Compare commits
179 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e59df1f8 | ||
|
|
c797944923 | ||
|
|
ade4e67b51 | ||
|
|
656f49f2ff | ||
|
|
0045244295 | ||
|
|
6bfb704f6f | ||
|
|
80cebdefcd | ||
|
|
68cd863fe0 | ||
|
|
65e5015d19 | ||
|
|
c26665ec4d | ||
|
|
91d82ebf4b | ||
|
|
303e4baa58 | ||
|
|
3c953d47ca | ||
|
|
5e629d5c09 | ||
|
|
c6ec2d4282 | ||
|
|
66b93a9af8 | ||
|
|
8d5479f55e | ||
|
|
96ce6c9504 | ||
|
|
0d55865545 | ||
|
|
a1fc383e6f | ||
|
|
c3807e175d | ||
|
|
6f83f76d41 | ||
|
|
9a56d619af | ||
|
|
f692d586f7 | ||
|
|
d3d3e99979 | ||
|
|
8e6a179efe | ||
|
|
17ff317d30 | ||
|
|
faef9f0049 | ||
|
|
bb0c831601 | ||
|
|
9462654738 | ||
|
|
e872169e4c | ||
|
|
a22404abe6 | ||
|
|
7c06313750 | ||
|
|
6f265f448d | ||
|
|
acdc41bd03 | ||
|
|
bcff2a7fb6 | ||
|
|
94188fddce | ||
|
|
3684e7f54a | ||
|
|
890181172f | ||
|
|
9c9d68561e | ||
|
|
1bd39ff935 | ||
|
|
17f3d2d581 | ||
|
|
55aa9e11db | ||
|
|
bc895eacc5 | ||
|
|
6c8eb4a19a | ||
|
|
887347106d | ||
|
|
419cf78984 | ||
|
|
aa339a8a9f | ||
|
|
a2f7aedd9c | ||
|
|
630379651e | ||
|
|
3d9b52fbc2 | ||
|
|
2e01c1f37e | ||
|
|
174abb352c | ||
|
|
85e028cab1 | ||
|
|
ff191c9404 | ||
|
|
31da01d4df | ||
|
|
6d45a94125 | ||
|
|
e7bfb04047 | ||
|
|
b9033d721c | ||
|
|
41c0343d33 | ||
|
|
aa8156a7fd | ||
|
|
e48adf7a07 | ||
|
|
8f214c51c0 | ||
|
|
096c4c78c7 | ||
|
|
257fce5a1b | ||
|
|
182bc7b8f9 | ||
|
|
3c35999246 | ||
|
|
340159b591 | ||
|
|
075fb2eaf2 | ||
|
|
21a2768ec3 | ||
|
|
554c840d4e | ||
|
|
9c28a1ba31 | ||
|
|
13fc921fa5 | ||
|
|
61f5d3972f | ||
|
|
5027bc743b | ||
|
|
9b8085220f | ||
|
|
54c04301cc | ||
|
|
cfd3bc823c | ||
|
|
329d95fd3a | ||
|
|
8dfef58f29 | ||
|
|
eeb4d3fe55 | ||
|
|
c6da4576b6 | ||
|
|
2417122ed3 | ||
|
|
e6c17e19d7 | ||
|
|
d98c2f89aa | ||
|
|
624991b9b7 | ||
|
|
c7ee776349 | ||
|
|
ffeacef394 | ||
|
|
f4ebec6759 | ||
|
|
93e3e4d2b1 | ||
|
|
3633049ba5 | ||
|
|
c566ed4643 | ||
|
|
af956f4d84 | ||
|
|
b70c72fc3b | ||
|
|
1f35694705 | ||
|
|
d912d96f00 | ||
|
|
94f8fb4a4b | ||
|
|
103744e2ca | ||
|
|
fe18a5de92 | ||
|
|
9b0394860d | ||
|
|
380c7628d8 | ||
|
|
f787a377c3 | ||
|
|
7c1b819728 | ||
|
|
8e5175e56b | ||
|
|
9e9d1a4e96 | ||
|
|
fd475423cf | ||
|
|
070911d458 | ||
|
|
3b585e6dbb | ||
|
|
2e893690bd | ||
|
|
d052b020fa | ||
|
|
ac6224563b | ||
|
|
a9630890fd | ||
|
|
4b889750db | ||
|
|
308bd0d81d | ||
|
|
d55a86e39b | ||
|
|
0c193c3ab7 | ||
|
|
6f513f5706 | ||
|
|
368bc91eed | ||
|
|
3a322c5c6e | ||
|
|
c5ee044343 | ||
|
|
19b918e56f | ||
|
|
cf5ed54c84 | ||
|
|
b813e1f7ab | ||
|
|
cdd8e52116 | ||
|
|
6945eb4186 | ||
|
|
1d9626d493 | ||
|
|
75b73f6821 | ||
|
|
f62f94381e | ||
|
|
cd6b3da665 | ||
|
|
25fb5d0ee6 | ||
|
|
65b2ca8f57 | ||
|
|
1ec07eb17a | ||
|
|
46fbf78da5 | ||
|
|
cea8d4a87d | ||
|
|
e07ba2c53d | ||
|
|
0af3f102aa | ||
|
|
a5b293401d | ||
|
|
05d0bda044 | ||
|
|
3dee3aba59 | ||
|
|
e732df46b8 | ||
|
|
86a8b231f4 | ||
|
|
10d359c222 | ||
|
|
1ef895e246 | ||
|
|
38ae370202 | ||
|
|
610a09817f | ||
|
|
c6938c9039 | ||
|
|
7a8fb8f430 | ||
|
|
3495591c5f | ||
|
|
050c31094b | ||
|
|
6a4668974b | ||
|
|
026d200add | ||
|
|
fe991ee767 | ||
|
|
b2a219f9d8 | ||
|
|
64810e0e0b | ||
|
|
6e5ed38b76 | ||
|
|
8d308ef2b8 | ||
|
|
ab76ae3778 | ||
|
|
222055fcff | ||
|
|
247d700c30 | ||
|
|
cf41d56c00 | ||
|
|
a8f7b1eb92 | ||
|
|
90d3ce4162 | ||
|
|
bc66b7f16e | ||
|
|
606708a96e | ||
|
|
2ec0d94c31 | ||
|
|
e6a17f78b6 | ||
|
|
d6b6d3f59f | ||
|
|
5932ddb0fe | ||
|
|
d1e5c2f86f | ||
|
|
1f2f25f7a3 | ||
|
|
b0edbf2857 | ||
|
|
91f0da9dcd | ||
|
|
3d5d60bc5b | ||
|
|
5c5599592a | ||
|
|
c60d09f3b2 | ||
|
|
5768c54c5b | ||
|
|
6d413e2492 | ||
|
|
331675d413 | ||
|
|
2105940286 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,7 +22,7 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
|
|
||||||
**Environment details**
|
**Environment details**
|
||||||
```
|
```
|
||||||
Press Ctrl+Shift+F6 (cmd+option+, on macOS) in kitty, to copy debug output about kitty and its
|
Press Ctrl+Shift+F6 (cmd+option+comma on macOS) in kitty, to copy debug output about kitty and its
|
||||||
configuration to the clipboard and paste it here.
|
configuration to the clipboard and paste it here.
|
||||||
|
|
||||||
On older versions of kitty, run kitty --debug-config instead
|
On older versions of kitty, run kitty --debug-config instead
|
||||||
|
|||||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -76,7 +76,7 @@ jobs:
|
|||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
|
|
||||||
- name: Install build-only deps
|
- name: Install build-only deps
|
||||||
run: pip install flake8 mypy types-requests types-docutils sphinx
|
run: pip install -r docs/requirements.txt flake8 mypy types-requests types-docutils
|
||||||
|
|
||||||
- name: Run pyflakes
|
- name: Run pyflakes
|
||||||
run: python -m flake8 --count .
|
run: python -m flake8 --count .
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
See https://sw.kovidgoyal.net/kitty/changelog.html
|
See https://sw.kovidgoyal.net/kitty/changelog/
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ config to reproduce the issue with).
|
|||||||
|
|
||||||
### Contributing code
|
### Contributing code
|
||||||
|
|
||||||
Install [the dependencies](https://sw.kovidgoyal.net/kitty/build.html#dependencies)
|
Install [the dependencies](https://sw.kovidgoyal.net/kitty/build/#dependencies)
|
||||||
using your favorite package manager. Build and run kitty [from
|
using your favorite package manager. Build and run kitty [from
|
||||||
source](https://sw.kovidgoyal.net/kitty/build.html#install-and-run-from-source).
|
source](https://sw.kovidgoyal.net/kitty/build/#install-and-run-from-source).
|
||||||
|
|
||||||
Make a fork, submit your Pull Request. If it's a large/controversial change, open an issue
|
Make a fork, submit your Pull Request. If it's a large/controversial change, open an issue
|
||||||
beforehand to discuss it, so that you don't waste your time making a pull
|
beforehand to discuss it, so that you don't waste your time making a pull
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
To build from source: <https://sw.kovidgoyal.net/kitty/build.html>
|
To build from source: <https://sw.kovidgoyal.net/kitty/build/>
|
||||||
|
|
||||||
Pre-built binaries: <https://sw.kovidgoyal.net/kitty/binary.html>
|
Pre-built binaries: <https://sw.kovidgoyal.net/kitty/binary/>
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -40,4 +40,11 @@ html:
|
|||||||
linkcheck:
|
linkcheck:
|
||||||
$(MAKE) FAIL_WARN=$(FAIL_WARN) -C docs linkcheck
|
$(MAKE) FAIL_WARN=$(FAIL_WARN) -C docs linkcheck
|
||||||
|
|
||||||
|
website:
|
||||||
|
./publish.py --only website
|
||||||
|
|
||||||
docs: man html
|
docs: man html
|
||||||
|
|
||||||
|
|
||||||
|
develop-docs:
|
||||||
|
$(MAKE) -C docs develop-docs
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ See https://sw.kovidgoyal.net/kitty/[the kitty website].
|
|||||||
|
|
||||||
image:https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg["Build status", link="https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI"]
|
image:https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg["Build status", link="https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI"]
|
||||||
|
|
||||||
https://sw.kovidgoyal.net/kitty/faq.html[Frequently Asked Questions]
|
https://sw.kovidgoyal.net/kitty/faq/[Frequently Asked Questions]
|
||||||
|
|
||||||
To ask other questions about kitty usage, use either the https://github.com/kovidgoyal/kitty/discussions/[discussions on GitHub] or the
|
To ask other questions about kitty usage, use either the https://github.com/kovidgoyal/kitty/discussions/[discussions on GitHub] or the
|
||||||
https://www.reddit.com/r/KittyTerminal[Reddit community]
|
https://www.reddit.com/r/KittyTerminal[Reddit community]
|
||||||
|
|||||||
13
__main__.py
13
__main__.py
@@ -49,13 +49,22 @@ def complete(args: List[str]) -> None:
|
|||||||
def launch(args: List[str]) -> None:
|
def launch(args: List[str]) -> None:
|
||||||
import runpy
|
import runpy
|
||||||
sys.argv = args[1:]
|
sys.argv = args[1:]
|
||||||
exe = args[1]
|
try:
|
||||||
|
exe = args[1]
|
||||||
|
except IndexError:
|
||||||
|
raise SystemExit(
|
||||||
|
'usage: kitty +launch script.py [arguments to be passed to script.py ...]\n\n'
|
||||||
|
'script.py will be run with full access to kitty code. If script.py is '
|
||||||
|
'prefixed with a : it will be searched for in PATH'
|
||||||
|
)
|
||||||
if exe.startswith(':'):
|
if exe.startswith(':'):
|
||||||
import shutil
|
import shutil
|
||||||
q = shutil.which(exe[1:])
|
q = shutil.which(exe[1:])
|
||||||
if not q:
|
if not q:
|
||||||
raise SystemExit('{} not found in PATH'.format(args[1][1:]))
|
raise SystemExit(f'{exe[1:]} not found in PATH')
|
||||||
exe = q
|
exe = q
|
||||||
|
if not os.path.exists(exe):
|
||||||
|
raise SystemExit(f'{exe} does not exist')
|
||||||
runpy.run_path(exe, run_name='__main__')
|
runpy.run_path(exe, run_name='__main__')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ def copy_libs(env):
|
|||||||
for x in binary_includes():
|
for x in binary_includes():
|
||||||
dest = env.bin_dir if '/bin/' in x else env.lib_dir
|
dest = env.bin_dir if '/bin/' in x else env.lib_dir
|
||||||
shutil.copy2(x, dest)
|
shutil.copy2(x, dest)
|
||||||
|
dest = os.path.join(dest, os.path.basename(x))
|
||||||
|
subprocess.check_call(['chrpath', '-d', dest])
|
||||||
|
|
||||||
|
|
||||||
def copy_python(env):
|
def copy_python(env):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
SPHINXOPTS = -j auto -T $(FAIL_WARN)
|
SPHINXOPTS = -n -q -j auto -T $(FAIL_WARN) $(OPTS)
|
||||||
SPHINXBUILD = sphinx-build
|
SPHINXBUILD = sphinx-build
|
||||||
SPHINXPROJ = kitty
|
SPHINXPROJ = kitty
|
||||||
SOURCEDIR = .
|
SOURCEDIR = .
|
||||||
@@ -18,3 +18,7 @@ help:
|
|||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
%: Makefile
|
%: Makefile
|
||||||
$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
|
||||||
|
develop-docs:
|
||||||
|
sphinx-autobuild --ignore "$(abspath $(SOURCEDIR))/generated/*" --watch ../kitty --watch ../kittens -b dirhtml "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
|
||||||
|
|||||||
113
docs/_static/custom.css
vendored
113
docs/_static/custom.css
vendored
@@ -5,122 +5,15 @@
|
|||||||
* Distributed under terms of the MIT license.
|
* Distributed under terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.float-left-img {
|
.sidebar-logo {
|
||||||
float: left;
|
max-height: 128px;
|
||||||
margin-right: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.float-right-img { float: right; margin-left: 1em; margin-bottom: 1em }
|
|
||||||
|
|
||||||
.half-with-img { max-width: 50% }
|
|
||||||
|
|
||||||
.fit-img { max-width: 95% }
|
|
||||||
|
|
||||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre.pre {
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
a[href], input[type="submit"] { cursor: pointer; }
|
|
||||||
|
|
||||||
img[style] {
|
|
||||||
/* Used for :scale: images to have them render properly but still popup when clicked */
|
|
||||||
width: auto !important;
|
|
||||||
height: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none !important;
|
|
||||||
border-bottom: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body div.document {
|
|
||||||
margin-top: 1ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.major-features li {
|
.major-features li {
|
||||||
margin-top: 0.75ex;
|
|
||||||
margin-bottom: 0.75ex;
|
margin-bottom: 0.75ex;
|
||||||
}
|
|
||||||
|
|
||||||
.support-form input[type=submit] {
|
|
||||||
border-radius: 6px;
|
|
||||||
box-shadow: rgb(255, 246, 175) 0px 1px 0px 0px;
|
|
||||||
background: linear-gradient(rgb(255, 236, 100) 5%, rgb(255, 171, 35) 100%) rgb(255, 236, 100);
|
|
||||||
border: 1px solid rgb(255, 170, 34);
|
|
||||||
display: inline-block;
|
|
||||||
color: rgb(51, 51, 51);
|
|
||||||
font-family: Arial;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 6px 24px;
|
|
||||||
text-decoration: none;
|
|
||||||
text-shadow: rgb(255, 238, 102) 0px 1px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.support-form input[type=submit]:hover {
|
|
||||||
background: linear-gradient(rgb(255, 171, 35) 5%, rgb(255, 236, 100) 100%) rgb(255, 171, 35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.support-form input[type=submit]:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div.sphinxsidebar {
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
max-height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebartoc li {
|
|
||||||
margin-top: 0.75ex;
|
margin-top: 0.75ex;
|
||||||
margin-bottom: 0.75ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebartoc ul {
|
.sidebar-tree a.current {
|
||||||
list-style: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebartoc a[href]:hover {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.green {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cyan {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.env {
|
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.italic {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: larger;
|
|
||||||
font-weight: bold
|
|
||||||
}
|
|
||||||
|
|||||||
57
docs/_static/custom.js
vendored
Normal file
57
docs/_static/custom.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* vim:fileencoding=utf-8
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPLv3 license
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function get_sidebar_tree() {
|
||||||
|
return document.querySelector('.sidebar-tree');
|
||||||
|
}
|
||||||
|
|
||||||
|
function scroll_sidebar_node_into_view(a) {
|
||||||
|
var ss = get_sidebar_tree().closest('.sidebar-scroll');
|
||||||
|
if (!ss || !a) return;
|
||||||
|
ss.style.position = 'relative';
|
||||||
|
var pos = 0;
|
||||||
|
while (true) {
|
||||||
|
pos += a.offsetTop;
|
||||||
|
a = a.offsetParent;
|
||||||
|
if (!a || a == ss) break;
|
||||||
|
}
|
||||||
|
ss.scrollTop = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mark_current_link(sidebar_tree, a, onload) {
|
||||||
|
var li = a.closest('li.has-children');
|
||||||
|
while (li) {
|
||||||
|
li.querySelector('input[type=checkbox]').setAttribute('checked', 'checked');
|
||||||
|
li = li.parentNode.closest('li.has-children');
|
||||||
|
}
|
||||||
|
sidebar_tree.querySelectorAll('.current').forEach(function (elem) {
|
||||||
|
elem.classList.remove('current');
|
||||||
|
});
|
||||||
|
if (onload) scroll_sidebar_node_into_view(a);
|
||||||
|
a.classList.add('current');
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_hash_in_sidebar(onload) {
|
||||||
|
var sidebar_tree = document.querySelector('.sidebar-tree');
|
||||||
|
if (document.location.hash.length > 1) {
|
||||||
|
var a = sidebar_tree.querySelector('a[href="' + document.location.hash + '"]');
|
||||||
|
if (a) mark_current_link(sidebar_tree, a, onload);
|
||||||
|
} else {
|
||||||
|
if (onload) scroll_sidebar_node_into_view(sidebar_tree.querySelector('.current-page a'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
show_hash_in_sidebar(true);
|
||||||
|
window.addEventListener('hashchange', show_hash_in_sidebar.bind(null, false));
|
||||||
|
});
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
||||||
22
docs/_templates/base.html
vendored
Normal file
22
docs/_templates/base.html
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends "!base.html" %}
|
||||||
|
{% block extrahead %}
|
||||||
|
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
{%- if analytics_id %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _gaq = _gaq || [];
|
||||||
|
_gaq.push(['_setAccount', '{{ analytics_id }}']);
|
||||||
|
_gaq.push(['_setDomainName', 'none']);
|
||||||
|
_gaq.push(['_setAllowLinker', true]);
|
||||||
|
_gaq.push(['_trackPageview']);
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||||
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||||
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
6
docs/_templates/layout.html
vendored
6
docs/_templates/layout.html
vendored
@@ -1,6 +0,0 @@
|
|||||||
{% extends "!layout.html" %}
|
|
||||||
|
|
||||||
{%- block extrahead %}
|
|
||||||
<!-- kitty analytics placeholder -->
|
|
||||||
{{ super() }}
|
|
||||||
{% endblock %}
|
|
||||||
6
docs/_templates/localtoc.html
vendored
6
docs/_templates/localtoc.html
vendored
@@ -1,6 +0,0 @@
|
|||||||
{%- if display_toc %}
|
|
||||||
<div> </div>
|
|
||||||
<div id="sidebartoc">
|
|
||||||
{{ toc }}
|
|
||||||
</div>
|
|
||||||
{%- endif %}
|
|
||||||
22
docs/_templates/searchbox.html
vendored
22
docs/_templates/searchbox.html
vendored
@@ -1,22 +0,0 @@
|
|||||||
{#
|
|
||||||
basic/searchbox.html
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Sphinx sidebar template: quick search box.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
#}
|
|
||||||
{%- if pagename != "search" and builder != "singlehtml" %}
|
|
||||||
<div id="searchbox" style="display: none" role="search">
|
|
||||||
<div class="searchformwrapper">
|
|
||||||
<form class="search" action="{{ pathto('search') }}" method="get">
|
|
||||||
<input type="text" name="q" placeholder="{{ _('Search') }}" />
|
|
||||||
<input type="submit" value="{{ _('Go') }}" style="cursor: pointer" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
{%- endif %}
|
|
||||||
7
docs/_templates/support.html
vendored
7
docs/_templates/support.html
vendored
@@ -1,7 +0,0 @@
|
|||||||
{% if pagename != "support" %}
|
|
||||||
<div id="support" style="text-align: center">
|
|
||||||
<form class="support-form" action="{{ pathto('support') }}" title="{{ _('Donate to support kitty development') }}">
|
|
||||||
<input type="submit" value="{{ _('Support kitty') }}">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
9
docs/actions.rst
Normal file
9
docs/actions.rst
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Mappable actions
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. highlight:: conf
|
||||||
|
|
||||||
|
The actions described below can be mapped to any key press or mouse action
|
||||||
|
using the ``map`` and ``mouse_map`` directives in :file:`kitty.conf`.
|
||||||
|
|
||||||
|
.. include:: /generated/actions.rst
|
||||||
@@ -83,6 +83,10 @@ move it to another tab or another OS window::
|
|||||||
map ctrl+f2 detach_window
|
map ctrl+f2 detach_window
|
||||||
# moves the window into a new Tab
|
# moves the window into a new Tab
|
||||||
map ctrl+f3 detach_window new-tab
|
map ctrl+f3 detach_window new-tab
|
||||||
|
# moves the window into the previously active tab
|
||||||
|
map ctrl+f3 detach_window tab-prev
|
||||||
|
# moves the window into the tab at the left of the active tab
|
||||||
|
map ctrl+f3 detach_window tab-left
|
||||||
# asks which tab to move the window into
|
# asks which tab to move the window into
|
||||||
map ctrl+f4 detach_window ask
|
map ctrl+f4 detach_window ask
|
||||||
|
|
||||||
@@ -102,6 +106,9 @@ the currently active window::
|
|||||||
Other keyboard shortcuts
|
Other keyboard shortcuts
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
|
The full list of actions that can be mapped to key presses is available
|
||||||
|
:doc:`here </actions>`.
|
||||||
|
|
||||||
================================== =======================
|
================================== =======================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
================================== =======================
|
================================== =======================
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
kitty - Binary install
|
Install kitty
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
Binary install
|
||||||
|
----------------
|
||||||
|
|
||||||
.. |ins| replace:: curl -L :literal:`https://sw.kovidgoyal.net/kitty/installer.sh` | sh /dev/stdin
|
.. |ins| replace:: curl -L :literal:`https://sw.kovidgoyal.net/kitty/installer.sh` | sh /dev/stdin
|
||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Building kitty from source
|
Build from source
|
||||||
==============================
|
==================
|
||||||
|
|
||||||
.. image:: https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg
|
.. image:: https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg
|
||||||
:alt: Build status
|
:alt: Build status
|
||||||
@@ -25,24 +25,27 @@ Dependencies
|
|||||||
|
|
||||||
Run-time dependencies:
|
Run-time dependencies:
|
||||||
|
|
||||||
* python >= 3.6
|
* ``python`` >= 3.6
|
||||||
* harfbuzz >= 2.2.0
|
* ``harfbuzz`` >= 2.2.0
|
||||||
* zlib
|
* ``zlib``
|
||||||
* libpng
|
* ``libpng``
|
||||||
* liblcms2
|
* ``liblcms2``
|
||||||
* freetype (not needed on macOS)
|
* ``freetype`` (not needed on macOS)
|
||||||
* fontconfig (not needed on macOS)
|
* ``fontconfig`` (not needed on macOS)
|
||||||
* libcanberra (not needed on macOS)
|
* ``libcanberra`` (not needed on macOS)
|
||||||
* ImageMagick (optional, needed to use the ``kitty +kitten icat`` tool to display images in the terminal)
|
* ``ImageMagick`` (optional, needed to use the ``kitty +kitten icat`` tool to display images in the terminal)
|
||||||
* pygments (optional, need for syntax highlighting in ``kitty +kitten diff``)
|
* ``pygments`` (optional, needed for syntax highlighting in ``kitty +kitten diff``)
|
||||||
|
|
||||||
|
|
||||||
Build-time dependencies:
|
Build-time dependencies:
|
||||||
|
|
||||||
* gcc or clang
|
* ``gcc`` or ``clang``
|
||||||
* pkg-config
|
* ``pkg-config``
|
||||||
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
|
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
|
||||||
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libx11-xcb-dev``, ``liblcms2-dev``, and ``libpython3-dev``,
|
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``,
|
||||||
if they are not already installed by your distro.
|
``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libx11-xcb-dev``,
|
||||||
|
``liblcms2-dev``, and ``libpython3-dev``, if they are not already installed by your distro.
|
||||||
|
|
||||||
|
|
||||||
Install and run from source
|
Install and run from source
|
||||||
------------------------------
|
------------------------------
|
||||||
@@ -78,8 +81,8 @@ you might have to rebuild the app.
|
|||||||
.. note::
|
.. note::
|
||||||
The released :file:`kitty.dmg` includes all dependencies, unlike the
|
The released :file:`kitty.dmg` includes all dependencies, unlike the
|
||||||
:file:`kitty.app` built above and is built automatically by using the
|
:file:`kitty.app` built above and is built automatically by using the
|
||||||
<https://github.com/kovidgoyal/bypy>`_ however, that is designed to
|
`bypy framework <https://github.com/kovidgoyal/bypy>`_ however, that is
|
||||||
run on Linux and is not for the faint of heart.
|
designed to run on Linux and is not for the faint of heart.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -128,18 +131,19 @@ This allows users to install the terminfo file on servers into which they ssh,
|
|||||||
without needing to install all of |kitty|.
|
without needing to install all of |kitty|.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
You need a couple of extra dependencies to build linux-package.
|
You need a couple of extra dependencies to build linux-package.
|
||||||
:file:`tic` to compile terminfo files, usually found in the
|
:file:`tic` to compile terminfo files, usually found in the
|
||||||
development package of :file:`ncurses`. Also, if you are building from
|
development package of :file:`ncurses`. Also, if you are building from
|
||||||
a git checkout instead of the released source code tarball, you will
|
a git checkout instead of the released source code tarball, you will
|
||||||
need :file:`sphinx-build` from the `Sphinx documentation generator
|
need to install the dependencies from ``docs/requirements.txt`` to
|
||||||
<https://www.sphinx-doc.org/>`_.
|
build the kitty documentation. They can be installed most easily with
|
||||||
|
``python -m pip -r docs/requirements.txt``.
|
||||||
|
|
||||||
This applies to creating packages for |kitty| for macOS package managers such as
|
This applies to creating packages for |kitty| for macOS package managers such as
|
||||||
brew or MacPorts as well.
|
brew or MacPorts as well.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|kitty| has its own update check mechanism, if you would like to turn
|
|kitty| has its own update check mechanism, if you would like to turn
|
||||||
it off for your package, use
|
it off for your package, use
|
||||||
``python3 setup.py linux-package --update-check-interval=0``
|
``python3 setup.py linux-package --update-check-interval=0``
|
||||||
|
|||||||
@@ -4,6 +4,110 @@ Changelog
|
|||||||
|kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal.
|
|kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal.
|
||||||
To update |kitty|, :doc:`follow the instructions <binary>`.
|
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||||
|
|
||||||
|
0.22.2 [2021-08-02]
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- macOS: Fix a long standing bug that could cause kitty windows to stop
|
||||||
|
updating, that got worse in the previous release (:iss:`3890` and
|
||||||
|
:iss:`2016`)
|
||||||
|
|
||||||
|
- Wayland: A better fix for compositors like sway that can toggle client side
|
||||||
|
decorations on and off (:iss:`3888`)
|
||||||
|
|
||||||
|
|
||||||
|
0.22.1 [2021-07-31]
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- Fix a regression in the previous release that broke ``kitty --help`` (:iss:`3869`)
|
||||||
|
|
||||||
|
- Graphics protocol: Fix composing onto currently displayed frame not updating the frame on the GPU (:iss:`3874`)
|
||||||
|
|
||||||
|
- Fix switching to previously active tab after detaching a tab not working (:pull:`3871`)
|
||||||
|
|
||||||
|
- macOS: Fix an error on Apple silicon when enumerating monitors (:pull:`3875`)
|
||||||
|
|
||||||
|
- detach_window: Allow specifying the previously active tab or the tab to the left/right of
|
||||||
|
the active tab (:disc:`3877`)
|
||||||
|
|
||||||
|
- broadcast kitten: Fix a regression in ``0.20.0`` that broke sending of some
|
||||||
|
keys, such as backspace
|
||||||
|
|
||||||
|
- Linux binary: Remove any RPATH build artifacts from bundled libraries
|
||||||
|
|
||||||
|
- Wayland: If the compositor turns off server side decorations after turning
|
||||||
|
them on do not draw client side decorations (:iss:`3888`)
|
||||||
|
|
||||||
|
|
||||||
|
0.22.0 [2021-07-26]
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- Add a new :ref:`action-toggle_layout` action to easily zoom/unzoom a window
|
||||||
|
|
||||||
|
- When right clicking to extend a selection, move the nearest selection
|
||||||
|
boundary rather than the end of the selection. To restore previous behavior
|
||||||
|
use ``mouse_map right press ungrabbed mouse_selection move-end``.
|
||||||
|
|
||||||
|
- When opening hyperlinks, allow defining open actions for directories
|
||||||
|
(:pull:`3836`)
|
||||||
|
|
||||||
|
- When using the OSC 52 escape code to copy to clipboard allow large
|
||||||
|
copies (up to 8MB) without needing a kitty specific chunking protocol.
|
||||||
|
Note that if you used the chunking protocol in the past, it will no longer
|
||||||
|
work and you should switch to using the unmodified protocol which has the
|
||||||
|
advantage of working with all terminal emulators.
|
||||||
|
|
||||||
|
- Fix a bug in the implementation of the synchronized updates escape code that
|
||||||
|
could cause incorrect parsing if either the pending buffer capacity or the
|
||||||
|
pending timeout were exceeded (:iss:`3779`)
|
||||||
|
|
||||||
|
- A new remote control command to :program:`resize the OS Window <kitty @
|
||||||
|
resize-os-window>`
|
||||||
|
|
||||||
|
- Graphics protocol: Add support for composing rectangles from one animation
|
||||||
|
frame onto another (:iss:`3809`)
|
||||||
|
|
||||||
|
- diff kitten: Remove limit on max line length of 4096 characters (:iss:`3806`)
|
||||||
|
|
||||||
|
- Fix turning off cursor blink via escape codes not working (:iss:`3808`)
|
||||||
|
|
||||||
|
- Allow using neighboring window operations in the stack layout. The previous
|
||||||
|
window is considered the left and top neighbor and the next window is
|
||||||
|
considered the bottom and right neighbor (:iss:`3778`)
|
||||||
|
|
||||||
|
- macOS: Render colors in the sRGB colorspace to match other macOS terminal
|
||||||
|
applications (:iss:`2249`)
|
||||||
|
|
||||||
|
- Add a new variable ``{num_window_groups}`` for the :opt:`tab_title_template`
|
||||||
|
(:iss:`3837`)
|
||||||
|
|
||||||
|
- Wayland: Fix :opt:`initial_window_width/height <remember_window_size>` specified
|
||||||
|
in cells not working on High DPI screens (:iss:`3834`)
|
||||||
|
|
||||||
|
- A new theme for the kitty website with support for dark mode.
|
||||||
|
|
||||||
|
- Render ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ with spaces at the edges. Matches rendering in
|
||||||
|
most other programs and allows long chains of them to look better
|
||||||
|
(:iss:`3844`)
|
||||||
|
|
||||||
|
- hints kitten: Detect paths and hashes that appear over multiple lines.
|
||||||
|
Note that this means that all line breaks in the text are no longer \n
|
||||||
|
soft breaks are instead \r. If you use a custom regular expression that
|
||||||
|
is meant to match over line breaks, you will need to match over both.
|
||||||
|
(:iss:`3845`)
|
||||||
|
|
||||||
|
- Allow leading or trailing spaces in :opt:`tab_activity_symbol`
|
||||||
|
|
||||||
|
- Fix mouse actions not working when caps lock or num lock are engaged
|
||||||
|
(:iss:`3859`)
|
||||||
|
|
||||||
|
- macOS: Fix automatic detection of bold/italic faces for fonts that
|
||||||
|
use the family name as the full face name of the regular font not working
|
||||||
|
(:iss:`3861`)
|
||||||
|
|
||||||
|
- clipboard kitten: fix copies to clipboard not working without the
|
||||||
|
:option:`kitty +kitten clipboard --wait-for-completion` option
|
||||||
|
|
||||||
|
|
||||||
0.21.2 [2021-06-28]
|
0.21.2 [2021-06-28]
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@@ -1682,8 +1786,7 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
|||||||
using standard keyboards) via `IBus
|
using standard keyboards) via `IBus
|
||||||
<https://github.com/ibus/ibus/wiki/ReadMe>`_ (:iss:`469`)
|
<https://github.com/ibus/ibus/wiki/ReadMe>`_ (:iss:`469`)
|
||||||
|
|
||||||
- Implement completion for the kitty command in bash and zsh. See
|
- Implement completion for the kitty command in bash and zsh
|
||||||
:ref:`completion`.
|
|
||||||
|
|
||||||
- Render the text under the cursor in a fixed color, configurable via
|
- Render the text under the cursor in a fixed color, configurable via
|
||||||
the option :opt:`cursor_text_color` (:iss:`126`)
|
the option :opt:`cursor_text_color` (:iss:`126`)
|
||||||
|
|||||||
26
docs/color-stack.rst
Normal file
26
docs/color-stack.rst
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Saving and restoring colors
|
||||||
|
==============================
|
||||||
|
|
||||||
|
It is often useful for a full screen application with its own color themes to
|
||||||
|
set the default foreground, background, selection and cursor colors and the
|
||||||
|
ANSI color table. This allows for various performance optimizations when
|
||||||
|
drawing the screen. The problem is that if the user previously used the escape
|
||||||
|
codes to change these colors herself, then running the full screen application
|
||||||
|
will lose her changes even after it exits. To avoid this, kitty introduces a
|
||||||
|
new pair of *OSC* escape codes to push and pop the current color values from a
|
||||||
|
stack::
|
||||||
|
|
||||||
|
<ESC>]30001<ESC>\ # push onto stack
|
||||||
|
<ESC>]30101<ESC>\ # pop from stack
|
||||||
|
|
||||||
|
These escape codes save/restore the colors, default
|
||||||
|
background, default foreground, selection background, selection foreground and
|
||||||
|
cursor color and the 256 colors of the ANSI color table.
|
||||||
|
|
||||||
|
.. note:: In July 2020, after several years, XTerm copied this protocol
|
||||||
|
extension, without acknowledgement, and using incompatible escape codes
|
||||||
|
(XTPUSHCOLORS, XTPOPCOLORS, XTREPORTCOLORS). And they decided to save not
|
||||||
|
just the dynamic colors but the entire ANSI color table. In the interests of
|
||||||
|
promoting interoperability, kitty added support for XTerm's escape codes as
|
||||||
|
well, and changed this extension to also save/restore the entire ANSI color
|
||||||
|
table.
|
||||||
105
docs/conf.py
105
docs/conf.py
@@ -22,7 +22,6 @@ from pygments.token import ( # type: ignore
|
|||||||
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
||||||
)
|
)
|
||||||
from sphinx import addnodes, version_info # type: ignore
|
from sphinx import addnodes, version_info # type: ignore
|
||||||
from sphinx.environment.adapters.toctree import TocTree # type: ignore
|
|
||||||
from sphinx.util.logging import getLogger # type: ignore
|
from sphinx.util.logging import getLogger # type: ignore
|
||||||
|
|
||||||
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
@@ -30,7 +29,7 @@ if kitty_src not in sys.path:
|
|||||||
sys.path.insert(0, kitty_src)
|
sys.path.insert(0, kitty_src)
|
||||||
|
|
||||||
from kitty.conf.types import Definition # noqa
|
from kitty.conf.types import Definition # noqa
|
||||||
from kitty.constants import str_version # noqa
|
from kitty.constants import str_version, website_url # noqa
|
||||||
|
|
||||||
# config {{{
|
# config {{{
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
@@ -60,8 +59,14 @@ extensions = [
|
|||||||
'sphinx.ext.ifconfig',
|
'sphinx.ext.ifconfig',
|
||||||
'sphinx.ext.viewcode',
|
'sphinx.ext.viewcode',
|
||||||
'sphinx.ext.githubpages',
|
'sphinx.ext.githubpages',
|
||||||
|
'sphinx_copybutton',
|
||||||
|
'sphinx_inline_tabs',
|
||||||
|
"sphinxext.opengraph",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# URL for OpenGraph tags
|
||||||
|
ogp_site_url = website_url()
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
|
|
||||||
@@ -85,13 +90,10 @@ language: Optional[str] = None
|
|||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
# This pattern also affects html_static_path and html_extra_path .
|
# This pattern also affects html_static_path and html_extra_path .
|
||||||
exclude_patterns = [
|
exclude_patterns = [
|
||||||
'_build', 'Thumbs.db', '.DS_Store',
|
'_build', 'Thumbs.db', '.DS_Store', 'basic.rst',
|
||||||
'generated/cli-*.rst', 'generated/conf-*.rst'
|
'generated/cli-*.rst', 'generated/conf-*.rst', 'generated/actions.rst'
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
rst_prolog = '''
|
rst_prolog = '''
|
||||||
.. |kitty| replace:: *kitty*
|
.. |kitty| replace:: *kitty*
|
||||||
.. |version| replace:: VERSION
|
.. |version| replace:: VERSION
|
||||||
@@ -101,7 +103,6 @@ rst_prolog = '''
|
|||||||
.. role:: bold
|
.. role:: bold
|
||||||
.. role:: cyan
|
.. role:: cyan
|
||||||
.. role:: title
|
.. role:: title
|
||||||
.. role:: env
|
|
||||||
|
|
||||||
'''.replace('VERSION', str_version)
|
'''.replace('VERSION', str_version)
|
||||||
|
|
||||||
@@ -111,32 +112,26 @@ rst_prolog = '''
|
|||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = 'alabaster'
|
html_theme = 'furo'
|
||||||
|
html_title = 'kitty'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
#
|
#
|
||||||
html_theme_options = {
|
html_theme_options: Dict[str, Any] = {
|
||||||
'logo': 'kitty.png',
|
'sidebar_hide_name': True,
|
||||||
'show_powered_by': False,
|
'navigation_with_keys': True,
|
||||||
'fixed_sidebar': True,
|
|
||||||
'sidebar_collapse': True,
|
|
||||||
'github_button': False,
|
|
||||||
'github_banner': True,
|
|
||||||
'github_user': 'kovidgoyal',
|
|
||||||
'github_repo': 'kitty',
|
|
||||||
# increase contrast of link color with text color
|
|
||||||
'link': '#00587d',
|
|
||||||
'link_hover': 'green',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ['_static', '../logo/kitty.png']
|
html_static_path = ['_static']
|
||||||
html_favicon = '../logo/kitty.png'
|
html_favicon = html_logo = '../logo/kitty.svg'
|
||||||
|
html_css_files = ['custom.css']
|
||||||
|
html_js_files = ['custom.js']
|
||||||
|
|
||||||
# Custom sidebar templates, must be a dictionary that maps document names
|
# Custom sidebar templates, must be a dictionary that maps document names
|
||||||
# to template names.
|
# to template names.
|
||||||
@@ -146,17 +141,9 @@ html_favicon = '../logo/kitty.png'
|
|||||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||||
# 'searchbox.html']``.
|
# 'searchbox.html']``.
|
||||||
#
|
#
|
||||||
html_sidebars = {
|
|
||||||
'**': [
|
|
||||||
'about.html',
|
|
||||||
'support.html',
|
|
||||||
'searchbox.html',
|
|
||||||
'localtoc.html',
|
|
||||||
'relations.html',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
html_show_sourcelink = False
|
html_show_sourcelink = False
|
||||||
|
html_show_sphinx = False
|
||||||
|
manpages_url = 'https://man7.org/linux/man-pages/man{section}/{page}.{section}.html'
|
||||||
|
|
||||||
# -- Options for manual page output ------------------------------------------
|
# -- Options for manual page output ------------------------------------------
|
||||||
|
|
||||||
@@ -220,28 +207,6 @@ def commit_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, o
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Sidebar ToC {{{
|
|
||||||
def create_toc(app: Any, pagename: str) -> Optional[Any]:
|
|
||||||
tt = TocTree(app.env)
|
|
||||||
toctree = tt.get_toc_for(pagename, app.builder)
|
|
||||||
if toctree is not None:
|
|
||||||
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
|
||||||
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
|
||||||
if bl is None:
|
|
||||||
return None # Empty ToC
|
|
||||||
subtree = subtree[bl]
|
|
||||||
# for li in subtree.traverse(nodes.list_item):
|
|
||||||
# modify_li(li)
|
|
||||||
# subtree['ids'] = [ID]
|
|
||||||
return app.builder.render_partial(subtree)['fragment']
|
|
||||||
|
|
||||||
|
|
||||||
def add_html_context(app: Any, pagename: str, templatename: str, context: Any, *args: Any) -> None:
|
|
||||||
if 'toc' in context:
|
|
||||||
context['toc'] = create_toc(app, pagename) or context['toc']
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
# CLI docs {{{
|
# CLI docs {{{
|
||||||
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
||||||
from kitty.cli import option_spec_as_rst
|
from kitty.cli import option_spec_as_rst
|
||||||
@@ -281,6 +246,11 @@ if you specify a program-to-run you can use the special placeholder
|
|||||||
with open(f'generated/cli-kitten-{kitten}.rst', 'w') as f:
|
with open(f'generated/cli-kitten-{kitten}.rst', 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('.. program::', f'kitty +kitten {kitten}')
|
p('.. program::', f'kitty +kitten {kitten}')
|
||||||
|
p(f'\nSource code for {kitten}')
|
||||||
|
p('-' * 72)
|
||||||
|
p(f'\nThe source code for this kitten is `available on GitHub <https://github.com/kovidgoyal/kitty/tree/master/kittens/{kitten}>`_.')
|
||||||
|
p('\nCommand Line Interface')
|
||||||
|
p('-' * 72, file=f)
|
||||||
p('\n\n' + option_spec_as_rst(
|
p('\n\n' + option_spec_as_rst(
|
||||||
data['options'], message=data['help_text'], usage=data['usage'], appname=f'kitty +kitten {kitten}',
|
data['options'], message=data['help_text'], usage=data['usage'], appname=f'kitty +kitten {kitten}',
|
||||||
heading_char='^'))
|
heading_char='^'))
|
||||||
@@ -347,6 +317,8 @@ class ConfLexer(RegexLexer):
|
|||||||
(r'(include)(\s+)(.+?)$', bygroups(Comment.Preproc, Whitespace, Name.Namespace)),
|
(r'(include)(\s+)(.+?)$', bygroups(Comment.Preproc, Whitespace, Name.Namespace)),
|
||||||
(r'(map)(\s+)(\S+)(\s+)', bygroups(
|
(r'(map)(\s+)(\S+)(\s+)', bygroups(
|
||||||
Keyword.Declaration, Whitespace, String, Whitespace), 'action'),
|
Keyword.Declaration, Whitespace, String, Whitespace), 'action'),
|
||||||
|
(r'(mouse_map)(\s+)(\S+)(\s+)(\S+)(\s+)(\S+)(\s+)', bygroups(
|
||||||
|
Keyword.Declaration, Whitespace, String, Whitespace, Name.Variable, Whitespace, String, Whitespace), 'action'),
|
||||||
(r'(symbol_map)(\s+)(\S+)(\s+)(.+?)$', bygroups(
|
(r'(symbol_map)(\s+)(\S+)(\s+)(.+?)$', bygroups(
|
||||||
Keyword.Declaration, Whitespace, String, Whitespace, Literal)),
|
Keyword.Declaration, Whitespace, String, Whitespace, Literal)),
|
||||||
(r'([a-zA-Z_0-9]+)(\s+)', bygroups(
|
(r'([a-zA-Z_0-9]+)(\s+)', bygroups(
|
||||||
@@ -510,9 +482,27 @@ def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
|
|||||||
definition = get_kitten_conf_docs(kitten)
|
definition = get_kitten_conf_docs(kitten)
|
||||||
if definition:
|
if definition:
|
||||||
generate_default_config(definition, f'kitten-{kitten}')
|
generate_default_config(definition, f'kitten-{kitten}')
|
||||||
|
|
||||||
|
from kitty.actions import as_rst
|
||||||
|
with open('generated/actions.rst', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(as_rst())
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
def add_html_context(app: Any, pagename: str, templatename: str, context: Any, doctree: Any, *args: Any) -> None:
|
||||||
|
context['analytics_id'] = app.config.analytics_id
|
||||||
|
if 'toctree' in context:
|
||||||
|
# this is needed with furo to use all titles from pages
|
||||||
|
# in the sidebar (global) toc
|
||||||
|
original_toctee_function = context['toctree']
|
||||||
|
|
||||||
|
def include_sub_headings(**kwargs: Any) -> Any:
|
||||||
|
kwargs['titles_only'] = False
|
||||||
|
return original_toctee_function(**kwargs)
|
||||||
|
|
||||||
|
context['toctree'] = include_sub_headings
|
||||||
|
|
||||||
|
|
||||||
def setup(app: Any) -> None:
|
def setup(app: Any) -> None:
|
||||||
os.makedirs('generated/conf', exist_ok=True)
|
os.makedirs('generated/conf', exist_ok=True)
|
||||||
from kittens.runner import all_kitten_names
|
from kittens.runner import all_kitten_names
|
||||||
@@ -520,10 +510,11 @@ def setup(app: Any) -> None:
|
|||||||
write_cli_docs(kn)
|
write_cli_docs(kn)
|
||||||
write_remote_control_protocol_docs()
|
write_remote_control_protocol_docs()
|
||||||
write_conf_docs(app, kn)
|
write_conf_docs(app, kn)
|
||||||
app.add_css_file('custom.css')
|
app.add_config_value('analytics_id', '', 'env')
|
||||||
|
app.connect('html-page-context', add_html_context)
|
||||||
app.add_lexer('session', SessionLexer() if version_info[0] < 3 else SessionLexer)
|
app.add_lexer('session', SessionLexer() if version_info[0] < 3 else SessionLexer)
|
||||||
app.add_role('link', link_role)
|
app.add_role('link', link_role)
|
||||||
app.add_role('iss', partial(num_role, 'issues'))
|
app.add_role('iss', partial(num_role, 'issues'))
|
||||||
app.add_role('pull', partial(num_role, 'pull'))
|
app.add_role('pull', partial(num_role, 'pull'))
|
||||||
|
app.add_role('disc', partial(num_role, 'discussions'))
|
||||||
app.add_role('commit', commit_role)
|
app.add_role('commit', commit_role)
|
||||||
app.connect('html-page-context', add_html_context)
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
:tocdepth: 2
|
kitty.conf
|
||||||
|
-----------------------
|
||||||
Configuring kitty
|
|
||||||
===============================
|
|
||||||
|
|
||||||
.. highlight:: conf
|
.. highlight:: conf
|
||||||
|
|
||||||
@@ -34,11 +32,15 @@ expanded, so :code:`${USER}.conf` becomes :file:`name.conf` if
|
|||||||
include other.conf
|
include other.conf
|
||||||
|
|
||||||
|
|
||||||
|
.. note:: Syntax highlighting for :file:`kitty.conf` in vim is available via
|
||||||
|
`vim-kitty <https://github.com/fladson/vim-kitty>`_.
|
||||||
|
|
||||||
|
|
||||||
.. include:: /generated/conf-kitty.rst
|
.. include:: /generated/conf-kitty.rst
|
||||||
|
|
||||||
|
|
||||||
Sample kitty.conf
|
Sample kitty.conf
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
--------------------
|
||||||
|
|
||||||
.. only:: html
|
.. only:: html
|
||||||
|
|
||||||
@@ -53,3 +55,14 @@ Sample kitty.conf
|
|||||||
file with full documentation and all settings commented out. If you
|
file with full documentation and all settings commented out. If you
|
||||||
have a pre-existing kitty.conf, then that will be used instead, delete
|
have a pre-existing kitty.conf, then that will be used instead, delete
|
||||||
it to see the sample file.
|
it to see the sample file.
|
||||||
|
|
||||||
|
|
||||||
|
All mappable actions
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
See the :doc:`list of all the things you can make kitty can do </actions>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
actions
|
||||||
|
|||||||
21
docs/deccara.rst
Normal file
21
docs/deccara.rst
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Setting text styles/colors in arbitrary regions of the screen
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
There already exists an escape code to set *some* text attributes in arbitrary
|
||||||
|
regions of the screen, `DECCARA
|
||||||
|
<https://vt100.net/docs/vt510-rm/DECCARA.html>`_. However, it is limited to
|
||||||
|
only a few attributes. |kitty| extends this to work with *all* SGR attributes.
|
||||||
|
So, for example, this can be used to set the background color in an arbitrary
|
||||||
|
region of the screen.
|
||||||
|
|
||||||
|
The motivation for this extension is the various problems with the existing
|
||||||
|
solution for erasing to background color, namely the *background color erase
|
||||||
|
(bce)* capability. See
|
||||||
|
`this discussion <https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545>`_
|
||||||
|
and `this FAQ <https://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`_
|
||||||
|
for a summary of problems with *bce*.
|
||||||
|
|
||||||
|
For example, to set the background color to blue in a
|
||||||
|
rectangular region of the screen from (3, 4) to (10, 11), you use::
|
||||||
|
|
||||||
|
<ESC>[2*x<ESC>[4;3;11;10;44$r<ESC>[*x
|
||||||
122
docs/desktop-notifications.rst
Normal file
122
docs/desktop-notifications.rst
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
.. _desktop_notifications:
|
||||||
|
|
||||||
|
|
||||||
|
Desktop notifications
|
||||||
|
=======================
|
||||||
|
|
||||||
|
|kitty| implements an extensible escape code (OSC 99) to show desktop
|
||||||
|
notifications. It is easy to use from shell scripts and fully extensible to
|
||||||
|
show title and body. Clicking on the notification can optionally focus the
|
||||||
|
window it came from, and/or send an escape code back to the application running
|
||||||
|
in that window.
|
||||||
|
|
||||||
|
The design of the escape code is partially based on the discussion in
|
||||||
|
the defunct
|
||||||
|
`terminal-wg <https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/13>`_
|
||||||
|
|
||||||
|
The escape code has the form::
|
||||||
|
|
||||||
|
<OSC> 99 ; metadata ; payload <terminator>
|
||||||
|
|
||||||
|
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is
|
||||||
|
:code:`<ESC><backslash>`. The metadata is a section of colon separated
|
||||||
|
:code:`key=value` pairs. Every key must be a single character from the set
|
||||||
|
:code:`a-zA-Z` and every value must be a word consisting of characters from
|
||||||
|
the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The payload must be
|
||||||
|
interpreted based on the metadata section. The two semi-colons *must* always be
|
||||||
|
present even when no metadata is present.
|
||||||
|
|
||||||
|
Before going into details, lets see how one can display a simple, single line
|
||||||
|
notification from a shell script::
|
||||||
|
|
||||||
|
printf '\x1b]99;;Hello world\x1b\\'
|
||||||
|
|
||||||
|
To show a message with a title and a body::
|
||||||
|
|
||||||
|
printf '\x1b]99;i=1:d=0;Hello world\x1b\\'
|
||||||
|
printf '\x1b]99;i=1:d=1:p=body;This is cool\x1b\\'
|
||||||
|
|
||||||
|
The most important key in the metadata is the ``p`` key, it controls how the
|
||||||
|
payload is interpreted. A value of ``title`` means the payload is setting the
|
||||||
|
title for the notification. A value of ``body`` means it is setting the body,
|
||||||
|
and so on, see the table below for full details.
|
||||||
|
|
||||||
|
The design of the escape code is fundamentally chunked, this is because
|
||||||
|
different terminal emulators have different limits on how large a single escape
|
||||||
|
code can be. Chunking is accomplished by the ``i`` and ``d`` keys. The ``i``
|
||||||
|
key is the *notification id* which can be any string containing the characters
|
||||||
|
``[a-zA-Z0-9_-+.]``. The ``d`` key stands for *done* and
|
||||||
|
can only take the values ``0`` and ``1``. A value of ``0`` means the
|
||||||
|
notification is not yet done and the terminal emulator should hold off
|
||||||
|
displaying it. A value of ``1`` means the notification is done, and should be
|
||||||
|
displayed. You can specify the title or body multiple times and the terminal
|
||||||
|
emulator will concatenate them, thereby allowing arbitrarily long text
|
||||||
|
(terminal emulators are free to impose a sensible limit to avoid
|
||||||
|
Denial-of-Service attacks).
|
||||||
|
|
||||||
|
Both the ``title`` and ``body`` payloads must be either UTF-8 encoded plain
|
||||||
|
text with no embedded escape codes, or UTF-8 text that is base64 encoded, in
|
||||||
|
which case there must be an ``e=1`` key in the metadata to indicate the payload
|
||||||
|
is base64 encoded.
|
||||||
|
|
||||||
|
When the user clicks the notification, a couple of things can happen, the
|
||||||
|
terminal emulator can focus the window from which the notification came, and/or
|
||||||
|
it can send back an escape code to the application indicating the notification
|
||||||
|
was activated. This is controlled by the ``a`` key which takes a comma
|
||||||
|
separated set of values, ``report`` and ``focus``. The value ``focus`` means
|
||||||
|
focus the window from which the notification was issued and is the default.
|
||||||
|
``report`` means send an escape code back to the application. The format of the
|
||||||
|
returned escape code is::
|
||||||
|
|
||||||
|
<OSC> 99 ; i=identifier ; <terminator>
|
||||||
|
|
||||||
|
The value of ``identifier`` comes from the ``i`` key in the escape code sent by
|
||||||
|
the application. If the application sends no identifier, then the terminal
|
||||||
|
*must* use ``i=0``. Actions can be preceded by a negative sign to turn them
|
||||||
|
off, so for example if you do not want any action, turn off the default
|
||||||
|
``focus`` action with::
|
||||||
|
|
||||||
|
a=-focus
|
||||||
|
|
||||||
|
Complete specification of all the metadata keys is in the table below. If a
|
||||||
|
terminal emulator encounters a key in the metadata it does not understand,
|
||||||
|
the key *must* be ignored, to allow for future extensibility of this escape
|
||||||
|
code. Similarly if values for known keys are unknown, the terminal emulator
|
||||||
|
*should* either ignore the entire escape code or perform a best guess effort
|
||||||
|
to display it based on what it does understand.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
It is possible to extend this escape code to allow specifying an icon for
|
||||||
|
the notification, however, given that some platforms, such as macOS, dont
|
||||||
|
allow displaying custom icons on a notification, at all, it was decided to
|
||||||
|
leave it out of the spec for the time being.
|
||||||
|
|
||||||
|
Similarly, features such as scheduled notifications could be added in future
|
||||||
|
revisions.
|
||||||
|
|
||||||
|
|
||||||
|
======= ==================== ========= =================
|
||||||
|
Key Value Default Description
|
||||||
|
======= ==================== ========= =================
|
||||||
|
``a`` Comma separated list ``focus`` What action to perform when the
|
||||||
|
of ``report``, notification is clicked
|
||||||
|
``focus``, with
|
||||||
|
optional leading
|
||||||
|
``-``
|
||||||
|
|
||||||
|
``d`` ``0`` or ``1`` ``1`` Indicates if the notification is
|
||||||
|
complete or not.
|
||||||
|
|
||||||
|
``e`` ``0`` or ``1`` ``0`` If set to ``1`` means the payload is base64 encoded UTF-8,
|
||||||
|
otherwise it is plain UTF-8 text with no C0 control codes in it
|
||||||
|
|
||||||
|
``i`` ``[a-zA-Z0-9-_+.]`` ``0`` Identifier for the notification
|
||||||
|
|
||||||
|
``p`` One of ``title`` or ``title`` Whether the payload is the notification title or body. If a
|
||||||
|
``body``. notification has no title, the body will be used as title.
|
||||||
|
======= ==================== ========= =================
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|kitty| also supports the legacy OSC 9 protocol developed by iTerm2 for
|
||||||
|
desktop notifications.
|
||||||
13
docs/faq.rst
13
docs/faq.rst
@@ -3,9 +3,6 @@ Frequently Asked Questions
|
|||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
Some special symbols are rendered small/truncated in kitty?
|
Some special symbols are rendered small/truncated in kitty?
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
@@ -36,7 +33,7 @@ it by adding the following to your vimrc::
|
|||||||
|
|
||||||
let &t_ut=''
|
let &t_ut=''
|
||||||
|
|
||||||
See :ref:`here <ext_styles>` for why |kitty| does not support background color erase.
|
See :doc:`here <deccara>` for why |kitty| does not support background color erase.
|
||||||
|
|
||||||
|
|
||||||
I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?
|
I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?
|
||||||
@@ -54,8 +51,6 @@ type it each time::
|
|||||||
|
|
||||||
alias ssh="kitty +kitten ssh"
|
alias ssh="kitty +kitten ssh"
|
||||||
|
|
||||||
Remember to also setup :ref:`completion`.
|
|
||||||
|
|
||||||
If for some reason that does not work (typically because the server is using a
|
If for some reason that does not work (typically because the server is using a
|
||||||
non POSIX compliant shell as ``/bin/sh``), you can try using it with ``python``
|
non POSIX compliant shell as ``/bin/sh``), you can try using it with ``python``
|
||||||
instead::
|
instead::
|
||||||
@@ -123,7 +118,7 @@ How do I change the colors in a running kitty instance?
|
|||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
You can either use the
|
You can either use the
|
||||||
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
|
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands>`_
|
||||||
to set colors or you can define keyboard shortcuts to set colors, for example::
|
to set colors or you can define keyboard shortcuts to set colors, for example::
|
||||||
|
|
||||||
map f1 set_colors --configured /path/to/some/config/file/colors.conf
|
map f1 set_colors --configured /path/to/some/config/file/colors.conf
|
||||||
@@ -309,10 +304,6 @@ terminal and then switch to another and these terminals have different TERM
|
|||||||
variables, tmux will break. You will need to restart it as tmux does not
|
variables, tmux will break. You will need to restart it as tmux does not
|
||||||
support multiple terminfo definitions.
|
support multiple terminfo definitions.
|
||||||
|
|
||||||
Copying to clipboard via OSC 52 will not work, because tmux does not support
|
|
||||||
the extended version of that protocol, you will need to add ``no-append`` to
|
|
||||||
:opt:`clipboard_control` in kitty.conf.
|
|
||||||
|
|
||||||
If you use any of the advanced features that kitty has innovated, such as
|
If you use any of the advanced features that kitty has innovated, such as
|
||||||
styled underlines, desktop notifications, extended keyboard support, etc.
|
styled underlines, desktop notifications, extended keyboard support, etc.
|
||||||
they may or may not work, depending on the whims of tmux's maintainer, your
|
they may or may not work, depending on the whims of tmux's maintainer, your
|
||||||
|
|||||||
122
docs/glossary.rst
Normal file
122
docs/glossary.rst
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
:orphan:
|
||||||
|
|
||||||
|
Glossary
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
os_window
|
||||||
|
kitty has two kinds of windows. Operating System windows, refered to as :term:`OS
|
||||||
|
Window <os_window>`, and *kitty windows*. An OS Window consists of one or more kitty
|
||||||
|
:term:`tabs <tab>`. Each tab in turn consists of one or more *kitty
|
||||||
|
windows* organized in a :term:`layout`.
|
||||||
|
|
||||||
|
tab
|
||||||
|
A *tab* refers to a group of :term:`kitty windows <window>`, organized in
|
||||||
|
a :term:`layout`. Every :term:`OS Window <os_window>` contains one or more tabs.
|
||||||
|
|
||||||
|
layout
|
||||||
|
A *layout* is a system of organizing :term:`kitty windows <window>` in
|
||||||
|
groups inside a tab. The layout automatically maintains the size and
|
||||||
|
position of the windows, think of a layout as a tiling window manager for
|
||||||
|
the terminal. See :doc:`layouts` for details.
|
||||||
|
|
||||||
|
window
|
||||||
|
kitty has two kinds of windows. Operating System windows, refered to as :term:`OS
|
||||||
|
Window <os_window>`, and *kitty windows*. An OS Window consists of one or more kitty
|
||||||
|
:term:`tabs <tab>`. Each tab in turn consists of one or more *kitty
|
||||||
|
windows* organized in a :term:`layout`.
|
||||||
|
|
||||||
|
overlay
|
||||||
|
An *overlay window* is a :term:`kitty window <window>` that is placed on
|
||||||
|
top of an existing kitty window, entirely covering it. Overlays are used
|
||||||
|
throught kitty, for example, to display the :ref:`the scrollback buffer <scrollback>`,
|
||||||
|
to display :doc:`hints </kittens/hints>`, for :doc:`unicode input
|
||||||
|
</kittens/unicode-input>` etc.
|
||||||
|
|
||||||
|
hyperlinks
|
||||||
|
Terminals can have hyperlinks, just like the internet. In kitty you can
|
||||||
|
:doc:`control exactly what happens <open_actions>` when clicking on a
|
||||||
|
hyperlink, based on the type of link and its URL.
|
||||||
|
|
||||||
|
.. _env_vars:
|
||||||
|
|
||||||
|
Environment variables
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Variables that influence kitty behavior
|
||||||
|
|
||||||
|
.. envvar:: KITTY_CONFIG_DIRECTORY
|
||||||
|
|
||||||
|
Controls where kitty looks for :file:`kitty.conf` and other configuration
|
||||||
|
files. Defaults to :file:`~/.config/kitty`. For full details of the config
|
||||||
|
directory lookup mechanism see, :option:`kitty --config`.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: VISUAL
|
||||||
|
|
||||||
|
The terminal editor (such as ``vi`` or ``nano``) kitty uses, when, for
|
||||||
|
instance, opening :file:`kitty.conf` in response to :sc:`edit_config_file`.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: EDITOR
|
||||||
|
|
||||||
|
Same as :envvar:`VISUAL`. Used if :envvar:`VISUAL` is not set.
|
||||||
|
|
||||||
|
|
||||||
|
Variables that kitty sets when running child programs
|
||||||
|
|
||||||
|
.. envvar:: KITTY_WINDOW_ID
|
||||||
|
|
||||||
|
An integer that is the id for the kitty :term:`window` the program is running in.
|
||||||
|
Can be used with the :doc:`kitty remote control facility <remote-control>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: WINDOWID
|
||||||
|
|
||||||
|
The id for the :term:`OS Window <os_window>` the program is running in. Only available
|
||||||
|
on platforms that have ids for their windows, such as X11 and macOS.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: TERM
|
||||||
|
|
||||||
|
The name of the terminal, defaults to ``xterm-kitty``. See :opt:`term`.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: TERMINFO
|
||||||
|
|
||||||
|
Path to a directory containing the kitty terminfo database.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: COLORTERM
|
||||||
|
|
||||||
|
Set to the value ``truecolor`` to indicate that kitty supports 16 million
|
||||||
|
colors.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: KITTY_LISTEN_ON
|
||||||
|
|
||||||
|
Set when the :doc:`remote control <remote-control>` facility is enabled and
|
||||||
|
the a socket is used for control via :option:`kitty --listen-on` or :opt:`listen_on`.
|
||||||
|
Contains the path to the socket. Avoids needs to use :option:`kitty @ --to` when
|
||||||
|
issuing remote control commands.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: KITTY_PIPE_DATA
|
||||||
|
|
||||||
|
Set to data describing the layout of the screen when running child
|
||||||
|
programs using :option:`launch --stdin-source` with the contents of the
|
||||||
|
screen/scrollback piped to them.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: KITTY_CHILD_CMDLINE
|
||||||
|
|
||||||
|
Set to the command line of the child process running in the kitty
|
||||||
|
window when calling the notification callback program on terminal bell, see
|
||||||
|
:opt:`command_on_bell`.
|
||||||
|
|
||||||
|
|
||||||
|
.. envvar:: KITTY_COMMON_OPTS
|
||||||
|
|
||||||
|
Set with the values of some common kitty options when running
|
||||||
|
kittens, so kittens can use them without needing to load kitty.conf.
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
:tocdepth: 3
|
Terminal graphics protocol
|
||||||
|
=================================
|
||||||
The terminal graphics protocol
|
|
||||||
==================================
|
|
||||||
|
|
||||||
The goal of this specification is to create a flexible and performant protocol
|
The goal of this specification is to create a flexible and performant protocol
|
||||||
that allows the program running in the terminal, hereafter called the *client*,
|
that allows the program running in the terminal, hereafter called the *client*,
|
||||||
to render arbitrary pixel (raster) graphics to the screen of the terminal
|
to render arbitrary pixel (raster) graphics to the screen of the terminal
|
||||||
emulator. The major design goals are
|
emulator. The major design goals are:
|
||||||
|
|
||||||
* Should not require terminal emulators to understand image formats.
|
* Should not require terminal emulators to understand image formats.
|
||||||
* Should allow specifying graphics to be drawn at individual pixel positions.
|
* Should allow specifying graphics to be drawn at individual pixel positions.
|
||||||
* The graphics should integrate with the text, in particular it should be possible to draw graphics
|
* The graphics should integrate with the text, in particular it should be possible to draw graphics
|
||||||
below as well as above the text, with alpha blending. The graphics should also scroll with the text, automatically.
|
below as well as above the text, with alpha blending. The graphics should also scroll with the text, automatically.
|
||||||
* Should use optimizations when the client is running on the same computer as the terminal emulator.
|
* Should use optimizations when the client is running on the same computer as the terminal emulator.
|
||||||
|
|
||||||
For some discussion regarding the design choices, see `#33
|
For some discussion regarding the design choices, see `#33
|
||||||
<https://github.com/kovidgoyal/kitty/issues/33>`_.
|
<https://github.com/kovidgoyal/kitty/issues/33>`_.
|
||||||
@@ -30,23 +28,19 @@ alpha-blending and text over graphics.
|
|||||||
|
|
||||||
Some programs and libraries that use the kitty graphics protocol:
|
Some programs and libraries that use the kitty graphics protocol:
|
||||||
|
|
||||||
* `termpdf.py <https://github.com/dsanson/termpdf.py>`_ - a terminal PDF/DJVU/CBR viewer
|
* `termpdf.py <https://github.com/dsanson/termpdf.py>`_ - a terminal PDF/DJVU/CBR viewer
|
||||||
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with
|
||||||
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
|
||||||
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
|
||||||
* `pixcat <https://github.com/mirukana/pixcat>`_ - a third party CLI and python library that wraps the graphics protocol
|
* `pixcat <https://github.com/mirukana/pixcat>`_ - a third party CLI and python library that wraps the graphics protocol
|
||||||
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
* `neofetch <https://github.com/dylanaraps/neofetch>`_ - A command line system
|
||||||
information tool
|
information tool
|
||||||
* `viu <https://github.com/atanunq/viu>`_ - a terminal image viewer
|
* `viu <https://github.com/atanunq/viu>`_ - a terminal image viewer
|
||||||
* `glkitty <https://github.com/michaeljclark/glkitty>`_ - C library to draw OpenGL shaders in the terminal with a glgears demo
|
* `glkitty <https://github.com/michaeljclark/glkitty>`_ - C library to draw OpenGL shaders in the terminal with a glgears demo
|
||||||
* `ctx.graphics <https://ctx.graphics/>`_ - Library for drawing graphics
|
* `ctx.graphics <https://ctx.graphics/>`_ - Library for drawing graphics
|
||||||
* `timg <https://github.com/hzeller/timg>`_ - a terminal image and video viewer
|
* `timg <https://github.com/hzeller/timg>`_ - a terminal image and video viewer
|
||||||
* `notcurses <https://github.com/dankamongmen/notcurses>`_ - C library for terminal graphics with bindings for C++, Rust and Python
|
* `notcurses <https://github.com/dankamongmen/notcurses>`_ - C library for terminal graphics with bindings for C++, Rust and Python
|
||||||
* `rasterm <https://github.com/BourgeoisBear/rasterm>`_ - Go library to display images in the the terminal
|
* `rasterm <https://github.com/BourgeoisBear/rasterm>`_ - Go library to display images in the the terminal
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
|
|
||||||
Getting the window size
|
Getting the window size
|
||||||
@@ -57,28 +51,33 @@ client must be able to get the window size in pixels and the number of cells
|
|||||||
per row and column. This can be done by using the ``TIOCGWINSZ`` ioctl. Some
|
per row and column. This can be done by using the ``TIOCGWINSZ`` ioctl. Some
|
||||||
code to demonstrate its use
|
code to demonstrate its use
|
||||||
|
|
||||||
In C:
|
.. tab:: C
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
struct winsize sz;
|
struct winsize sz;
|
||||||
ioctl(0, TIOCGWINSZ, &sz);
|
ioctl(0, TIOCGWINSZ, &sz);
|
||||||
printf("number of rows: %i, number of columns: %i, screen width: %i, screen height: %i\n", sz.ws_row, sz.ws_col, sz.ws_xpixel, sz.ws_ypixel);
|
printf(
|
||||||
return 0;
|
"number of rows: %i, number of columns: %i, screen width: %i, screen height: %i\n",
|
||||||
}
|
sz.ws_row, sz.ws_col, sz.ws_xpixel, sz.ws_ypixel);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
In Python:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. tab:: Python
|
||||||
|
|
||||||
import array, fcntl, sys, termios
|
.. code-block:: python
|
||||||
buf = array.array('H', [0, 0, 0, 0])
|
|
||||||
fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, buf)
|
import array, fcntl, sys, termios
|
||||||
print('number of rows: {}, number of columns: {}, screen width: {}, screen height: {}'.format(*buf))
|
buf = array.array('H', [0, 0, 0, 0])
|
||||||
|
fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, buf)
|
||||||
|
print((
|
||||||
|
'number of rows: {} number of columns: {}'
|
||||||
|
'screen width: {} screen height: {}').format(*buf))
|
||||||
|
|
||||||
Note that some terminals return ``0`` for the width and height values. Such
|
Note that some terminals return ``0`` for the width and height values. Such
|
||||||
terminals should be modified to return the correct values. Examples of
|
terminals should be modified to return the correct values. Examples of
|
||||||
@@ -98,32 +97,36 @@ features of the graphics protocol:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from base64 import standard_b64encode
|
from base64 import standard_b64encode
|
||||||
|
|
||||||
def serialize_gr_command(**cmd):
|
|
||||||
payload = cmd.pop('payload', None)
|
|
||||||
cmd = ','.join('{}={}'.format(k, v) for k, v in cmd.items())
|
|
||||||
ans = []
|
|
||||||
w = ans.append
|
|
||||||
w(b'\033_G'), w(cmd.encode('ascii'))
|
|
||||||
if payload:
|
|
||||||
w(b';')
|
|
||||||
w(payload)
|
|
||||||
w(b'\033\\')
|
|
||||||
return b''.join(ans)
|
|
||||||
|
|
||||||
def write_chunked(**cmd):
|
def serialize_gr_command(**cmd):
|
||||||
data = standard_b64encode(cmd.pop('data'))
|
payload = cmd.pop('payload', None)
|
||||||
while data:
|
cmd = ','.join('{}={}'.format(k, v) for k, v in cmd.items())
|
||||||
chunk, data = data[:4096], data[4096:]
|
ans = []
|
||||||
m = 1 if data else 0
|
w = ans.append
|
||||||
sys.stdout.buffer.write(serialize_gr_command(payload=chunk, m=m, **cmd))
|
w(b'\033_G'), w(cmd.encode('ascii'))
|
||||||
sys.stdout.flush()
|
if payload:
|
||||||
cmd.clear()
|
w(b';')
|
||||||
|
w(payload)
|
||||||
|
w(b'\033\\')
|
||||||
|
return b''.join(ans)
|
||||||
|
|
||||||
with open(sys.argv[-1], 'rb') as f:
|
|
||||||
write_chunked(a='T', f=100, data=f.read())
|
def write_chunked(**cmd):
|
||||||
|
data = standard_b64encode(cmd.pop('data'))
|
||||||
|
while data:
|
||||||
|
chunk, data = data[:4096], data[4096:]
|
||||||
|
m = 1 if data else 0
|
||||||
|
sys.stdout.buffer.write(serialize_gr_command(payload=chunk, m=m,
|
||||||
|
**cmd))
|
||||||
|
sys.stdout.flush()
|
||||||
|
cmd.clear()
|
||||||
|
|
||||||
|
|
||||||
|
with open(sys.argv[-1], 'rb') as f:
|
||||||
|
write_chunked(a='T', f=100, data=f.read())
|
||||||
|
|
||||||
|
|
||||||
Save this script as :file:`png.py`, then you can use it to display any PNG
|
Save this script as :file:`png.py`, then you can use it to display any PNG
|
||||||
@@ -226,8 +229,9 @@ Value of `t` Meaning
|
|||||||
is in a known temporary directory, such as :file:`/tmp`,
|
is in a known temporary directory, such as :file:`/tmp`,
|
||||||
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
||||||
specific temporary directories.
|
specific temporary directories.
|
||||||
``s`` A *shared memory object*, which on POSIX systems is a `POSIX shared memory object
|
``s`` A *shared memory object*, which on POSIX systems is a
|
||||||
<http://man7.org/linux/man-pages/man7/shm_overview.7.html>`_ and on Windows is a
|
`POSIX shared memory object <https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html>`_
|
||||||
|
and on Windows is a
|
||||||
`Named shared memory object <https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory>`_.
|
`Named shared memory object <https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory>`_.
|
||||||
The terminal emulator must read the data from the memory
|
The terminal emulator must read the data from the memory
|
||||||
object and then unlink and close it on POSIX and just
|
object and then unlink and close it on POSIX and just
|
||||||
@@ -590,7 +594,7 @@ Clients can control animations by using the ``a=a`` key in the escape code sent
|
|||||||
to the terminal.
|
to the terminal.
|
||||||
|
|
||||||
The simplest is client driven animations, where the client transmits the frame
|
The simplest is client driven animations, where the client transmits the frame
|
||||||
data and the also instructs the terminal to make a particular frame the current
|
data and then also instructs the terminal to make a particular frame the current
|
||||||
frame. To change the current frame, use the ``c`` key::
|
frame. To change the current frame, use the ``c`` key::
|
||||||
|
|
||||||
<ESC>_Ga=a,i=3,c=7<ESC>\
|
<ESC>_Ga=a,i=3,c=7<ESC>\
|
||||||
@@ -632,6 +636,45 @@ static background.
|
|||||||
In particular, the first frame or *root frame* is created with the base image
|
In particular, the first frame or *root frame* is created with the base image
|
||||||
data and has no gap, so its gap must be set using this control code.
|
data and has no gap, so its gap must be set using this control code.
|
||||||
|
|
||||||
|
Composing animation frames
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 0.22.0
|
||||||
|
Support for frame composition
|
||||||
|
|
||||||
|
Clients can *compose* animation frames, this means that they can compose pixels
|
||||||
|
in rectangular regions from one frame onto another frame. This allows for fast
|
||||||
|
and low band-width modification of frames.
|
||||||
|
|
||||||
|
To achieve this use the ``a=c`` key. The source frame is specified with
|
||||||
|
``r=frame number`` and the destination frame as ``c=frame number``. The size of
|
||||||
|
the rectangle is specified as ``w=width,h=height`` pixels. If unspecified, the
|
||||||
|
full image width and height are used. The offset of the rectangle from the
|
||||||
|
top-left corner for the source frame is specified by the ``x,y`` keys and the
|
||||||
|
destination frame by the ``X,Y`` keys. The composition operation is specified
|
||||||
|
by the ``C`` key with the default being to alpha blend the source rectangle
|
||||||
|
onto the destination rectangle. With ``C=1`` it will be a simple replacement
|
||||||
|
of pixels. For example::
|
||||||
|
|
||||||
|
<ESC>_Gi=1,r=7,c=9,w=23,h=27,X=4,Y=8,x=1,y=3<ESC>\
|
||||||
|
|
||||||
|
Will compose a ``23x27`` rectangle located at ``(4, 8)`` in the ``7th frame``
|
||||||
|
onto the rectangle located at ``(1, 3)`` in the ``9th frame``. These will be
|
||||||
|
in the image with ``id=1``.
|
||||||
|
|
||||||
|
If the frames or the image are not found the terminal emulator must
|
||||||
|
respond with `ENOENT`. If the rectangles go out of bounds of the image
|
||||||
|
the terminal must respond with `EINVAL`. If the source and destination frames are
|
||||||
|
the same and the rectangles overlap, the terminal must respond with `EINVAL`.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In kitty, doing a composition will cause a frame to be *fully rendered*
|
||||||
|
potentially increasing its storage requirements, when the frame was previously
|
||||||
|
stored as a set of operations on other frames. If this happens and there
|
||||||
|
is not enough storage space, kitty will respond with ENOSPC.
|
||||||
|
|
||||||
|
|
||||||
Image persistence and storage quotas
|
Image persistence and storage quotas
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
@@ -654,10 +697,10 @@ take, and the default value they take when missing. All integers are 32-bit.
|
|||||||
Key Value Default Description
|
Key Value Default Description
|
||||||
======= ==================== ========= =================
|
======= ==================== ========= =================
|
||||||
``a`` Single character. ``t`` The overall action this graphics command is performing.
|
``a`` Single character. ``t`` The overall action this graphics command is performing.
|
||||||
``(t, T, q, p, d)`` ``t`` - transmit data, ``T`` - transmit data and display image,
|
``(a, c, d, f, `` ``t`` - transmit data, ``T`` - transmit data and display image,
|
||||||
``q`` - query terminal, ``p`` - put (display) previous transmitted image,
|
``p, q, t, T)`` ``q`` - query terminal, ``p`` - put (display) previous transmitted image,
|
||||||
``d`` - delete image, ``f`` - transmit data for animation frames,
|
``d`` - delete image, ``f`` - transmit data for animation frames,
|
||||||
``a`` - control animation
|
``a`` - control animation, ``c`` - compose animation frames
|
||||||
|
|
||||||
``q`` ``0, 1, 2`` ``0`` Suppress responses from the terminal to this graphics command.
|
``q`` ``0, 1, 2`` ``0`` Suppress responses from the terminal to this graphics command.
|
||||||
|
|
||||||
@@ -711,6 +754,20 @@ Key Value Default Description
|
|||||||
``Y`` Positive integer ``0`` The background color for pixels not
|
``Y`` Positive integer ``0`` The background color for pixels not
|
||||||
specified in the frame data. Must be in 32-bit RGBA format
|
specified in the frame data. Must be in 32-bit RGBA format
|
||||||
|
|
||||||
|
**Keys for animation frame composition**
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
``c`` Positive integer ``0`` The 1-based frame number of the frame whose image data serves as the overlaid data
|
||||||
|
``r`` Positive integer ``0`` The 1-based frame number of the frame that is being edited.
|
||||||
|
``x`` Positive integer ``0`` The left edge (in pixels) of the destination rectangle
|
||||||
|
``y`` Positive integer ``0`` The top edge (in pixels) of the destination rectangle
|
||||||
|
``w`` Positive integer ``0`` The width (in pixels) of the source and destination rectangles. By default, the entire width is used
|
||||||
|
``h`` Positive integer ``0`` The height (in pixels) of the source and destination rectangles. By default, the entire height is used
|
||||||
|
``X`` Positive integer ``0`` The left edge (in pixels) of the source rectangle
|
||||||
|
``Y`` Positive integer ``0`` The top edge (in pixels) of the source rectangle
|
||||||
|
``C`` Positive integer ``0`` The composition mode for blending
|
||||||
|
pixels. Default is full alpha blending. ``1`` means a simple overwrite.
|
||||||
|
|
||||||
|
|
||||||
**Keys for animation control**
|
**Keys for animation control**
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|||||||
447
docs/index.rst
447
docs/index.rst
@@ -1,421 +1,66 @@
|
|||||||
:tocdepth: 2
|
kitty
|
||||||
|
|
||||||
==========================================================
|
|
||||||
kitty - the fast, featureful, GPU based terminal emulator
|
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
.. container:: major-features
|
*The fast, feature-rich, GPU based terminal emulator*
|
||||||
|
|
||||||
* Offloads rendering to the GPU for :doc:`lower system load <performance>` and
|
.. toctree::
|
||||||
buttery smooth scrolling. Uses threaded rendering to minimize input latency.
|
:hidden:
|
||||||
|
|
||||||
* Supports all modern terminal features: :doc:`graphics (images)
|
quickstart
|
||||||
<graphics-protocol>`, unicode, `true-color
|
overview
|
||||||
<https://gist.github.com/XVilka/8346728>`_,
|
faq
|
||||||
OpenType ligatures, mouse protocol, :doc:`hyperlinks <open_actions>`,
|
support
|
||||||
focus tracking, `bracketed paste <https://cirw.in/blog/bracketed-paste>`_
|
performance
|
||||||
and several :doc:`new terminal protocol extensions
|
changelog
|
||||||
<protocol-extensions>`.
|
integrations
|
||||||
|
protocol-extensions
|
||||||
|
|
||||||
* Supports tiling multiple terminal windows side by side in different
|
|
||||||
:ref:`layouts <layouts>` without needing to use an extra program like tmux
|
|
||||||
|
|
||||||
* Can be :doc:`controlled from scripts or the shell prompt <remote-control>`,
|
.. tab:: Fast
|
||||||
even over SSH.
|
|
||||||
|
|
||||||
* Has a framework for :ref:`kittens`, small terminal programs that can be used to
|
* Offloads rendering to the GPU for :doc:`lower system load <performance>`
|
||||||
extend |kitty|'s functionality. For example, they are used for
|
* Uses threaded rendering for absolutely minimal latency
|
||||||
:doc:`Unicode input <kittens/unicode-input>`, :doc:`Hints <kittens/hints>` and
|
* Performance tradeoffs can be :ref:`tuned <conf-kitty-performance>`
|
||||||
:doc:`Side-by-side diff <kittens/diff>`.
|
|
||||||
|
|
||||||
* Supports :ref:`startup sessions <sessions>` which allow you to specify
|
.. tab:: Capable
|
||||||
the window/tab layout, working directories and programs to run on startup.
|
|
||||||
|
|
||||||
* Cross-platform: |kitty| works on Linux and macOS, but because it uses only
|
* Graphics, with :doc:`images and animations <graphics-protocol>`
|
||||||
OpenGL for rendering, it should be trivial to port to other Unix-like platforms.
|
* Ligatures and emoji, with :opt:`per glyph font substitution <symbol_map>`
|
||||||
|
* :term:`Hyperlinks<hyperlinks>`, with :doc:`configurable actions <open_actions>`
|
||||||
|
|
||||||
* Allows you to open :ref:`the scrollback buffer <scrollback>` in a
|
.. tab:: Scriptable
|
||||||
separate window using arbitrary programs of your choice. This is useful for
|
|
||||||
browsing the history comfortably in a pager or editor.
|
|
||||||
|
|
||||||
* Has :ref:`multiple copy/paste buffers <cpbuf>`, like vim.
|
* Control from :doc:`scripts or the shell <remote-control>`
|
||||||
|
* Extend with :ref:`kittens <kittens>` using the Python language
|
||||||
|
* Use :ref:`startup sessions <sessions>` to specify working environments
|
||||||
|
|
||||||
|
.. tab:: Composable
|
||||||
|
|
||||||
|
* Programmble tabs, :ref:`splits <splits_layout>` and multiple :doc:`layouts <layouts>` to manage windows
|
||||||
|
* Browse the :ref:`entire history <scrollback>` or the output from the last command comfortably in pagers and editors
|
||||||
|
* Edit or download :doc:`remote files <kittens/remote_file>` in an existing SSH session
|
||||||
|
|
||||||
|
.. tab:: Cross-platform
|
||||||
|
|
||||||
|
* Linux
|
||||||
|
* macOS
|
||||||
|
* Various BSDs
|
||||||
|
|
||||||
|
.. tab:: Innovative
|
||||||
|
|
||||||
|
Pioneered various extensions to move the entire terminal ecosystem forward
|
||||||
|
|
||||||
|
* :doc:`graphics-protocol`
|
||||||
|
* :doc:`keyboard-protocol`
|
||||||
|
* Lots more in :doc:`protocol-extensions`
|
||||||
|
|
||||||
|
|
||||||
.. figure:: screenshots/screenshot.png
|
.. figure:: screenshots/screenshot.png
|
||||||
:alt: Screenshot, showing three programs in the 'Tall' layout
|
:alt: Screenshot, showing three programs in the 'Tall' layout
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
||||||
|
|
||||||
|
|
||||||
|
To get started see :doc:`quickstart`.
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 1
|
|
||||||
|
|
||||||
|
|
||||||
.. _quickstart:
|
|
||||||
|
|
||||||
Quickstart
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Pre-built binaries of |kitty| are available for both macOS and Linux.
|
|
||||||
See the :doc:`binary install instructions </binary>`. You can also
|
|
||||||
:doc:`build from source </build>`.
|
|
||||||
|
|
||||||
Additionally, you can use your favorite package manager to install the |kitty|
|
|
||||||
package, but note that some Linux distribution packages are woefully outdated.
|
|
||||||
|kitty| is available in a vast number of package repositories for macOS
|
|
||||||
and Linux.
|
|
||||||
|
|
||||||
.. image:: https://repology.org/badge/tiny-repos/kitty.svg
|
|
||||||
:target: https://repology.org/project/kitty/versions
|
|
||||||
:alt: Number of repositories kitty is available in
|
|
||||||
|
|
||||||
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
|
||||||
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
|
||||||
|
|
||||||
|
|
||||||
Design philosophy
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
|kitty| is designed for power keyboard users. To that end all its controls
|
|
||||||
work with the keyboard (although it fully supports mouse interactions as
|
|
||||||
well). Its configuration is a simple, human editable, single file for
|
|
||||||
easy reproducibility (I like to store configuration in source control).
|
|
||||||
|
|
||||||
The code in |kitty| is designed to be simple, modular and hackable. It is
|
|
||||||
written in a mix of C (for performance sensitive parts) and Python (for
|
|
||||||
easy hackability of the UI). It does not depend on any large and complex
|
|
||||||
UI toolkit, using only OpenGL for rendering everything.
|
|
||||||
|
|
||||||
Finally, |kitty| is designed from the ground up to support all modern
|
|
||||||
terminal features, such as unicode, true color, bold/italic fonts, text
|
|
||||||
formatting, etc. It even extends existing text formatting escape codes,
|
|
||||||
to add support for features not available elsewhere, such as colored and
|
|
||||||
styled (curly) underlines. One of the design goals of |kitty| is to be
|
|
||||||
easily extensible so that new features can be added in the future with
|
|
||||||
relatively little effort.
|
|
||||||
|
|
||||||
.. include:: basic.rst
|
|
||||||
|
|
||||||
.. _layouts:
|
|
||||||
|
|
||||||
Layouts
|
|
||||||
----------
|
|
||||||
|
|
||||||
A layout is an arrangement of multiple kitty *windows* inside a top-level OS window. You can create a new window
|
|
||||||
using the :sc:`new_window` key combination.
|
|
||||||
|
|
||||||
Currently, there are seven layouts available:
|
|
||||||
|
|
||||||
* **Fat** -- One (or optionally more) windows are shown full width on the top, the rest of the windows are shown side-by-side on the bottom
|
|
||||||
* **Grid** -- All windows are shown in a grid
|
|
||||||
* **Horizontal** -- All windows are shown side-by-side
|
|
||||||
* **Splits** -- Windows arranged in arbitrary patterns created using horizontal and vertical splits
|
|
||||||
* **Stack** -- Only a single maximized window is shown at a time
|
|
||||||
* **Tall** -- One (or optionally more) windows are shown full height on the left, the rest of the windows are shown one below the other on the right
|
|
||||||
* **Vertical** -- All windows are shown one below the other
|
|
||||||
|
|
||||||
By default, all layouts are enabled and you can switch between layouts using
|
|
||||||
the :sc:`next_layout` key combination. You can also create shortcuts to select
|
|
||||||
particular layouts, and choose which layouts you want to enable/disable, see
|
|
||||||
:ref:`conf-kitty-shortcuts.layout` for examples. The first layout listed in
|
|
||||||
:opt:`enabled_layouts` becomes the default layout.
|
|
||||||
|
|
||||||
For more details on the layouts and how to use them see :doc:`layouts`.
|
|
||||||
|
|
||||||
.. _kittens:
|
|
||||||
|
|
||||||
Kittens
|
|
||||||
------------------
|
|
||||||
|
|
||||||
|kitty| has a framework for easily creating terminal programs that make use of
|
|
||||||
its advanced features. These programs are called kittens. They are used both
|
|
||||||
to add features to |kitty| itself and to create useful standalone programs.
|
|
||||||
Some prominent kittens:
|
|
||||||
|
|
||||||
:doc:`icat <kittens/icat>`
|
|
||||||
Display images in the terminal
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`diff <kittens/diff>`
|
|
||||||
A fast, side-by-side diff for the terminal with syntax highlighting and
|
|
||||||
images
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Unicode Input <kittens/unicode-input>`
|
|
||||||
Easily input arbitrary unicode characters in |kitty| by name or hex code.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Hints <kittens/hints>`
|
|
||||||
Select and open/paste/insert arbitrary text snippets such as URLs,
|
|
||||||
filenames, words, lines, etc. from the terminal screen.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Remote file <kittens/remote_file>`
|
|
||||||
Edit, open, or download remote files over SSH easily, by simply clicking on
|
|
||||||
the filename.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Hyperlinked grep <kittens/hyperlinked_grep>`
|
|
||||||
Search your files using `ripgrep <https://github.com/BurntSushi/ripgrep>`_
|
|
||||||
and open the results directly in your favorite editor in the terminal,
|
|
||||||
at the line containing the search result, simply by clicking on the result you want.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Broadcast <kittens/broadcast>`
|
|
||||||
Type in one kitty window and have it broadcast to all (or a subset) of
|
|
||||||
other kitty windows.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Panel <kittens/panel>`
|
|
||||||
Draw a GPU accelerated dock panel on your desktop showing the output
|
|
||||||
from an arbitrary terminal program.
|
|
||||||
|
|
||||||
|
|
||||||
:doc:`Clipboard <kittens/clipboard>`
|
|
||||||
Copy/paste to the clipboard from shell scripts, even over SSH.
|
|
||||||
|
|
||||||
You can also :doc:`Learn to create your own kittens <kittens/custom>`.
|
|
||||||
|
|
||||||
|
|
||||||
Configuring kitty
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
|kitty| is highly configurable, everything from keyboard shortcuts to
|
|
||||||
painting frames-per-second. Press :sc:`edit_config_file` in kitty
|
|
||||||
to open its fully commented sample config file in your text editor.
|
|
||||||
For details see the :doc:`configuration docs <conf>`.
|
|
||||||
|
|
||||||
|
|
||||||
Remote control
|
|
||||||
------------------
|
|
||||||
|
|
||||||
|kitty| has a very powerful system that allows you to control it from the
|
|
||||||
:doc:`shell prompt, even over SSH <remote-control>`. You can change colors,
|
|
||||||
fonts, open new windows, tabs, set their titles, change window layout, get text
|
|
||||||
from one window and send text to another, etc, etc. The possibilities are
|
|
||||||
endless. See the :doc:`tutorial <remote-control>` to get started.
|
|
||||||
|
|
||||||
.. _sessions:
|
|
||||||
|
|
||||||
Startup Sessions
|
|
||||||
------------------
|
|
||||||
|
|
||||||
You can control the tabs, window layout, working directory, startup programs,
|
|
||||||
etc. by creating a "session" file and using the :option:`kitty --session`
|
|
||||||
command line flag or the :opt:`startup_session` option in :file:`kitty.conf`.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
.. code-block:: session
|
|
||||||
|
|
||||||
# Set the window layout for the current tab
|
|
||||||
layout tall
|
|
||||||
# Set the working directory for windows in the current tab
|
|
||||||
cd ~
|
|
||||||
# Create a window and run the specified command in it
|
|
||||||
launch zsh
|
|
||||||
# Create a window with some environment variables set and run
|
|
||||||
# vim in it
|
|
||||||
launch --env FOO=BAR vim
|
|
||||||
# Set the title for the next window
|
|
||||||
launch --title "Chat with x" irssi --profile x
|
|
||||||
|
|
||||||
# Create a new tab (the part after new_tab is the optional tab
|
|
||||||
# name which will be displayed in the tab bar, if omitted, the
|
|
||||||
# title of the active window will be used instead)
|
|
||||||
new_tab my tab
|
|
||||||
cd ~/somewhere
|
|
||||||
# Set the layouts allowed in this tab
|
|
||||||
enabled_layouts tall, stack
|
|
||||||
# Set the current layout
|
|
||||||
layout stack
|
|
||||||
launch zsh
|
|
||||||
|
|
||||||
# Create a new OS window
|
|
||||||
new_os_window
|
|
||||||
# set new window size to 80x25 cells
|
|
||||||
os_window_size 80c 25c
|
|
||||||
# set the --class for the new OS window
|
|
||||||
os_window_class mywindow
|
|
||||||
launch sh
|
|
||||||
# Make the current window the active (focused) window
|
|
||||||
focus
|
|
||||||
launch emacs
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
The :doc:`launch <launch>` command when used in a session file
|
|
||||||
cannot create new OS windows, or tabs.
|
|
||||||
|
|
||||||
|
|
||||||
Mouse features
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
* You can click on a URL to open it in a browser.
|
|
||||||
* You can double click to select a word and then drag to select more words.
|
|
||||||
* You can triple click to select a line and then drag to select more lines.
|
|
||||||
* You can triple click while holding :kbd:`ctrl+alt` to select from clicked
|
|
||||||
point to end of line.
|
|
||||||
* You can right click to extend a previous selection.
|
|
||||||
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
|
||||||
columns.
|
|
||||||
* Selecting text automatically copies it to the primary clipboard (on
|
|
||||||
platforms with a primary clipboard).
|
|
||||||
* You can middle click to paste from the primary clipboard (on platforms
|
|
||||||
with a primary clipboard).
|
|
||||||
* You can select text with kitty even when a terminal program has grabbed
|
|
||||||
the mouse by holding down the :kbd:`shift` key.
|
|
||||||
|
|
||||||
All these actions can be customized in :file:`kitty.conf` as described
|
|
||||||
:ref:`here <conf-kitty-mouse.mousemap>`.
|
|
||||||
|
|
||||||
|
|
||||||
Font control
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
|kitty| has extremely flexible and powerful font selection features. You can
|
|
||||||
specify individual families for the regular, bold, italic and bold+italic
|
|
||||||
fonts. You can even specify specific font families for specific ranges of
|
|
||||||
unicode characters. This allows precise control over text rendering. It can
|
|
||||||
come in handy for applications like powerline, without the need to use patched
|
|
||||||
fonts. See the various font related configuration directives in
|
|
||||||
:ref:`conf-kitty-fonts`.
|
|
||||||
|
|
||||||
|
|
||||||
.. _scrollback:
|
|
||||||
|
|
||||||
The scrollback buffer
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
|kitty| supports scrolling back to view history, just like most terminals. You
|
|
||||||
can use either keyboard shortcuts or the mouse scroll wheel to do so. However,
|
|
||||||
|kitty| has an extra, neat feature. Sometimes you need to explore the
|
|
||||||
scrollback buffer in more detail, maybe search for some text or refer to it
|
|
||||||
side-by-side while typing in a follow-up command. |kitty| allows you to do this
|
|
||||||
by pressing the :sc:`show_scrollback` key-combination, which will open the
|
|
||||||
scrollback buffer in your favorite pager program (which is ``less`` by default).
|
|
||||||
Colors and text formatting are preserved. You can explore the scrollback buffer
|
|
||||||
comfortably within the pager.
|
|
||||||
|
|
||||||
Additionally, you can pipe the contents of the scrollback buffer to an
|
|
||||||
arbitrary, command running in a new window, tab or overlay, for example::
|
|
||||||
|
|
||||||
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
|
|
||||||
|
|
||||||
Would open the scrollback buffer in a new window when you press the :kbd:`F1`
|
|
||||||
key. See :sc:`show_scrollback` for details.
|
|
||||||
|
|
||||||
If you want to use it with an editor such as vim to get more powerful features,
|
|
||||||
you can see tips for doing so, in
|
|
||||||
`this thread <https://github.com/kovidgoyal/kitty/issues/719>`_.
|
|
||||||
|
|
||||||
If you wish to store very large amounts of scrollback to view using the piping or
|
|
||||||
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
|
||||||
option.
|
|
||||||
|
|
||||||
.. _cpbuf:
|
|
||||||
|
|
||||||
Multiple copy/paste buffers
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
In addition to being able to copy/paste from the system clipboard, in |kitty| you
|
|
||||||
can also setup an arbitrary number of copy paste buffers. To do so, simply add
|
|
||||||
something like the following to your :file:`kitty.conf`::
|
|
||||||
|
|
||||||
map f1 copy_to_buffer a
|
|
||||||
map f2 paste_from_buffer a
|
|
||||||
|
|
||||||
This will allow you to press :kbd:`F1` to copy the current selection to an
|
|
||||||
internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
|
|
||||||
names are arbitrary strings, so you can define as many such buffers as you
|
|
||||||
need.
|
|
||||||
|
|
||||||
Marks
|
|
||||||
-------------
|
|
||||||
|
|
||||||
kitty has the ability to mark text on the screen based on regular expressions.
|
|
||||||
This can be useful to highlight words or phrases when browsing output from long
|
|
||||||
running programs or similar. To learn how this feature works, see :doc:`marks`.
|
|
||||||
|
|
||||||
|
|
||||||
Frequently Asked Questions
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
The list of Frequently Asked Questions (*FAQ*) is :doc:`available here <faq>`.
|
|
||||||
|
|
||||||
|
|
||||||
Cool integrations for kitty with other CLI tools
|
|
||||||
--------------------------------------------------
|
|
||||||
|
|
||||||
kitty provides extremely powerful interfaces such as :doc:`remote-control` and
|
|
||||||
:doc:`kittens/custom` and :doc:`kittens/icat`
|
|
||||||
that allow it to be integrated with other tools seamlessly. For a list of such
|
|
||||||
user created integrations, see: :doc:`integrations`.
|
|
||||||
|
|
||||||
.. _completion:
|
|
||||||
|
|
||||||
Completion for kitty
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
|kitty| comes with completion for the ``kitty`` command for popular shells.
|
|
||||||
|
|
||||||
|
|
||||||
bash
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
Add the following to your :file:`~/.bashrc`
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
source <(kitty + complete setup bash)
|
|
||||||
|
|
||||||
Older versions of bash (for example, v3.2) do not support
|
|
||||||
process substitution with the source command, in which
|
|
||||||
case you can try an alternative:
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$(kitty + complete setup bash)"
|
|
||||||
|
|
||||||
|
|
||||||
zsh
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
Add the following to your :file:`~/.zshrc`
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
autoload -Uz compinit
|
|
||||||
compinit
|
|
||||||
# Completion for kitty
|
|
||||||
kitty + complete setup zsh | source /dev/stdin
|
|
||||||
|
|
||||||
The important thing above is to make sure the call to |kitty| to load the zsh
|
|
||||||
completions happens after the call to :file:`compinit`.
|
|
||||||
|
|
||||||
|
|
||||||
fish
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
For versions of fish earlier than 3.0.0, add the following to your
|
|
||||||
:file:`~/.config/fish/config.fish`. Later versions source completions by default.
|
|
||||||
|
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
kitty + complete setup fish | source
|
|
||||||
|
|
||||||
|
|
||||||
Changelog
|
|
||||||
------------------
|
|
||||||
|
|
||||||
See :doc:`changelog`.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:glob:
|
|
||||||
|
|
||||||
*
|
|
||||||
kittens/*
|
|
||||||
generated/rc
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
:tocdepth: 2
|
||||||
|
|
||||||
Integrations with other tools
|
Integrations with other tools
|
||||||
================================
|
================================
|
||||||
|
|
||||||
@@ -12,149 +14,245 @@ Image and document viewers
|
|||||||
Powered by kitty's :doc:`graphics-protocol` there exist many tools for viewing
|
Powered by kitty's :doc:`graphics-protocol` there exist many tools for viewing
|
||||||
images and other types of documents directly in your terminal, even over SSH.
|
images and other types of documents directly in your terminal, even over SSH.
|
||||||
|
|
||||||
|
.. _tool_termpdf:
|
||||||
|
|
||||||
`termpdf.py <https://github.com/dsanson/termpdf.py>`_
|
`termpdf.py <https://github.com/dsanson/termpdf.py>`_
|
||||||
a terminal PDF/DJVU/CBR viewer
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A terminal PDF/DJVU/CBR viewer
|
||||||
|
|
||||||
|
.. _tool_mdcat:
|
||||||
|
|
||||||
`mdcat <https://github.com/lunaryorn/mdcat>`_
|
`mdcat <https://github.com/lunaryorn/mdcat>`_
|
||||||
Display markdown files nicely formatted with images in the terminal
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Display markdown files nicely formatted with images in the terminal
|
||||||
|
|
||||||
|
.. _tool_ranger:
|
||||||
|
|
||||||
`ranger <https://github.com/ranger/ranger>`_
|
`ranger <https://github.com/ranger/ranger>`_
|
||||||
a terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||||
|
|
||||||
|
.. _tool_nnn:
|
||||||
|
|
||||||
`nnn <https://github.com/jarun/nnn/>`_
|
`nnn <https://github.com/jarun/nnn/>`_
|
||||||
another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||||
|
|
||||||
|
.. _tool_hunter:
|
||||||
|
|
||||||
`hunter <https://github.com/rabite0/hunter>`_
|
`hunter <https://github.com/rabite0/hunter>`_
|
||||||
another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||||
|
|
||||||
|
.. _tool_koneko:
|
||||||
|
|
||||||
`koneko <https://github.com/twenty5151/koneko>`_
|
`koneko <https://github.com/twenty5151/koneko>`_
|
||||||
browse images from the pixiv artist community directly in kitty.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Browse images from the pixiv artist community directly in kitty.
|
||||||
|
|
||||||
|
.. _tool_viu:
|
||||||
|
|
||||||
`viu <https://github.com/atanunq/viu>`_
|
`viu <https://github.com/atanunq/viu>`_
|
||||||
view images in the terminal, similar to kitty's icat.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
View images in the terminal, similar to kitty's icat.
|
||||||
|
|
||||||
|
.. _tool_nb:
|
||||||
|
|
||||||
|
|
||||||
`nb <https://github.com/xwmx/nb>`_
|
`nb <https://github.com/xwmx/nb>`_
|
||||||
command line and local web note-taking, bookmarking, archiving, and
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
knowledge base application that uses kitty's graphics protocol for images.
|
command line and local web note-taking, bookmarking, archiving, and
|
||||||
|
knowledge base application that uses kitty's graphics protocol for images.
|
||||||
|
|
||||||
|
.. _tool_w3m:
|
||||||
|
|
||||||
`w3m <https://github.com/tats/w3m>`_
|
`w3m <https://github.com/tats/w3m>`_
|
||||||
A text mode WWW browser that supports kitty's graphics protocol to display
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
images.
|
A text mode WWW browser that supports kitty's graphics protocol to display
|
||||||
|
images.
|
||||||
|
|
||||||
|
.. _tool_timg:
|
||||||
|
|
||||||
`timg <https://github.com/hzeller/timg>`_
|
`timg <https://github.com/hzeller/timg>`_
|
||||||
A terminal image and video viewer, that displays static and animated
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
images or plays videos. Fast multi-threaded loading, JPEG exif rotation,
|
A terminal image and video viewer, that displays static and animated
|
||||||
grid view and connecting to the webcam make it a versatile terminal utility.
|
images or plays videos. Fast multi-threaded loading, JPEG exif rotation,
|
||||||
|
grid view and connecting to the webcam make it a versatile terminal utility.
|
||||||
|
|
||||||
|
|
||||||
System and data visualisation tools
|
System and data visualisation tools
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
.. _tool_neofetch:
|
||||||
|
|
||||||
`neofetch <https://github.com/dylanaraps/neofetch>`_
|
`neofetch <https://github.com/dylanaraps/neofetch>`_
|
||||||
A command line system information tool that shows images using kitty's graphics protocol
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A command line system information tool that shows images using kitty's graphics protocol
|
||||||
|
|
||||||
|
.. _tool_matplotlib:
|
||||||
|
|
||||||
`matplotlib <https://github.com/jktr/matplotlib-backend-kitty>`_
|
`matplotlib <https://github.com/jktr/matplotlib-backend-kitty>`_
|
||||||
show matplotlib plots directly in kitty
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Show matplotlib plots directly in kitty
|
||||||
|
|
||||||
|
.. _tool_KittyTerminalImage:
|
||||||
|
|
||||||
`KittyTerminalImages.jl <https://github.com/simonschoelly/KittyTerminalImages.jl>`_
|
`KittyTerminalImages.jl <https://github.com/simonschoelly/KittyTerminalImages.jl>`_
|
||||||
show images from Julia directly in kitty
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Show images from Julia directly in kitty
|
||||||
|
|
||||||
|
.. _tool_euporie:
|
||||||
|
|
||||||
`euporie <https://github.com/joouha/euporie>`_
|
`euporie <https://github.com/joouha/euporie>`_
|
||||||
a text-based user interface for running and editing Jupyter notebooks,
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
powered by kitty's graphics protocol for displaying plots
|
A text-based user interface for running and editing Jupyter notebooks,
|
||||||
|
powered by kitty's graphics protocol for displaying plots
|
||||||
|
|
||||||
|
.. _tool_gnuplot:
|
||||||
|
|
||||||
`gnuplot <http://www.gnuplot.info/>`_
|
`gnuplot <http://www.gnuplot.info/>`_
|
||||||
a graphing and data visualization tool that can be made to display its
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
output in kitty with the following bash snippet::
|
|
||||||
|
|
||||||
function iplot {
|
A graphing and data visualization tool that can be made to display its
|
||||||
cat <<EOF | gnuplot
|
output in kitty with the following bash snippet:
|
||||||
set terminal pngcairo enhanced font 'Fira Sans,10'
|
|
||||||
set autoscale
|
|
||||||
set samples 1000
|
|
||||||
set output '|kitty +kitten icat --stdin yes'
|
|
||||||
set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"#fdf6e3" behind
|
|
||||||
plot $@
|
|
||||||
set output '/dev/null'
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
Add this to bashrc and then to plot a function, simply do::
|
.. code-block:: sh
|
||||||
|
|
||||||
iplot 'sin(x*3)*exp(x*.2)'
|
function iplot {
|
||||||
|
cat <<EOF | gnuplot
|
||||||
|
set terminal pngcairo enhanced font 'Fira Sans,10'
|
||||||
|
set autoscale
|
||||||
|
set samples 1000
|
||||||
|
set output '|kitty +kitten icat --stdin yes'
|
||||||
|
set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"#fdf6e3" behind
|
||||||
|
plot $@
|
||||||
|
set output '/dev/null'
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
Add this to bashrc and then to plot a function, simply do:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
iplot 'sin(x*3)*exp(x*.2)'
|
||||||
|
|
||||||
|
.. tool_onefetch:
|
||||||
|
|
||||||
`onefetch <https://github.com/o2sh/onefetch>`_
|
`onefetch <https://github.com/o2sh/onefetch>`_
|
||||||
a tool to fetch information about your git repositories
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A tool to fetch information about your git repositories
|
||||||
|
|
||||||
|
.. tool_patat:
|
||||||
|
|
||||||
`patat <https://github.com/jaspervdj/patat>`_
|
`patat <https://github.com/jaspervdj/patat>`_
|
||||||
terminal based presentations using pandoc and kitty's image protocol for
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
images
|
Terminal based presentations using pandoc and kitty's image protocol for
|
||||||
|
images
|
||||||
|
|
||||||
|
.. tool_wttr:
|
||||||
|
|
||||||
`wttr.in <https://github.com/chubin/wttr.in>`_
|
`wttr.in <https://github.com/chubin/wttr.in>`_
|
||||||
a tool to display weather information in your terminal with curl
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A tool to display weather information in your terminal with curl
|
||||||
|
|
||||||
|
.. tool_wl_clipboard:
|
||||||
|
|
||||||
`wl-clipboard-manager <https://github.com/maximbaz/wl-clipboard-manager>`_
|
`wl-clipboard-manager <https://github.com/maximbaz/wl-clipboard-manager>`_
|
||||||
view and manage the system clipboard under Wayland in your kitty terminal
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
View and manage the system clipboard under Wayland in your kitty terminal
|
||||||
|
|
||||||
|
.. tool_dmenu_term:
|
||||||
|
|
||||||
`dmenu-term <https://github.com/maximbaz/dmenu-term>`_
|
`dmenu-term <https://github.com/maximbaz/dmenu-term>`_
|
||||||
run applications on your system with fuzzy find inside a kitty window
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Run applications on your system with fuzzy find inside a kitty window
|
||||||
|
|
||||||
|
|
||||||
Editor integration
|
Editor integration
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
kitty can be integrated into many different terminal editors to add features
|
|kitty| can be integrated into many different terminal editors to add features
|
||||||
such a split windows, previews, REPLs etc.
|
such a split windows, previews, REPLs etc.
|
||||||
|
|
||||||
|
.. tool_kakoune:
|
||||||
|
|
||||||
`kakoune <https://kakoune.org/>`_
|
`kakoune <https://kakoune.org/>`_
|
||||||
integrates with kitty to use native kitty windows for its windows/panels and REPLs.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
integrates with kitty to use native kitty windows for its windows/panels and REPLs.
|
||||||
|
|
||||||
|
.. tool_vim_slime:
|
||||||
|
|
||||||
`vim-slime <https://github.com/jpalardy/vim-slime#kitty>`_
|
`vim-slime <https://github.com/jpalardy/vim-slime#kitty>`_
|
||||||
uses kitty remote control for a Lisp REPL.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
uses kitty remote control for a Lisp REPL.
|
||||||
|
|
||||||
|
.. tool_vim_kitty_navigator:
|
||||||
|
|
||||||
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||||
allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
||||||
|
|
||||||
|
.. tool_vim_test:
|
||||||
|
|
||||||
`vim-test <https://github.com/vim-test/vim-test>`_
|
`vim-test <https://github.com/vim-test/vim-test>`_
|
||||||
allows easily running tests in a terminal window
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Allows easily running tests in a terminal window
|
||||||
|
|
||||||
|
.. tool_hologram:
|
||||||
|
|
||||||
`hologram.nvim <https://github.com/edluffy/hologram.nvim>`_
|
`hologram.nvim <https://github.com/edluffy/hologram.nvim>`_
|
||||||
terminal image viewer for nvim
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Terminal image viewer for nvim
|
||||||
|
|
||||||
|
|
||||||
Scrollback manipulation
|
Scrollback manipulation
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
.. tool_kitty_search:
|
||||||
|
|
||||||
`kitty-search <https://github.com/trygveaa/kitty-kitten-search>`_
|
`kitty-search <https://github.com/trygveaa/kitty-kitten-search>`_
|
||||||
Live incremental search of the scrollback buffer.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Live incremental search of the scrollback buffer.
|
||||||
|
|
||||||
|
.. tool_kitty_grab:
|
||||||
|
|
||||||
`kitty-grab <https://github.com/yurikhan/kitty_grab>`_
|
`kitty-grab <https://github.com/yurikhan/kitty_grab>`_
|
||||||
keyboard based text selection for the kitty scrollback buffer.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Keyboard based text selection for the kitty scrollback buffer.
|
||||||
|
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
.. tool_kitty_smart_tab:
|
||||||
|
|
||||||
`kitty-smart-tab <https://github.com/yurikhan/kitty-smart-tab>`_
|
`kitty-smart-tab <https://github.com/yurikhan/kitty-smart-tab>`_
|
||||||
use keys to either control tabs or pass them onto running applications if
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
no tabs are present
|
use keys to either control tabs or pass them onto running applications if
|
||||||
|
no tabs are present
|
||||||
|
|
||||||
|
.. tool_kitty_smart_scroll:
|
||||||
|
|
||||||
`kitty-smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
`kitty-smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||||
use keys to either scroll or pass them onto running applications if
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
no scrollback buffer is present
|
use keys to either scroll or pass them onto running applications if
|
||||||
|
no scrollback buffer is present
|
||||||
|
|
||||||
`reload keybindings <https://github.com/kovidgoyal/kitty/issues/1292#issuecomment-582388769>`_
|
.. tool_kitti3:
|
||||||
reload key bindings from :file:`kitty.conf` without needing to restart
|
|
||||||
kitty
|
|
||||||
|
|
||||||
`kitti3 <https://github.com/LandingEllipse/kitti3>`_
|
`kitti3 <https://github.com/LandingEllipse/kitti3>`_
|
||||||
allow using kitty as a drop-down terminal under the i3 window manager
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
allow using kitty as a drop-down terminal under the i3 window manager
|
||||||
|
|
||||||
|
.. tool_weechat_hints:
|
||||||
|
|
||||||
`weechat-hints <https://github.com/GermainZ/kitty-weechat-hints>`_
|
`weechat-hints <https://github.com/GermainZ/kitty-weechat-hints>`_
|
||||||
URL hints kitten for WeeChat that works without having to use WeeChat's
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
raw-mode.
|
URL hints kitten for WeeChat that works without having to use WeeChat's
|
||||||
|
raw-mode.
|
||||||
|
|
||||||
|
.. tool_glkitty:
|
||||||
|
|
||||||
`glkitty <https://github.com/michaeljclark/glkitty>`_
|
`glkitty <https://github.com/michaeljclark/glkitty>`_
|
||||||
C library to draw OpenGL shaders in the terminal with a glgears demo
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
C library to draw OpenGL shaders in the terminal with a glgears demo
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
:orphan:
|
||||||
|
|
||||||
The kitty command line interface
|
The kitty command line interface
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
A protocol for comprehensive keyboard handling in terminals
|
Comprehensive keyboard handling in terminals
|
||||||
=================================================================
|
==============================================
|
||||||
|
|
||||||
There are various problems with the current state of keyboard handling in
|
There are various problems with the current state of keyboard handling in
|
||||||
terminals. They include:
|
terminals. They include:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
broadcast - type text in all kitty windows
|
broadcast
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
|
*Type text in all kitty windows simultaneously*
|
||||||
|
|
||||||
The ``broadcast`` kitten can be used to type text simultaneously in
|
The ``broadcast`` kitten can be used to type text simultaneously in
|
||||||
all kitty windows (or a subset as desired).
|
all kitty windows (or a subset as desired).
|
||||||
|
|
||||||
@@ -17,7 +19,4 @@ are selected.
|
|||||||
.. program:: kitty +kitten broadcast
|
.. program:: kitty +kitten broadcast
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
.. include:: /generated/cli-kitten-broadcast.rst
|
.. include:: /generated/cli-kitten-broadcast.rst
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
clipboard - copy/paste to the system clipboard
|
clipboard
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
|
*Copy/paste to the system clipboard from shell scripts*
|
||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +23,4 @@ use::
|
|||||||
.. program:: kitty +kitten clipboard
|
.. program:: kitty +kitten clipboard
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
.. include:: /generated/cli-kitten-clipboard.rst
|
.. include:: /generated/cli-kitten-clipboard.rst
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ terminal program, you can tell the kittens system to run the
|
|||||||
``handle_result()`` function without first running the ``main()`` function.
|
``handle_result()`` function without first running the ``main()`` function.
|
||||||
|
|
||||||
For example, here is a kitten that "zooms/unzooms" the current terminal window
|
For example, here is a kitten that "zooms/unzooms" the current terminal window
|
||||||
by switching to the stack layout or back to the previous layout.
|
by switching to the stack layout or back to the previous layout. This is
|
||||||
|
equivalent to the builtin :ref:`action-toggle_layout` action.
|
||||||
|
|
||||||
Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
kitty-diff - A fast side-by-side diff tool with syntax highlighting and images
|
kitty-diff
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
*A fast side-by-side diff tool with syntax highlighting and images*
|
||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
Major Features
|
Major Features
|
||||||
@@ -21,13 +23,10 @@ Major Features
|
|||||||
.. figure:: ../screenshots/diff.png
|
.. figure:: ../screenshots/diff.png
|
||||||
:alt: Screenshot, showing a sample diff
|
:alt: Screenshot, showing a sample diff
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing a sample diff
|
Screenshot, showing a sample diff
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
---------------
|
---------------
|
||||||
@@ -35,7 +34,7 @@ Installation
|
|||||||
Simply :ref:`install kitty <quickstart>`. You also need
|
Simply :ref:`install kitty <quickstart>`. You also need
|
||||||
to have either the `git <https://git-scm.com/>`_ program or the ``diff`` program
|
to have either the `git <https://git-scm.com/>`_ program or the ``diff`` program
|
||||||
installed. Additionally, for syntax highlighting to work,
|
installed. Additionally, for syntax highlighting to work,
|
||||||
`pygments <http://pygments.org/>`_ must be installed (note that pygments is
|
`pygments <https://pygments.org/>`_ must be installed (note that pygments is
|
||||||
included in the macOS kitty app).
|
included in the macOS kitty app).
|
||||||
|
|
||||||
|
|
||||||
@@ -121,8 +120,8 @@ Why does this work only in kitty?
|
|||||||
|
|
||||||
The diff kitten makes use of various features that are :doc:`kitty only
|
The diff kitten makes use of various features that are :doc:`kitty only
|
||||||
</protocol-extensions>`, such as the :doc:`kitty graphics protocol
|
</protocol-extensions>`, such as the :doc:`kitty graphics protocol
|
||||||
</graphics-protocol>`, the :ref:`extended keyboard protocol
|
</graphics-protocol>`, the :doc:`extended keyboard protocol
|
||||||
<extended-key-protocol>`, etc. It also leverages terminal program
|
</keyboard-protocol>`, etc. It also leverages terminal program
|
||||||
infrastructure I created for all of kitty's other kittens to reduce the amount
|
infrastructure I created for all of kitty's other kittens to reduce the amount
|
||||||
of code needed (the entire implementation is under 2000 lines of code).
|
of code needed (the entire implementation is under 2000 lines of code).
|
||||||
|
|
||||||
@@ -143,9 +142,6 @@ configuration directives.
|
|||||||
.. include:: /generated/conf-kitten-diff.rst
|
.. include:: /generated/conf-kitten-diff.rst
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. include:: /generated/cli-kitten-diff.rst
|
.. include:: /generated/cli-kitten-diff.rst
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ browser.
|
|||||||
.. figure:: ../screenshots/hints_mode.png
|
.. figure:: ../screenshots/hints_mode.png
|
||||||
:alt: URL hints mode
|
:alt: URL hints mode
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
URL hints mode
|
URL hints mode
|
||||||
|
|
||||||
@@ -88,8 +88,14 @@ Now run kitty with::
|
|||||||
When you press the :kbd:`F1` key you will be able to select a word to
|
When you press the :kbd:`F1` key you will be able to select a word to
|
||||||
look it up in the Google dictionary.
|
look it up in the Google dictionary.
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-hints.rst
|
.. include:: ../generated/cli-kitten-hints.rst
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
To avoid having to specify the same command line options on ever invocation,
|
||||||
|
you can use the :opt:`kitten_alias` option in :file:`kitty.conf` to create aliases
|
||||||
|
that have common sets of options. For example::
|
||||||
|
|
||||||
|
kitten_alias myhints hints --alphabet qfjdkslaureitywovmcxzpq1234567890
|
||||||
|
|
||||||
|
Documentation for the full set of options is below.
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ Then, for example, for ZSH, add the following to :file:`.zshrc`::
|
|||||||
compdef _rg hg
|
compdef _rg hg
|
||||||
|
|
||||||
To learn more about kitty's powerful framework for customizing URL click
|
To learn more about kitty's powerful framework for customizing URL click
|
||||||
actions, :doc:`see here <../open_actions>`.
|
actions, :doc:`see here </open_actions>`.
|
||||||
|
|
||||||
Hopefully, someday this functionality will make it into some `upstream grep
|
Hopefully, someday this functionality will make it into some `upstream grep
|
||||||
<https://github.com/BurntSushi/ripgrep/issues/665>`_
|
<https://github.com/BurntSushi/ripgrep/issues/665>`_
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
icat - Display images in the terminal
|
icat
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
|
*Display images in the terminal*
|
||||||
|
|
||||||
The ``icat`` kitten can be used to display arbitrary images in the |kitty|
|
The ``icat`` kitten can be used to display arbitrary images in the |kitty|
|
||||||
terminal. Using it is as simple as::
|
terminal. Using it is as simple as::
|
||||||
|
|
||||||
@@ -35,7 +37,4 @@ The ``icat`` kitten has various command line arguments to allow it to be used
|
|||||||
from inside other programs to display images. In particular, :option:`--place`,
|
from inside other programs to display images. In particular, :option:`--place`,
|
||||||
:option:`--detect-support` and :option:`--print-window-size`.
|
:option:`--detect-support` and :option:`--print-window-size`.
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
.. include:: /generated/cli-kitten-icat.rst
|
.. include:: /generated/cli-kitten-icat.rst
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using terminal programs instead of GUI toolkits.
|
|||||||
.. figure:: ../screenshots/panel.png
|
.. figure:: ../screenshots/panel.png
|
||||||
:alt: Screenshot, showing a sample panel
|
:alt: Screenshot, showing a sample panel
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing a sample panel
|
Screenshot, showing a sample panel
|
||||||
|
|
||||||
@@ -37,7 +37,4 @@ print out ``Hello, world!``. You can make the terminal program as complex as
|
|||||||
you like, as demonstrated in the screenshot above.
|
you like, as demonstrated in the screenshot above.
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-panel.rst
|
.. include:: ../generated/cli-kitten-panel.rst
|
||||||
|
|||||||
@@ -15,7 +15,4 @@ for *XTGETTCAP* to see the syntax for the escape code and read the source
|
|||||||
of this kitten to find the values of the keys for the various queries.
|
of this kitten to find the values of the keys for the various queries.
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-query_terminal.rst
|
.. include:: ../generated/cli-kitten-query_terminal.rst
|
||||||
|
|||||||
@@ -11,15 +11,16 @@ Then hold down :kbd:`ctrl+shift` and click the name of the file.
|
|||||||
.. figure:: ../screenshots/remote_file.png
|
.. figure:: ../screenshots/remote_file.png
|
||||||
:alt: Remote file actions
|
:alt: Remote file actions
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Remote file actions
|
Remote file actions
|
||||||
|
|
||||||
|kitty| will ask you what you want to do with the remote file. You can choose
|
|kitty| will ask you what you want to do with the remote file. You can choose
|
||||||
to *Edit* it in which case kitty will download it and open it locally in your
|
to *Edit* it in which case kitty will download it and open it locally in your
|
||||||
``EDITOR``. As you make changes to the file, they are automatically transferred
|
:envvar:`EDITOR`. As you make changes to the file, they are automatically
|
||||||
to the remote computer. Note that this happens without needing to install *any*
|
transferred to the remote computer. Note that this happens without needing
|
||||||
special software on the server, beyond ``ls`` that supports hyperlinks.
|
to install *any* special software on the server, beyond ``ls`` that supports
|
||||||
|
hyperlinks.
|
||||||
|
|
||||||
.. versionadded:: 0.19.0
|
.. versionadded:: 0.19.0
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Press :sc:`input_unicode_character` to start the unicode input widget, shown bel
|
|||||||
.. figure:: ../screenshots/unicode.png
|
.. figure:: ../screenshots/unicode.png
|
||||||
:alt: A screenshot of the unicode input widget
|
:alt: A screenshot of the unicode input widget
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
A screenshot of the unicode input widget
|
A screenshot of the unicode input widget
|
||||||
|
|
||||||
@@ -28,7 +28,4 @@ You can switch between modes using either the function keys or by pressing
|
|||||||
:kbd:`Ctrl+Shift+Tab`.
|
:kbd:`Ctrl+Shift+Tab`.
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
.. include:: ../generated/cli-kitten-unicode_input.rst
|
.. include:: ../generated/cli-kitten-unicode_input.rst
|
||||||
|
|||||||
66
docs/kittens_intro.rst
Normal file
66
docs/kittens_intro.rst
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
.. _kittens:
|
||||||
|
|
||||||
|
Extend with kittens
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:glob:
|
||||||
|
|
||||||
|
kittens/icat
|
||||||
|
kittens/diff
|
||||||
|
kittens/unicode-input
|
||||||
|
kittens/hints
|
||||||
|
kittens/remote_file
|
||||||
|
kittens/hyperlinked_grep
|
||||||
|
kittens/custom
|
||||||
|
kittens/*
|
||||||
|
|
||||||
|
|kitty| has a framework for easily creating terminal programs that make use of
|
||||||
|
its advanced features. These programs are called kittens. They are used both
|
||||||
|
to add features to |kitty| itself and to create useful standalone programs.
|
||||||
|
Some prominent kittens:
|
||||||
|
|
||||||
|
:doc:`icat <kittens/icat>`
|
||||||
|
Display images in the terminal
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`diff <kittens/diff>`
|
||||||
|
A fast, side-by-side diff for the terminal with syntax highlighting and
|
||||||
|
images
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Unicode Input <kittens/unicode-input>`
|
||||||
|
Easily input arbitrary unicode characters in |kitty| by name or hex code.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Hints <kittens/hints>`
|
||||||
|
Select and open/paste/insert arbitrary text snippets such as URLs,
|
||||||
|
filenames, words, lines, etc. from the terminal screen.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Remote file <kittens/remote_file>`
|
||||||
|
Edit, open, or download remote files over SSH easily, by simply clicking on
|
||||||
|
the filename.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Hyperlinked grep <kittens/hyperlinked_grep>`
|
||||||
|
Search your files using `ripgrep <https://github.com/BurntSushi/ripgrep>`_
|
||||||
|
and open the results directly in your favorite editor in the terminal,
|
||||||
|
at the line containing the search result, simply by clicking on the result you want.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Broadcast <kittens/broadcast>`
|
||||||
|
Type in one :term:`kitty window <window>` and have it broadcast to all (or a subset) of
|
||||||
|
other :term:`kitty windows <window>`.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Panel <kittens/panel>`
|
||||||
|
Draw a GPU accelerated dock panel on your desktop showing the output
|
||||||
|
from an arbitrary terminal program.
|
||||||
|
|
||||||
|
|
||||||
|
:doc:`Clipboard <kittens/clipboard>`
|
||||||
|
Copy/paste to the clipboard from shell scripts, even over SSH.
|
||||||
|
|
||||||
|
You can also :doc:`Learn to create your own kittens <kittens/custom>`.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Launching programs in new windows/tabs
|
The :command:`launch` command
|
||||||
========================================
|
--------------------------------
|
||||||
|
|
||||||
.. program:: launch
|
.. program:: launch
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ The piping environment
|
|||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
When using :option:`launch --stdin-source`, the program to which the data is
|
When using :option:`launch --stdin-source`, the program to which the data is
|
||||||
piped has a special environment variable declared, ``KITTY_PIPE_DATA`` whose
|
piped has a special environment variable declared, :envvar:`KITTY_PIPE_DATA` whose
|
||||||
contents are::
|
contents are::
|
||||||
|
|
||||||
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
|
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Layouts
|
Arrange windows
|
||||||
============
|
-------------------
|
||||||
|
|
||||||
kitty has the ability to define its own windows that can be tiled next to each
|
kitty has the ability to define its own windows that can be tiled next to each
|
||||||
other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
||||||
@@ -8,7 +8,7 @@ other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
|||||||
.. figure:: screenshots/screenshot.png
|
.. figure:: screenshots/screenshot.png
|
||||||
:alt: Screenshot, showing three programs in the 'Tall' layout
|
:alt: Screenshot, showing three programs in the 'Tall' layout
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
|||||||
.. figure:: screenshots/splits.png
|
.. figure:: screenshots/splits.png
|
||||||
:alt: Screenshot, showing windows in the 'Splits' layout
|
:alt: Screenshot, showing windows in the 'Splits' layout
|
||||||
:align: center
|
:align: center
|
||||||
:scale: 100%
|
:width: 100%
|
||||||
|
|
||||||
Screenshot, showing windows with arbitrary arrangement in the 'Splits'
|
Screenshot, showing windows with arbitrary arrangement in the 'Splits'
|
||||||
layout
|
layout
|
||||||
@@ -27,9 +27,6 @@ you can switch layouts using :sc:`next_layout`. To control which layouts
|
|||||||
are available use :opt:`enabled_layouts`, the first listed layout becomes
|
are available use :opt:`enabled_layouts`, the first listed layout becomes
|
||||||
the default. Individual layouts and how to use them are described below.
|
the default. Individual layouts and how to use them are described below.
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
|
|
||||||
The Stack Layout
|
The Stack Layout
|
||||||
------------------
|
------------------
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
Marks
|
Mark text on screen
|
||||||
=================
|
---------------------
|
||||||
|
|
||||||
|
|
||||||
kitty has the ability to mark text on the screen based on regular expressions.
|
kitty has the ability to mark text on the screen based on regular expressions.
|
||||||
This can be useful to highlight words or phrases when browsing output from long
|
This can be useful to highlight words or phrases when browsing output from long
|
||||||
running programs or similar. Lets start with a few examples:
|
running programs or similar. Lets start with a few examples:
|
||||||
|
|
||||||
|
Examples
|
||||||
|
----------
|
||||||
|
|
||||||
Suppose we want to be able to highlight the word ERROR in the current window.
|
Suppose we want to be able to highlight the word ERROR in the current window.
|
||||||
Add the following to :file:`kitty.conf`::
|
Add the following to :file:`kitty.conf`::
|
||||||
|
|
||||||
@@ -89,12 +92,11 @@ The syntax of the :code:`toggle_marker` command is::
|
|||||||
|
|
||||||
Here :code:`marker-type` is one of:
|
Here :code:`marker-type` is one of:
|
||||||
|
|
||||||
* :code:`text` - simple substring matching
|
* :code:`text` - simple substring matching
|
||||||
* :code:`itext` - case-insensitive substring matching
|
* :code:`itext` - case-insensitive substring matching
|
||||||
* :code:`regex` - A python regular expression
|
* :code:`regex` - A python regular expression
|
||||||
* :code:`iregex` - A case-insensitive python regular expression
|
* :code:`iregex` - A case-insensitive python regular expression
|
||||||
* :code:`function` - An arbitrary function defined in a python file, see
|
* :code:`function` - An arbitrary function defined in a python file, see :ref:`marker_funcs`.
|
||||||
:ref:`marker_funcs`.
|
|
||||||
|
|
||||||
.. _marker_funcs:
|
.. _marker_funcs:
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
Customizing the actions taken when clicking on links
|
Scripting the mouse click
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
|kitty| has support for `terminal hyperlinks <https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`_. These
|
|kitty| has support for `terminal hyperlinks
|
||||||
|
<https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`_. These
|
||||||
are generated by many terminal programs, such as ``ls``, ``gcc``, ``systemd``,
|
are generated by many terminal programs, such as ``ls``, ``gcc``, ``systemd``,
|
||||||
``mdcat``, etc. You can customize exactly what happens when clicking on these hyperlinks
|
:ref:`tool_mdcat`, etc. You can customize exactly what happens when clicking on these
|
||||||
in |kitty|.
|
hyperlinks in |kitty|.
|
||||||
|
|
||||||
You can tell kitty to take arbitrarily many, complex actions
|
You can tell kitty to take arbitrarily many, complex actions
|
||||||
when a link is clicked. Let us illustrate with some examples, first. Create
|
when a link is clicked. Let us illustrate with some examples, first. Create
|
||||||
@@ -85,7 +86,7 @@ lines. The various available criteria are:
|
|||||||
:file:`mime.types` in the kitty configuration directory. Useful if your
|
:file:`mime.types` in the kitty configuration directory. Useful if your
|
||||||
system MIME database does not have definitions you need. This file is
|
system MIME database does not have definitions you need. This file is
|
||||||
in the standard format of one definition per line, like: ``text/plain rst
|
in the standard format of one definition per line, like: ``text/plain rst
|
||||||
md``.
|
md``. Note that the MIME type for directories is ``inode/directory``.
|
||||||
|
|
||||||
``ext``
|
``ext``
|
||||||
A comma separated list of file extensions, for example: ``jpeg, tar.gz``
|
A comma separated list of file extensions, for example: ``jpeg, tar.gz``
|
||||||
|
|||||||
283
docs/overview.rst
Normal file
283
docs/overview.rst
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
Overview
|
||||||
|
==============
|
||||||
|
|
||||||
|
Design philosophy
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|kitty| is designed for power keyboard users. To that end all its controls
|
||||||
|
work with the keyboard (although it fully supports mouse interactions as
|
||||||
|
well). Its configuration is a simple, human editable, single file for
|
||||||
|
easy reproducibility (I like to store configuration in source control).
|
||||||
|
|
||||||
|
The code in |kitty| is designed to be simple, modular and hackable. It is
|
||||||
|
written in a mix of C (for performance sensitive parts) and Python (for
|
||||||
|
easy hackability of the UI). It does not depend on any large and complex
|
||||||
|
UI toolkit, using only OpenGL for rendering everything.
|
||||||
|
|
||||||
|
Finally, |kitty| is designed from the ground up to support all modern
|
||||||
|
terminal features, such as unicode, true color, bold/italic fonts, text
|
||||||
|
formatting, etc. It even extends existing text formatting escape codes,
|
||||||
|
to add support for features not available elsewhere, such as colored and
|
||||||
|
styled (curly) underlines. One of the design goals of |kitty| is to be
|
||||||
|
easily extensible so that new features can be added in the future with
|
||||||
|
relatively little effort.
|
||||||
|
|
||||||
|
.. include:: basic.rst
|
||||||
|
|
||||||
|
|
||||||
|
Configuring kitty
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|kitty| is highly configurable, everything from keyboard shortcuts to
|
||||||
|
painting frames-per-second. Press :sc:`edit_config_file` in kitty
|
||||||
|
to open its fully commented sample config file in your text editor.
|
||||||
|
For details see the :doc:`configuration docs <conf>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
conf
|
||||||
|
|
||||||
|
|
||||||
|
.. _layouts:
|
||||||
|
|
||||||
|
Layouts
|
||||||
|
----------
|
||||||
|
|
||||||
|
A :term:`layout` is an arrangement of multiple :term:`kitty windows <window>`
|
||||||
|
inside a top-level :term:`OS window <os_window>`. The layout manages all its
|
||||||
|
windows automatically, resizing and moving them as needed. You can create a new
|
||||||
|
:term:`window` using the :sc:`new_window` key combination.
|
||||||
|
|
||||||
|
Currently, there are seven layouts available:
|
||||||
|
|
||||||
|
* **Fat** -- One (or optionally more) windows are shown full width on the top, the rest of the windows are shown side-by-side on the bottom
|
||||||
|
* **Grid** -- All windows are shown in a grid
|
||||||
|
* **Horizontal** -- All windows are shown side-by-side
|
||||||
|
* **Splits** -- Windows arranged in arbitrary patterns created using horizontal and vertical splits
|
||||||
|
* **Stack** -- Only a single maximized window is shown at a time
|
||||||
|
* **Tall** -- One (or optionally more) windows are shown full height on the left, the rest of the windows are shown one below the other on the right
|
||||||
|
* **Vertical** -- All windows are shown one below the other
|
||||||
|
|
||||||
|
By default, all layouts are enabled and you can switch between layouts using
|
||||||
|
the :sc:`next_layout` key combination. You can also create shortcuts to select
|
||||||
|
particular layouts, and choose which layouts you want to enable/disable, see
|
||||||
|
:ref:`conf-kitty-shortcuts.layout` for examples. The first layout listed in
|
||||||
|
:opt:`enabled_layouts` becomes the default layout.
|
||||||
|
|
||||||
|
For more details on the layouts and how to use them see :doc:`the documentation
|
||||||
|
<layouts>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
layouts
|
||||||
|
|
||||||
|
Extending kitty
|
||||||
|
------------------
|
||||||
|
|
||||||
|
kitty has a powerful framework for scripting. You can create small terminal
|
||||||
|
programs called :doc:`kittens <kittens_intro>`. These can used to add features
|
||||||
|
to kitty, for example, :doc:`editing remote files <kittens/remote_file>` or
|
||||||
|
:doc:`inputting unicode characters <kittens/unicode-input>`. They can also be
|
||||||
|
used to create programs that leverage kitty's powerful features, for example,
|
||||||
|
:doc:`viewing images <kittens/icat>` or :doc:`diffing files with images
|
||||||
|
<kittens/diff>`.
|
||||||
|
|
||||||
|
You can :doc:`create your own kittens to scratch your own itches
|
||||||
|
<kittens/custom>`.
|
||||||
|
|
||||||
|
For a list of all the builtin kittens, :ref:`see here <kittens>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
kittens_intro
|
||||||
|
|
||||||
|
|
||||||
|
Remote control
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|kitty| has a very powerful system that allows you to control it from the
|
||||||
|
:doc:`shell prompt, even over SSH <remote-control>`. You can change colors,
|
||||||
|
fonts, open new :term:`windows <window>`, :term:`tabs <tab>`, set their titles,
|
||||||
|
change window layout, get text
|
||||||
|
from one window and send text to another, etc, etc. The possibilities are
|
||||||
|
endless. See the :doc:`tutorial <remote-control>` to get started.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
remote-control
|
||||||
|
|
||||||
|
|
||||||
|
.. _sessions:
|
||||||
|
|
||||||
|
Startup Sessions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
You can control the :term:`tabs <tab>`, `:term:`kitty window <window>` layout,
|
||||||
|
working directory, startup programs,
|
||||||
|
etc. by creating a "session" file and using the :option:`kitty --session`
|
||||||
|
command line flag or the :opt:`startup_session` option in :file:`kitty.conf`.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: session
|
||||||
|
|
||||||
|
# Set the layout for the current tab
|
||||||
|
layout tall
|
||||||
|
# Set the working directory for windows in the current tab
|
||||||
|
cd ~
|
||||||
|
# Create a window and run the specified command in it
|
||||||
|
launch zsh
|
||||||
|
# Create a window with some environment variables set and run
|
||||||
|
# vim in it
|
||||||
|
launch --env FOO=BAR vim
|
||||||
|
# Set the title for the next window
|
||||||
|
launch --title "Chat with x" irssi --profile x
|
||||||
|
|
||||||
|
# Create a new tab (the part after new_tab is the optional tab
|
||||||
|
# name which will be displayed in the tab bar, if omitted, the
|
||||||
|
# title of the active window will be used instead)
|
||||||
|
new_tab my tab
|
||||||
|
cd ~/somewhere
|
||||||
|
# Set the layouts allowed in this tab
|
||||||
|
enabled_layouts tall, stack
|
||||||
|
# Set the current layout
|
||||||
|
layout stack
|
||||||
|
launch zsh
|
||||||
|
|
||||||
|
# Create a new OS window
|
||||||
|
new_os_window
|
||||||
|
# set new window size to 80x25 cells
|
||||||
|
os_window_size 80c 25c
|
||||||
|
# set the --class for the new OS window
|
||||||
|
os_window_class mywindow
|
||||||
|
launch sh
|
||||||
|
# Make the current window the active (focused) window
|
||||||
|
focus
|
||||||
|
launch emacs
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The :doc:`launch <launch>` command when used in a session file
|
||||||
|
cannot create new OS windows, or tabs.
|
||||||
|
|
||||||
|
|
||||||
|
Creating tabs/windows
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
kitty can be told to run arbitrary programs in new :term:`tabs <tab>`,
|
||||||
|
:term:`windows <window>` or :term:`overlays <overlay>` at a keypress.
|
||||||
|
To learn how to do this, see :doc:`here <launch>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
launch
|
||||||
|
|
||||||
|
|
||||||
|
Mouse features
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* You can click on a URL to open it in a browser.
|
||||||
|
* You can double click to select a word and then drag to select more words.
|
||||||
|
* You can triple click to select a line and then drag to select more lines.
|
||||||
|
* You can triple click while holding :kbd:`ctrl+alt` to select from clicked
|
||||||
|
point to end of line.
|
||||||
|
* You can right click to extend a previous selection.
|
||||||
|
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
||||||
|
columns.
|
||||||
|
* Selecting text automatically copies it to the primary clipboard (on
|
||||||
|
platforms with a primary clipboard).
|
||||||
|
* You can middle click to paste from the primary clipboard (on platforms
|
||||||
|
with a primary clipboard).
|
||||||
|
* You can select text with kitty even when a terminal program has grabbed
|
||||||
|
the mouse by holding down the :kbd:`shift` key.
|
||||||
|
|
||||||
|
All these actions can be customized in :file:`kitty.conf` as described
|
||||||
|
:ref:`here <conf-kitty-mouse.mousemap>`.
|
||||||
|
|
||||||
|
You can also customize what happens when clicking on :term:`hyperlinks` in kitty,
|
||||||
|
having it open files in your editor, download remote files, open things
|
||||||
|
in your browser, etc.
|
||||||
|
|
||||||
|
For details, see :doc:`here <open_actions>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
open_actions
|
||||||
|
|
||||||
|
Font control
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
|kitty| has extremely flexible and powerful font selection features. You can
|
||||||
|
specify individual families for the regular, bold, italic and bold+italic
|
||||||
|
fonts. You can even specify specific font families for specific ranges of
|
||||||
|
unicode characters. This allows precise control over text rendering. It can
|
||||||
|
come in handy for applications like powerline, without the need to use patched
|
||||||
|
fonts. See the various font related configuration directives in
|
||||||
|
:ref:`conf-kitty-fonts`.
|
||||||
|
|
||||||
|
|
||||||
|
.. _scrollback:
|
||||||
|
|
||||||
|
The scrollback buffer
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
|kitty| supports scrolling back to view history, just like most terminals. You
|
||||||
|
can use either keyboard shortcuts or the mouse scroll wheel to do so. However,
|
||||||
|
|kitty| has an extra, neat feature. Sometimes you need to explore the
|
||||||
|
scrollback buffer in more detail, maybe search for some text or refer to it
|
||||||
|
side-by-side while typing in a follow-up command. |kitty| allows you to do this
|
||||||
|
by pressing the :sc:`show_scrollback` key-combination, which will open the
|
||||||
|
scrollback buffer in your favorite pager program (which is ``less`` by default).
|
||||||
|
Colors and text formatting are preserved. You can explore the scrollback buffer
|
||||||
|
comfortably within the pager.
|
||||||
|
|
||||||
|
Additionally, you can pipe the contents of the scrollback buffer to an
|
||||||
|
arbitrary, command running in a new :term:`window`, :term:`tab` or :term:`overlay`,
|
||||||
|
for example::
|
||||||
|
|
||||||
|
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
|
||||||
|
|
||||||
|
Would open the scrollback buffer in a new :term:`window` when you press the :kbd:`F1`
|
||||||
|
key. See :sc:`show_scrollback` for details.
|
||||||
|
|
||||||
|
If you want to use it with an editor such as vim to get more powerful features,
|
||||||
|
you can see tips for doing so, in
|
||||||
|
`this thread <https://github.com/kovidgoyal/kitty/issues/719>`_.
|
||||||
|
|
||||||
|
If you wish to store very large amounts of scrollback to view using the piping or
|
||||||
|
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
||||||
|
option.
|
||||||
|
|
||||||
|
.. _cpbuf:
|
||||||
|
|
||||||
|
Multiple copy/paste buffers
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
In addition to being able to copy/paste from the system clipboard, in |kitty| you
|
||||||
|
can also setup an arbitrary number of copy paste buffers. To do so, simply add
|
||||||
|
something like the following to your :file:`kitty.conf`::
|
||||||
|
|
||||||
|
map f1 copy_to_buffer a
|
||||||
|
map f2 paste_from_buffer a
|
||||||
|
|
||||||
|
This will allow you to press :kbd:`F1` to copy the current selection to an
|
||||||
|
internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
|
||||||
|
names are arbitrary strings, so you can define as many such buffers as you
|
||||||
|
need.
|
||||||
|
|
||||||
|
|
||||||
|
Marks
|
||||||
|
-------------
|
||||||
|
|
||||||
|
kitty has the ability to mark text on the screen based on regular expressions.
|
||||||
|
This can be useful to highlight words or phrases when browsing output from long
|
||||||
|
running programs or similar. To learn how this feature works, see :doc:`marks`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
marks
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
|kitty| Performance
|
Performance
|
||||||
===================
|
===================
|
||||||
|
|
||||||
The main goals for |kitty| performance are user perceived latency while typing
|
The main goals for |kitty| performance are user perceived latency while typing
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
:orphan:
|
||||||
|
|
||||||
Working with the screen and history buffer contents
|
Working with the screen and history buffer contents
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Extensions to the xterm protocol
|
Terminal protocol extensions
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|kitty| has a few extensions to the xterm protocol, to enable advanced features.
|
|kitty| has extensions to the legacy terminal protocol, to enable advanced features.
|
||||||
These are typically in the form of new or re-purposed escape codes. While these
|
These are typically in the form of new or re-purposed escape codes. While these
|
||||||
extensions are currently |kitty| specific, it would be nice to get some of them
|
extensions are currently |kitty| specific, it would be nice to get some of them
|
||||||
adopted more broadly, to push the state of terminal emulators forward.
|
adopted more broadly, to push the state of terminal emulators forward.
|
||||||
@@ -19,301 +19,14 @@ If you wish to discuss these extensions, propose additions/changes to them
|
|||||||
please do so by opening issues in the `GitHub
|
please do so by opening issues in the `GitHub
|
||||||
<https://github.com/kovidgoyal/kitty/issues>`_ bug tracker.
|
<https://github.com/kovidgoyal/kitty/issues>`_ bug tracker.
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
Colored and styled underlines
|
.. toctree::
|
||||||
-------------------------------
|
:maxdepth: 1
|
||||||
|
|
||||||
|kitty| supports colored and styled (wavy) underlines. This is of particular
|
underlines
|
||||||
use in terminal editors such as vim and emacs to display red, wavy underlines
|
graphics-protocol
|
||||||
under mis-spelled words and/or syntax errors. This is done by re-purposing some
|
keyboard-protocol
|
||||||
SGR escape codes that are not used in modern terminals (`CSI codes
|
desktop-notifications
|
||||||
<https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences>`_)
|
unscroll
|
||||||
|
color-stack
|
||||||
To set the underline style::
|
deccara
|
||||||
|
|
||||||
<ESC>[4:0m # this is no underline
|
|
||||||
<ESC>[4:1m # this is a straight underline
|
|
||||||
<ESC>[4:2m # this is a double underline
|
|
||||||
<ESC>[4:3m # this is a curly underline
|
|
||||||
<ESC>[4:4m # this is a dotted underline (not implemented in kitty)
|
|
||||||
<ESC>[4:5m # this is a dashed underline (not implemented in kitty)
|
|
||||||
<ESC>[4m # this is a straight underline (for backwards compat)
|
|
||||||
<ESC>[24m # this is no underline (for backwards compat)
|
|
||||||
|
|
||||||
To set the underline color (this is reserved and as far as I can tell not actually used for anything)::
|
|
||||||
|
|
||||||
<ESC>[58...m
|
|
||||||
|
|
||||||
This works exactly like the codes ``38, 48`` that are used to set foreground and
|
|
||||||
background color respectively.
|
|
||||||
|
|
||||||
To reset the underline color (also previously reserved and unused)::
|
|
||||||
|
|
||||||
<ESC>[59m
|
|
||||||
|
|
||||||
The underline color must remain the same under reverse video, if it has a
|
|
||||||
color, if not, it should follow the foreground color.
|
|
||||||
|
|
||||||
To detect support for this feature in a terminal emulator, query the terminfo database
|
|
||||||
for the ``Su`` boolean capability.
|
|
||||||
|
|
||||||
Graphics rendering
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
See :doc:`/graphics-protocol` for a description
|
|
||||||
of this protocol to enable drawing of arbitrary raster images in the terminal.
|
|
||||||
|
|
||||||
|
|
||||||
.. _extended-key-protocol:
|
|
||||||
|
|
||||||
Keyboard handling
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
kitty has a :doc:`keyboard protocol <keyboard-protocol>` for reporting key
|
|
||||||
presses to terminal applications that solves all key handling issues in
|
|
||||||
terminal applications.
|
|
||||||
|
|
||||||
.. _ext_styles:
|
|
||||||
|
|
||||||
Setting text styles/colors in arbitrary regions of the screen
|
|
||||||
------------------------------------------------------------------
|
|
||||||
|
|
||||||
There already exists an escape code to set *some* text attributes in arbitrary
|
|
||||||
regions of the screen, `DECCARA
|
|
||||||
<https://vt100.net/docs/vt510-rm/DECCARA.html>`_. However, it is limited to
|
|
||||||
only a few attributes. |kitty| extends this to work with *all* SGR attributes.
|
|
||||||
So, for example, this can be used to set the background color in an arbitrary
|
|
||||||
region of the screen.
|
|
||||||
|
|
||||||
The motivation for this extension is the various problems with the existing
|
|
||||||
solution for erasing to background color, namely the *background color erase
|
|
||||||
(bce)* capability. See
|
|
||||||
`this discussion <https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545>`_
|
|
||||||
and `this FAQ <https://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`_
|
|
||||||
for a summary of problems with *bce*.
|
|
||||||
|
|
||||||
For example, to set the background color to blue in a
|
|
||||||
rectangular region of the screen from (3, 4) to (10, 11), you use::
|
|
||||||
|
|
||||||
<ESC>[2*x<ESC>[4;3;11;10;44$r<ESC>[*x
|
|
||||||
|
|
||||||
|
|
||||||
Saving and restoring colors
|
|
||||||
---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
It is often useful for a full screen application with its own color themes to
|
|
||||||
set the default foreground, background, selection and cursor colors and the
|
|
||||||
ANSI color table. This allows for various performance optimizations when
|
|
||||||
drawing the screen. The problem is that if the user previously used the escape
|
|
||||||
codes to change these colors herself, then running the full screen application
|
|
||||||
will lose her changes even after it exits. To avoid this, kitty introduces a
|
|
||||||
new pair of *OSC* escape codes to push and pop the current color values from a
|
|
||||||
stack::
|
|
||||||
|
|
||||||
<ESC>]30001<ESC>\ # push onto stack
|
|
||||||
<ESC>]30101<ESC>\ # pop from stack
|
|
||||||
|
|
||||||
These escape codes save/restore the colors, default
|
|
||||||
background, default foreground, selection background, selection foreground and
|
|
||||||
cursor color and the 256 colors of the ANSI color table.
|
|
||||||
|
|
||||||
.. note:: In July 2020, after several years, XTerm copied this protocol
|
|
||||||
extension, without acknowledgement, and using incompatible escape codes
|
|
||||||
(XTPUSHCOLORS, XTPOPCOLORS, XTREPORTCOLORS). And they decided to save not
|
|
||||||
just the dynamic colors but the entire ANSI color table. In the interests of
|
|
||||||
promoting interoperability, kitty added support for XTerm's escape codes as
|
|
||||||
well, and changed this extension to also save/restore the entire ANSI color
|
|
||||||
table.
|
|
||||||
|
|
||||||
|
|
||||||
Pasting to clipboard
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
|kitty| implements the OSC 52 escape code protocol to get/set the clipboard
|
|
||||||
contents (controlled via the :opt:`clipboard_control` setting). There is one
|
|
||||||
difference in kitty's implementation compared to some other terminal emulators.
|
|
||||||
|kitty| allows sending arbitrary amounts of text to the clipboard. It does so
|
|
||||||
by modifying the protocol slightly. Successive OSC 52 escape codes to set the
|
|
||||||
clipboard will concatenate, so::
|
|
||||||
|
|
||||||
<ESC>]52;c;<payload1><ESC>\
|
|
||||||
<ESC>]52;c;<payload2><ESC>\
|
|
||||||
|
|
||||||
will result in the clipboard having the contents ``payload1 + payload2``. To
|
|
||||||
send a new string to the clipboard send an OSC 52 sequence with an invalid payload
|
|
||||||
first, for example::
|
|
||||||
|
|
||||||
<ESC>]52;c;!<ESC>\
|
|
||||||
|
|
||||||
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
|
||||||
Further, since it is invalid, it should be ignored by terminal emulators
|
|
||||||
that do not support this extension, thereby making it safe to use, simply
|
|
||||||
always send it before starting a new OSC 52 paste, even if you aren't chunking
|
|
||||||
up large pastes, that way kitty won't concatenate your paste, and it will have
|
|
||||||
no ill-effects in other terminal emulators.
|
|
||||||
|
|
||||||
In case you're using software that can't be easily adapted to this
|
|
||||||
protocol extension, it can be disabled by specifying ``no-append`` to the
|
|
||||||
:opt:`clipboard_control` setting.
|
|
||||||
|
|
||||||
|
|
||||||
.. _unscroll:
|
|
||||||
|
|
||||||
Unscrolling the screen
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
This is a small extension to the `SD (Pan up) escape code
|
|
||||||
<https://vt100.net/docs/vt510-rm/SD.html>`_ from the VT-420 terminal. The
|
|
||||||
``SD`` escape code normally causes the text on screen to scroll down by the
|
|
||||||
specified number of lines, with empty lines appearing at the top of the screen.
|
|
||||||
This extension allows the new lines to be filled in from the scrollback buffer
|
|
||||||
instead of being blank.
|
|
||||||
|
|
||||||
The motivation for this is that many modern shells will show completions in a
|
|
||||||
block of lines under the cursor, this causes some of the on-screen text to be
|
|
||||||
lost even after the completion is completed, because it has scrolled off
|
|
||||||
screen. This escape code allows that text to be restored.
|
|
||||||
|
|
||||||
If the scrollback buffer is empty or there is no scrollback buffer, such as for
|
|
||||||
the alternate screen, then the newly inserted lines must be empty, just as with
|
|
||||||
the original ``SD`` escape code. The maximum number of lines that can be
|
|
||||||
scrolled down is implementation defined, but must be at least one screen worth.
|
|
||||||
|
|
||||||
The syntax of the escape code is identical to that of ``SD`` except that it has
|
|
||||||
a trailing ``+`` modifier. This is legal under the `ECMA 48 standard
|
|
||||||
<https://www.ecma-international.org/publications-and-standards/standards/ecma-48/>`_
|
|
||||||
and unused for any other purpose as far as I can tell. So for example, to
|
|
||||||
unscroll three lines, the escape code would be::
|
|
||||||
|
|
||||||
CSI 3 + T
|
|
||||||
|
|
||||||
See `discussion here
|
|
||||||
<https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/30>`_.
|
|
||||||
|
|
||||||
.. versionadded:: 0.20.2
|
|
||||||
|
|
||||||
|
|
||||||
.. _desktop_notifications:
|
|
||||||
|
|
||||||
|
|
||||||
Desktop notifications
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
|kitty| implements an extensible escape code (OSC 99) to show desktop
|
|
||||||
notifications. It is easy to use from shell scripts and fully extensible to
|
|
||||||
show title and body. Clicking on the notification can optionally focus the
|
|
||||||
window it came from, and/or send an escape code back to the application running
|
|
||||||
in that window.
|
|
||||||
|
|
||||||
The design of the escape code is partially based on the discussion in
|
|
||||||
the defunct
|
|
||||||
`terminal-wg <https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/13>`_
|
|
||||||
|
|
||||||
The escape code has the form::
|
|
||||||
|
|
||||||
<OSC> 99 ; metadata ; payload <terminator>
|
|
||||||
|
|
||||||
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is
|
|
||||||
:code:`<ESC><backslash>`. The metadata is a section of colon separated
|
|
||||||
:code:`key=value` pairs. Every key must be a single character from the set
|
|
||||||
:code:`a-zA-Z` and every value must be a word consisting of characters from
|
|
||||||
the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The payload must be
|
|
||||||
interpreted based on the metadata section. The two semi-colons *must* always be
|
|
||||||
present even when no metadata is present.
|
|
||||||
|
|
||||||
Before going into details, lets see how one can display a simple, single line
|
|
||||||
notification from a shell script::
|
|
||||||
|
|
||||||
printf '\x1b]99;;Hello world\x1b\\'
|
|
||||||
|
|
||||||
To show a message with a title and a body::
|
|
||||||
|
|
||||||
printf '\x1b]99;i=1:d=0;Hello world\x1b\\'
|
|
||||||
printf '\x1b]99;i=1:d=1:p=body;This is cool\x1b\\'
|
|
||||||
|
|
||||||
The most important key in the metadata is the ``p`` key, it controls how the
|
|
||||||
payload is interpreted. A value of ``title`` means the payload is setting the
|
|
||||||
title for the notification. A value of ``body`` means it is setting the body,
|
|
||||||
and so on, see the table below for full details.
|
|
||||||
|
|
||||||
The design of the escape code is fundamentally chunked, this is because
|
|
||||||
different terminal emulators have different limits on how large a single escape
|
|
||||||
code can be. Chunking is accomplished by the ``i`` and ``d`` keys. The ``i``
|
|
||||||
key is the *notification id* which can be any string containing the characters
|
|
||||||
``[a-zA-Z0-9_-+.]``. The ``d`` key stands for *done* and
|
|
||||||
can only take the values ``0`` and ``1``. A value of ``0`` means the
|
|
||||||
notification is not yet done and the terminal emulator should hold off
|
|
||||||
displaying it. A value of ``1`` means the notification is done, and should be
|
|
||||||
displayed. You can specify the title or body multiple times and the terminal
|
|
||||||
emulator will concatenate them, thereby allowing arbitrarily long text
|
|
||||||
(terminal emulators are free to impose a sensible limit to avoid
|
|
||||||
Denial-of-Service attacks).
|
|
||||||
|
|
||||||
Both the ``title`` and ``body`` payloads must be either UTF-8 encoded plain
|
|
||||||
text with no embedded escape codes, or UTF-8 text that is base64 encoded, in
|
|
||||||
which case there must be an ``e=1`` key in the metadata to indicate the payload
|
|
||||||
is base64 encoded.
|
|
||||||
|
|
||||||
When the user clicks the notification, a couple of things can happen, the
|
|
||||||
terminal emulator can focus the window from which the notification came, and/or
|
|
||||||
it can send back an escape code to the application indicating the notification
|
|
||||||
was activated. This is controlled by the ``a`` key which takes a comma
|
|
||||||
separated set of values, ``report`` and ``focus``. The value ``focus`` means
|
|
||||||
focus the window from which the notification was issued and is the default.
|
|
||||||
``report`` means send an escape code back to the application. The format of the
|
|
||||||
returned escape code is::
|
|
||||||
|
|
||||||
<OSC> 99 ; i=identifier ; <terminator>
|
|
||||||
|
|
||||||
The value of ``identifier`` comes from the ``i`` key in the escape code sent by
|
|
||||||
the application. If the application sends no identifier, then the terminal
|
|
||||||
*must* use ``i=0``. Actions can be preceded by a negative sign to turn them
|
|
||||||
off, so for example if you do not want any action, turn off the default
|
|
||||||
``focus`` action with::
|
|
||||||
|
|
||||||
a=-focus
|
|
||||||
|
|
||||||
Complete specification of all the metadata keys is in the table below. If a
|
|
||||||
terminal emulator encounters a key in the metadata it does not understand,
|
|
||||||
the key *must* be ignored, to allow for future extensibility of this escape
|
|
||||||
code. Similarly if values for known keys are unknown, the terminal emulator
|
|
||||||
*should* either ignore the entire escape code or perform a best guess effort
|
|
||||||
to display it based on what it does understand.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
It is possible to extend this escape code to allow specifying an icon for
|
|
||||||
the notification, however, given that some platforms, such as macOS, dont
|
|
||||||
allow displaying custom icons on a notification, at all, it was decided to
|
|
||||||
leave it out of the spec for the time being.
|
|
||||||
|
|
||||||
Similarly, features such as scheduled notifications could be added in future
|
|
||||||
revisions.
|
|
||||||
|
|
||||||
|
|
||||||
======= ==================== ========= =================
|
|
||||||
Key Value Default Description
|
|
||||||
======= ==================== ========= =================
|
|
||||||
``a`` Comma separated list ``focus`` What action to perform when the
|
|
||||||
of ``report``, notification is clicked
|
|
||||||
``focus``, with
|
|
||||||
optional leading
|
|
||||||
``-``
|
|
||||||
|
|
||||||
``d`` ``0`` or ``1`` ``1`` Indicates if the notification is
|
|
||||||
complete or not.
|
|
||||||
|
|
||||||
``e`` ``0`` or ``1`` ``0`` If set to ``1`` means the payload is base64 encoded UTF-8,
|
|
||||||
otherwise it is plain UTF-8 text with no C0 control codes in it
|
|
||||||
|
|
||||||
``i`` ``[a-zA-Z0-9-_+.]`` ``0`` Identifier for the notification
|
|
||||||
|
|
||||||
``p`` One of ``title`` or ``title`` Whether the payload is the notification title or body. If a
|
|
||||||
``body``. notification has no title, the body will be used as title.
|
|
||||||
======= ==================== ========= =================
|
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|kitty| also supports the legacy OSC 9 protocol developed by iTerm2 for
|
|
||||||
desktop notifications.
|
|
||||||
|
|||||||
28
docs/quickstart.rst
Normal file
28
docs/quickstart.rst
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
.. _quickstart:
|
||||||
|
|
||||||
|
Quickstart
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
binary
|
||||||
|
build
|
||||||
|
|
||||||
|
Pre-built binaries of |kitty| are available for both macOS and Linux.
|
||||||
|
See the :doc:`binary install instructions </binary>`. You can also
|
||||||
|
:doc:`build from source </build>`.
|
||||||
|
|
||||||
|
Additionally, you can use your favorite package manager to install the |kitty|
|
||||||
|
package, but note that some Linux distribution packages are woefully outdated.
|
||||||
|
|kitty| is available in a vast number of package repositories for macOS
|
||||||
|
and Linux.
|
||||||
|
|
||||||
|
.. image:: https://repology.org/badge/tiny-repos/kitty.svg
|
||||||
|
:target: https://repology.org/project/kitty/versions
|
||||||
|
:alt: Number of repositories kitty is available in
|
||||||
|
|
||||||
|
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
||||||
|
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
||||||
|
|
||||||
|
For a tour of kitty's design and features, see the :doc:`/overview`.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Documentation for the kitty remote control protocol
|
The kitty remote control protocol
|
||||||
======================================================
|
==================================
|
||||||
|
|
||||||
The kitty remote control protocol is a simple protocol that involves sending
|
The kitty remote control protocol is a simple protocol that involves sending
|
||||||
data to kitty in the form of JSON. Any individual command of kitty has the
|
data to kitty in the form of JSON. Any individual command of kitty has the
|
||||||
@@ -37,5 +37,4 @@ with the following command line::
|
|||||||
|
|
||||||
echo -en '\eP@kitty-cmd{"cmd":"ls","version":[0,14,2]}\e\' | socat - unix:/tmp/test | awk '{ print substr($0, 13, length($0) - 14) }' | jq -c '.data | fromjson' | jq .
|
echo -en '\eP@kitty-cmd{"cmd":"ls","version":[0,14,2]}\e\' | socat - unix:/tmp/test | awk '{ print substr($0, 13, length($0) - 14) }' | jq -c '.data | fromjson' | jq .
|
||||||
|
|
||||||
|
|
||||||
.. include:: generated/rc.rst
|
.. include:: generated/rc.rst
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
:tocdepth: 2
|
Control kitty from scripts
|
||||||
|
----------------------------
|
||||||
Controlling kitty from scripts or the shell
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
.. highlight:: sh
|
.. highlight:: sh
|
||||||
|
|
||||||
Tutorial
|
|
||||||
----------
|
|
||||||
|
|
||||||
|kitty| can be controlled from scripts or the shell prompt. You can open new
|
|kitty| can be controlled from scripts or the shell prompt. You can open new
|
||||||
windows, send arbitrary text input to any window, name windows and tabs, etc.
|
windows, send arbitrary text input to any window, name windows and tabs, etc.
|
||||||
Let's walk through a few examples of controlling |kitty|.
|
Let's walk through a few examples of controlling |kitty|.
|
||||||
|
|
||||||
|
Tutorial
|
||||||
|
------------
|
||||||
|
|
||||||
Start by running |kitty| as::
|
Start by running |kitty| as::
|
||||||
|
|
||||||
kitty -o allow_remote_control=yes -o enabled_layouts=tall
|
kitty -o allow_remote_control=yes -o enabled_layouts=tall
|
||||||
@@ -142,6 +140,8 @@ running on other computers (for example, over ssh) or as other users.
|
|||||||
kitty, as if you were running with ``allow_remote_control`` turned on.
|
kitty, as if you were running with ``allow_remote_control`` turned on.
|
||||||
|
|
||||||
|
|
||||||
|
.. _rc_mapping:
|
||||||
|
|
||||||
Mapping key presses to remote control commands
|
Mapping key presses to remote control commands
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
@@ -172,10 +172,15 @@ Now press, F1 and start typing, what you type will be sent to all windows,
|
|||||||
live, as you type it.
|
live, as you type it.
|
||||||
|
|
||||||
|
|
||||||
Documentation for the remote control protocol
|
The remote control protocol
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
If you wish to develop your own client to talk to |kitty|, you
|
If you wish to develop your own client to talk to |kitty|, you
|
||||||
can use the :doc:`rc_protocol`.
|
can use the :doc:`protocol specification <rc_protocol>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
rc_protocol
|
||||||
|
|
||||||
.. include:: generated/cli-kitty-at.rst
|
.. include:: generated/cli-kitty-at.rst
|
||||||
|
|||||||
5
docs/requirements.txt
Normal file
5
docs/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
sphinx
|
||||||
|
furo
|
||||||
|
sphinx-copybutton
|
||||||
|
sphinxext-opengraph
|
||||||
|
sphinx-inline-tabs
|
||||||
36
docs/underlines.rst
Normal file
36
docs/underlines.rst
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
Colored and styled underlines
|
||||||
|
================================
|
||||||
|
|
||||||
|
|kitty| supports colored and styled (wavy) underlines. This is of particular
|
||||||
|
use in terminal editors such as vim and emacs to display red, wavy underlines
|
||||||
|
under mis-spelled words and/or syntax errors. This is done by re-purposing some
|
||||||
|
SGR escape codes that are not used in modern terminals (`CSI codes
|
||||||
|
<https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences>`_)
|
||||||
|
|
||||||
|
To set the underline style::
|
||||||
|
|
||||||
|
<ESC>[4:0m # this is no underline
|
||||||
|
<ESC>[4:1m # this is a straight underline
|
||||||
|
<ESC>[4:2m # this is a double underline
|
||||||
|
<ESC>[4:3m # this is a curly underline
|
||||||
|
<ESC>[4:4m # this is a dotted underline (not implemented in kitty)
|
||||||
|
<ESC>[4:5m # this is a dashed underline (not implemented in kitty)
|
||||||
|
<ESC>[4m # this is a straight underline (for backwards compat)
|
||||||
|
<ESC>[24m # this is no underline (for backwards compat)
|
||||||
|
|
||||||
|
To set the underline color (this is reserved and as far as I can tell not actually used for anything)::
|
||||||
|
|
||||||
|
<ESC>[58...m
|
||||||
|
|
||||||
|
This works exactly like the codes ``38, 48`` that are used to set foreground and
|
||||||
|
background color respectively.
|
||||||
|
|
||||||
|
To reset the underline color (also previously reserved and unused)::
|
||||||
|
|
||||||
|
<ESC>[59m
|
||||||
|
|
||||||
|
The underline color must remain the same under reverse video, if it has a
|
||||||
|
color, if not, it should follow the foreground color.
|
||||||
|
|
||||||
|
To detect support for this feature in a terminal emulator, query the terminfo database
|
||||||
|
for the ``Su`` boolean capability.
|
||||||
34
docs/unscroll.rst
Normal file
34
docs/unscroll.rst
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
.. _unscroll:
|
||||||
|
|
||||||
|
Unscrolling the screen
|
||||||
|
========================
|
||||||
|
|
||||||
|
This is a small extension to the `SD (Pan up) escape code
|
||||||
|
<https://vt100.net/docs/vt510-rm/SD.html>`_ from the VT-420 terminal. The
|
||||||
|
``SD`` escape code normally causes the text on screen to scroll down by the
|
||||||
|
specified number of lines, with empty lines appearing at the top of the screen.
|
||||||
|
This extension allows the new lines to be filled in from the scrollback buffer
|
||||||
|
instead of being blank.
|
||||||
|
|
||||||
|
The motivation for this is that many modern shells will show completions in a
|
||||||
|
block of lines under the cursor, this causes some of the on-screen text to be
|
||||||
|
lost even after the completion is completed, because it has scrolled off
|
||||||
|
screen. This escape code allows that text to be restored.
|
||||||
|
|
||||||
|
If the scrollback buffer is empty or there is no scrollback buffer, such as for
|
||||||
|
the alternate screen, then the newly inserted lines must be empty, just as with
|
||||||
|
the original ``SD`` escape code. The maximum number of lines that can be
|
||||||
|
scrolled down is implementation defined, but must be at least one screen worth.
|
||||||
|
|
||||||
|
The syntax of the escape code is identical to that of ``SD`` except that it has
|
||||||
|
a trailing ``+`` modifier. This is legal under the `ECMA 48 standard
|
||||||
|
<https://www.ecma-international.org/publications-and-standards/standards/ecma-48/>`_
|
||||||
|
and unused for any other purpose as far as I can tell. So for example, to
|
||||||
|
unscroll three lines, the escape code would be::
|
||||||
|
|
||||||
|
CSI 3 + T
|
||||||
|
|
||||||
|
See `discussion here
|
||||||
|
<https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/30>`_.
|
||||||
|
|
||||||
|
.. versionadded:: 0.20.2
|
||||||
@@ -250,7 +250,7 @@ def write_header(text: str, path: str) -> None:
|
|||||||
def graphics_parser() -> None:
|
def graphics_parser() -> None:
|
||||||
flag = frozenset
|
flag = frozenset
|
||||||
keymap: KeymapType = {
|
keymap: KeymapType = {
|
||||||
'a': ('action', flag('tTqpdfa')),
|
'a': ('action', flag('tTqpdfac')),
|
||||||
'd': ('delete_action', flag('aAiIcCfFnNpPqQxXyYzZ')),
|
'd': ('delete_action', flag('aAiIcCfFnNpPqQxXyYzZ')),
|
||||||
't': ('transmission_type', flag('dfts')),
|
't': ('transmission_type', flag('dfts')),
|
||||||
'o': ('compressed', flag('z')),
|
'o': ('compressed', flag('z')),
|
||||||
|
|||||||
@@ -388,7 +388,8 @@ def gen_ucd() -> None:
|
|||||||
rmap[0xfe0e], rmap[0xfe0f]
|
rmap[0xfe0e], rmap[0xfe0f]
|
||||||
))
|
))
|
||||||
with open('kittens/hints/url_regex.py', 'w') as f:
|
with open('kittens/hints/url_regex.py', 'w') as f:
|
||||||
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n'))))
|
f.write('# generated by gen-wcwidth.py, do not edit\n\n')
|
||||||
|
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n\r'))))
|
||||||
|
|
||||||
|
|
||||||
def gen_names() -> None:
|
def gen_names() -> None:
|
||||||
|
|||||||
2
glfw/backend_utils.c
vendored
2
glfw/backend_utils.c
vendored
@@ -375,7 +375,7 @@ GLFWAPI char* utf_8_strndup(const char* source, size_t max_length) {
|
|||||||
int createAnonymousFile(off_t size) {
|
int createAnonymousFile(off_t size) {
|
||||||
int ret, fd = -1, shm_anon = 0;
|
int ret, fd = -1, shm_anon = 0;
|
||||||
#ifdef HAS_MEMFD_CREATE
|
#ifdef HAS_MEMFD_CREATE
|
||||||
fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
fd = glfw_memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||||
if (fd < 0) return -1;
|
if (fd < 0) return -1;
|
||||||
// We can add this seal before calling posix_fallocate(), as the file
|
// We can add this seal before calling posix_fallocate(), as the file
|
||||||
// is currently zero-sized anyway.
|
// is currently zero-sized anyway.
|
||||||
|
|||||||
@@ -41,8 +41,22 @@
|
|||||||
|
|
||||||
// Get the name of the specified display, or NULL
|
// Get the name of the specified display, or NULL
|
||||||
//
|
//
|
||||||
static char* getDisplayName(CGDirectDisplayID displayID)
|
static char*
|
||||||
|
getDisplayName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||||
{
|
{
|
||||||
|
// IOKit doesn't work on Apple Silicon anymore
|
||||||
|
// Luckily, 10.15 introduced -[NSScreen localizedName].
|
||||||
|
// Use it if available, and fall back to IOKit otherwise.
|
||||||
|
if (screen)
|
||||||
|
{
|
||||||
|
if ([screen respondsToSelector:@selector(localizedName)])
|
||||||
|
{
|
||||||
|
NSString* name = [screen valueForKey:@"localizedName"];
|
||||||
|
if (name) {
|
||||||
|
return _glfw_strdup([name UTF8String]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
io_iterator_t it;
|
io_iterator_t it;
|
||||||
io_service_t service;
|
io_service_t service;
|
||||||
CFDictionaryRef info;
|
CFDictionaryRef info;
|
||||||
@@ -89,7 +103,7 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
if (!service)
|
if (!service)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Cocoa: Failed to find service port for display, cannot get its name, using Unknown");
|
"Cocoa: Failed to find service port for display");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,11 +328,9 @@ void _glfwClearDisplayLinks() {
|
|||||||
if (_glfw.ns.displayLinks.entries[i].displayLink) {
|
if (_glfw.ns.displayLinks.entries[i].displayLink) {
|
||||||
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
|
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
|
||||||
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
|
|
||||||
_glfw.ns.displayLinks.entries[i].first_unserviced_render_frame_request_at = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
memset(_glfw.ns.displayLinks.entries, 0, sizeof(_GLFWDisplayLinkNS) * _glfw.ns.displayLinks.count);
|
||||||
_glfw.ns.displayLinks.count = 0;
|
_glfw.ns.displayLinks.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,16 +352,21 @@ _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry) {
|
|||||||
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)entry->displayID);
|
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)entry->displayID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
_GLFWDisplayLinkNS*
|
||||||
createDisplayLink(CGDirectDisplayID displayID) {
|
_glfw_create_display_link(CGDirectDisplayID displayID) {
|
||||||
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
|
if (_glfw.ns.displayLinks.count >= arraysz(_glfw.ns.displayLinks.entries) - 1) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many monitors cannot create display link");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
// already created in this run
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return _glfw.ns.displayLinks.entries + i;
|
||||||
}
|
}
|
||||||
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
||||||
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
||||||
entry->displayID = displayID;
|
entry->displayID = displayID;
|
||||||
_glfw_create_cv_display_link(entry);
|
_glfw_create_cv_display_link(entry);
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for changes in the set of connected monitors
|
// Poll for changes in the set of connected monitors
|
||||||
@@ -357,11 +374,13 @@ createDisplayLink(CGDirectDisplayID displayID) {
|
|||||||
void _glfwPollMonitorsNS(void)
|
void _glfwPollMonitorsNS(void)
|
||||||
{
|
{
|
||||||
uint32_t displayCount;
|
uint32_t displayCount;
|
||||||
|
|
||||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||||
CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
_glfwClearDisplayLinks();
|
_glfwClearDisplayLinks();
|
||||||
|
if (_glfw.hints.init.debugRendering) {
|
||||||
|
fprintf(stderr, "Polling for monitors: %u found\n", displayCount);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _glfw.monitorCount; i++)
|
for (int i = 0; i < _glfw.monitorCount; i++)
|
||||||
_glfw.monitors[i]->ns.screen = nil;
|
_glfw.monitors[i]->ns.screen = nil;
|
||||||
@@ -378,32 +397,57 @@ void _glfwPollMonitorsNS(void)
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < displayCount; i++)
|
for (uint32_t i = 0; i < displayCount; i++)
|
||||||
{
|
{
|
||||||
if (CGDisplayIsAsleep(displays[i]))
|
if (CGDisplayIsAsleep(displays[i])) {
|
||||||
|
if (_glfw.hints.init.debugRendering) fprintf(stderr, "Ignoring sleeping display: %u", displays[i]);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||||
|
NSScreen* screen = nil;
|
||||||
|
|
||||||
|
for (screen in [NSScreen screens])
|
||||||
|
{
|
||||||
|
NSNumber* screenNumber = [screen deviceDescription][@"NSScreenNumber"];
|
||||||
|
|
||||||
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
|
// display replacement on machines with automatic graphics
|
||||||
|
// switching
|
||||||
|
if (CGDisplayUnitNumber([screenNumber unsignedIntValue]) == unitNumber)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// HACK: Compare unit numbers instead of display IDs to work around
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
// display replacement on machines with automatic graphics
|
// display replacement on machines with automatic graphics
|
||||||
// switching
|
// switching
|
||||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
uint32_t j;
|
||||||
|
for (j = 0; j < disconnectedCount; j++)
|
||||||
for (uint32_t j = 0; j < disconnectedCount; j++)
|
|
||||||
{
|
{
|
||||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||||
{
|
{
|
||||||
|
disconnected[j]->ns.displayID = displays[i];
|
||||||
|
disconnected[j]->ns.screen = screen;
|
||||||
|
_glfw_create_display_link(displays[i]);
|
||||||
disconnected[j] = NULL;
|
disconnected[j] = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||||
char* name = getDisplayName(displays[i]);
|
char* name = getDisplayName(displays[i], screen);
|
||||||
if (!name)
|
if (!name) {
|
||||||
name = _glfw_strdup("Unknown");
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Failed to get name for display, using generic name");
|
||||||
|
name = _glfw_strdup("Display with no name");
|
||||||
|
}
|
||||||
|
|
||||||
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
||||||
monitor->ns.displayID = displays[i];
|
monitor->ns.displayID = displays[i];
|
||||||
monitor->ns.unitNumber = unitNumber;
|
monitor->ns.unitNumber = unitNumber;
|
||||||
createDisplayLink(monitor->ns.displayID);
|
monitor->ns.screen = screen;
|
||||||
|
_glfw_create_display_link(monitor->ns.displayID);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
@@ -554,15 +598,16 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
|
|
||||||
const GLFWvidmode mode =
|
const GLFWvidmode mode =
|
||||||
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
|
CFIndex j;
|
||||||
|
|
||||||
for (CFIndex j = 0; j < *count; j++)
|
for (j = 0; j < *count; j++)
|
||||||
{
|
{
|
||||||
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip duplicate modes
|
// Skip duplicate modes
|
||||||
if (i < *count)
|
if (j < *count)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
(*count)++;
|
(*count)++;
|
||||||
|
|||||||
1
glfw/cocoa_platform.h
vendored
1
glfw/cocoa_platform.h
vendored
@@ -250,3 +250,4 @@ void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
|||||||
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
||||||
void _glfwCocoaPostEmptyEvent(void);
|
void _glfwCocoaPostEmptyEvent(void);
|
||||||
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
||||||
|
_GLFWDisplayLinkNS* _glfw_create_display_link(CGDirectDisplayID);
|
||||||
|
|||||||
@@ -337,9 +337,12 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) {
|
|||||||
display_link_shutdown_timer = _glfwPlatformAddTimer(DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL, false, _glfwShutdownCVDisplayLink, NULL, NULL);
|
display_link_shutdown_timer = _glfwPlatformAddTimer(DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL, false, _glfwShutdownCVDisplayLink, NULL, NULL);
|
||||||
}
|
}
|
||||||
monotonic_t now = glfwGetTime();
|
monotonic_t now = glfwGetTime();
|
||||||
|
bool found_display_link = false;
|
||||||
|
_GLFWDisplayLinkNS *dl = NULL;
|
||||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
dl = &_glfw.ns.displayLinks.entries[i];
|
||||||
if (dl->displayID == displayID) {
|
if (dl->displayID == displayID) {
|
||||||
|
found_display_link = true;
|
||||||
dl->lastRenderFrameRequestedAt = now;
|
dl->lastRenderFrameRequestedAt = now;
|
||||||
if (!dl->first_unserviced_render_frame_request_at) dl->first_unserviced_render_frame_request_at = now;
|
if (!dl->first_unserviced_render_frame_request_at) dl->first_unserviced_render_frame_request_at = now;
|
||||||
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||||
@@ -359,6 +362,14 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) {
|
|||||||
dl->first_unserviced_render_frame_request_at = 0;
|
dl->first_unserviced_render_frame_request_at = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!found_display_link) {
|
||||||
|
dl = _glfw_create_display_link(displayID);
|
||||||
|
if (dl) {
|
||||||
|
dl->lastRenderFrameRequestedAt = now;
|
||||||
|
dl->first_unserviced_render_frame_request_at = now;
|
||||||
|
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1712,6 +1723,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return false;
|
return false;
|
||||||
|
[window->ns.object setColorSpace:[NSColorSpace sRGBColorSpace]];
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||||||
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
||||||
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||||
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
|
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
|
||||||
|
int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
|
||||||
'''.splitlines():
|
'''.splitlines():
|
||||||
if line:
|
if line:
|
||||||
functions.append(Function(line.strip(), check_fail=False))
|
functions.append(Function(line.strip(), check_fail=False))
|
||||||
|
|||||||
4
glfw/memfd.h
vendored
4
glfw/memfd.h
vendored
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
static inline int memfd_create(const char *name, unsigned int flags) {
|
static inline int glfw_memfd_create(const char *name, unsigned int flags) {
|
||||||
return syscall(__NR_memfd_create, name, flags);
|
return (int)syscall(__NR_memfd_create, name, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef F_LINUX_SPECIFIC_BASE
|
#ifndef F_LINUX_SPECIFIC_BASE
|
||||||
|
|||||||
1
glfw/wl_init.c
vendored
1
glfw/wl_init.c
vendored
@@ -29,7 +29,6 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
#include "wl_client_side_decorations.h"
|
|
||||||
#include "linux_desktop_settings.h"
|
#include "linux_desktop_settings.h"
|
||||||
#include "../kitty/monotonic.h"
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
|
|||||||
43
glfw/wl_window.c
vendored
43
glfw/wl_window.c
vendored
@@ -254,15 +254,39 @@ dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height
|
|||||||
_glfwInputWindowDamage(window);
|
_glfwInputWindowDamage(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
inform_compositor_of_window_geometry(_GLFWwindow *window, const char *event) {
|
||||||
|
#define geometry window->wl.decorations.geometry
|
||||||
|
debug("Setting window geometry in %s event: x=%d y=%d %dx%d\n", event, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||||
|
xdg_surface_set_window_geometry(window->wl.xdg.surface, geometry.x, geometry.y, geometry.width, geometry.height);
|
||||||
|
#undef geometry
|
||||||
|
}
|
||||||
|
|
||||||
static void xdgDecorationHandleConfigure(void* data,
|
|
||||||
|
static void
|
||||||
|
xdgDecorationHandleConfigure(void* data,
|
||||||
struct zxdg_toplevel_decoration_v1* decoration UNUSED,
|
struct zxdg_toplevel_decoration_v1* decoration UNUSED,
|
||||||
uint32_t mode)
|
uint32_t mode)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
|
|
||||||
window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
bool has_server_side_decorations = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
|
debug("XDG decoration configure event received: has_server_side_decorations: %d\n", has_server_side_decorations);
|
||||||
|
if (has_server_side_decorations == window->wl.decorations.serverSide) return;
|
||||||
|
window->wl.decorations.serverSide = has_server_side_decorations;
|
||||||
|
int width = window->wl.width, height = window->wl.height;
|
||||||
|
if (window->wl.decorations.serverSide) {
|
||||||
|
free_csd_surfaces(window);
|
||||||
|
height += window->wl.decorations.metrics.visible_titlebar_height;
|
||||||
|
} else {
|
||||||
|
ensure_csd_resources(window);
|
||||||
|
}
|
||||||
|
set_csd_window_geometry(window, &width, &height);
|
||||||
|
dispatchChangesAfterConfigure(window, width, height);
|
||||||
ensure_csd_resources(window);
|
ensure_csd_resources(window);
|
||||||
|
wl_surface_commit(window->wl.surface);
|
||||||
|
debug("final window content size: %dx%d\n", window->wl.width, window->wl.height);
|
||||||
|
inform_compositor_of_window_geometry(window, "configure-decorations");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
|
static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
|
||||||
@@ -396,7 +420,8 @@ _glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
|
|||||||
return !already_fullscreen;
|
return !already_fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdgToplevelHandleConfigure(void* data,
|
static void
|
||||||
|
xdgToplevelHandleConfigure(void* data,
|
||||||
struct xdg_toplevel* toplevel UNUSED,
|
struct xdg_toplevel* toplevel UNUSED,
|
||||||
int32_t width,
|
int32_t width,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
@@ -452,10 +477,7 @@ static void xdgToplevelHandleConfigure(void* data,
|
|||||||
_glfwInputWindowFocus(window, window->wl.toplevel_states & TOPLEVEL_STATE_ACTIVATED);
|
_glfwInputWindowFocus(window, window->wl.toplevel_states & TOPLEVEL_STATE_ACTIVATED);
|
||||||
ensure_csd_resources(window);
|
ensure_csd_resources(window);
|
||||||
wl_surface_commit(window->wl.surface);
|
wl_surface_commit(window->wl.surface);
|
||||||
#define geometry window->wl.decorations.geometry
|
inform_compositor_of_window_geometry(window, "configure");
|
||||||
debug("Setting window geometry: x=%d y=%d %dx%d\n", geometry.x, geometry.y, geometry.width, geometry.height);
|
|
||||||
xdg_surface_set_window_geometry(window->wl.xdg.surface, geometry.x, geometry.y, geometry.width, geometry.height);
|
|
||||||
#undef geometry
|
|
||||||
if (live_resize_done) _glfwInputLiveResize(window, false);
|
if (live_resize_done) _glfwInputLiveResize(window, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +504,8 @@ static const struct xdg_surface_listener xdgSurfaceListener = {
|
|||||||
xdgSurfaceHandleConfigure
|
xdgSurfaceHandleConfigure
|
||||||
};
|
};
|
||||||
|
|
||||||
static void setXdgDecorations(_GLFWwindow* window)
|
static void
|
||||||
|
setXdgDecorations(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (_glfw.wl.decorationManager)
|
if (_glfw.wl.decorationManager)
|
||||||
{
|
{
|
||||||
@@ -504,7 +527,8 @@ static void setXdgDecorations(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool createXdgSurface(_GLFWwindow* window)
|
static bool
|
||||||
|
createXdgSurface(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
||||||
window->wl.surface);
|
window->wl.surface);
|
||||||
@@ -872,6 +896,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
resizeFramebuffer(window);
|
resizeFramebuffer(window);
|
||||||
ensure_csd_resources(window);
|
ensure_csd_resources(window);
|
||||||
wl_surface_commit(window->wl.surface);
|
wl_surface_commit(window->wl.surface);
|
||||||
|
inform_compositor_of_window_geometry(window, "SetWindowSize");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
glfw/x11_window.c
vendored
7
glfw/x11_window.c
vendored
@@ -3122,3 +3122,10 @@ GLFWAPI unsigned long long glfwDBusUserNotify(const char *app_name, const char*
|
|||||||
GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) {
|
GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) {
|
||||||
glfw_dbus_set_user_notification_activated_handler(handler);
|
glfw_dbus_set_user_notification_activated_handler(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
return XSetCommand(_glfw.x11.display, window->x11.handle, argv, argc);
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class Clipboard(Handler):
|
|||||||
self.args = args
|
self.args = args
|
||||||
self.clipboard_contents: Optional[str] = None
|
self.clipboard_contents: Optional[str] = None
|
||||||
self.data_to_send = data_to_send
|
self.data_to_send = data_to_send
|
||||||
|
self.quit_on_write = False
|
||||||
|
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
if self.data_to_send is not None:
|
if self.data_to_send is not None:
|
||||||
@@ -30,10 +31,14 @@ class Clipboard(Handler):
|
|||||||
self.print('\x1bP+q544e\x1b\\', end='')
|
self.print('\x1bP+q544e\x1b\\', end='')
|
||||||
self.print('Waiting for completion...')
|
self.print('Waiting for completion...')
|
||||||
return
|
return
|
||||||
self.quit_loop(0)
|
self.quit_on_write = True
|
||||||
return
|
return
|
||||||
self.cmd.request_from_clipboard(self.args.use_primary)
|
self.cmd.request_from_clipboard(self.args.use_primary)
|
||||||
|
|
||||||
|
def on_writing_finished(self) -> None:
|
||||||
|
if self.quit_on_write:
|
||||||
|
self.quit_loop(0)
|
||||||
|
|
||||||
def on_clipboard_response(self, text: str, from_primary: bool = False) -> None:
|
def on_clipboard_response(self, text: str, from_primary: bool = False) -> None:
|
||||||
self.clipboard_contents = text
|
self.clipboard_contents = text
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
See https://sw.kovidgoyal.net/kitty/kittens/diff.html
|
See https://sw.kovidgoyal.net/kitty/kittens/diff/
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ def sanitize(text: str) -> str:
|
|||||||
|
|
||||||
@lru_cache(maxsize=1024)
|
@lru_cache(maxsize=1024)
|
||||||
def mime_type_for_path(path: str) -> str:
|
def mime_type_for_path(path: str) -> str:
|
||||||
return guess_type(path) or 'application/octet-stream'
|
return guess_type(path, allow_filesystem_access=True) or 'application/octet-stream'
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1024)
|
@lru_cache(maxsize=1024)
|
||||||
|
|||||||
@@ -71,28 +71,48 @@ next_segment(SegmentPointer *s, PyObject *highlights) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
typedef struct LineBuffer {
|
||||||
insert_code(PyObject *code, Py_UCS4 *buf, size_t bufsz, unsigned int *buf_pos) {
|
Py_UCS4 *buf;
|
||||||
unsigned int csz = PyUnicode_GET_LENGTH(code);
|
size_t pos, capacity;
|
||||||
if (*buf_pos + csz >= bufsz) return false;
|
} LineBuffer;
|
||||||
for (unsigned int s = 0; s < csz; s++) buf[(*buf_pos)++] = PyUnicode_READ(PyUnicode_KIND(code), PyUnicode_DATA(code), s);
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ensure_space(LineBuffer *b, size_t num) {
|
||||||
|
if (b->pos + num >= b->capacity) {
|
||||||
|
size_t new_cap = MAX(b->capacity * 2, 4096u);
|
||||||
|
new_cap = MAX(b->pos + num + 1024u, new_cap);
|
||||||
|
b->buf = realloc(b->buf, new_cap * sizeof(b->buf[0]));
|
||||||
|
if (!b->buf) { PyErr_NoMemory(); return false; }
|
||||||
|
b->capacity = new_cap;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
add_line(Segment *bg_segment, Segment *fg_segment, Py_UCS4 *buf, size_t bufsz, unsigned int *buf_pos, PyObject *ans) {
|
insert_code(PyObject *code, LineBuffer *b) {
|
||||||
bool bg_is_active = bg_segment->current_pos == bg_segment->end_pos, fg_is_active = fg_segment->current_pos == fg_segment->end_pos;
|
unsigned int csz = PyUnicode_GET_LENGTH(code);
|
||||||
if (bg_is_active) { if(!insert_code(bg_segment->end_code, buf, bufsz, buf_pos)) return false; }
|
if (!ensure_space(b, csz)) return false;
|
||||||
if (fg_is_active) { if(!insert_code(fg_segment->end_code, buf, bufsz, buf_pos)) return false; }
|
for (unsigned int s = 0; s < csz; s++) b->buf[b->pos++] = PyUnicode_READ(PyUnicode_KIND(code), PyUnicode_DATA(code), s);
|
||||||
PyObject *wl = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, *buf_pos);
|
|
||||||
if (!wl) return false;
|
|
||||||
int ret = PyList_Append(ans, wl); Py_DECREF(wl); if (ret != 0) return false;
|
|
||||||
*buf_pos = 0;
|
|
||||||
if (bg_is_active) { if(!insert_code(bg_segment->start_code, buf, bufsz, buf_pos)) return false; }
|
|
||||||
if (fg_is_active) { if(!insert_code(fg_segment->start_code, buf, bufsz, buf_pos)) return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
add_line(Segment *bg_segment, Segment *fg_segment, LineBuffer *b, PyObject *ans) {
|
||||||
|
bool bg_is_active = bg_segment->current_pos == bg_segment->end_pos, fg_is_active = fg_segment->current_pos == fg_segment->end_pos;
|
||||||
|
if (bg_is_active) { if(!insert_code(bg_segment->end_code, b)) return false; }
|
||||||
|
if (fg_is_active) { if(!insert_code(fg_segment->end_code, b)) return false; }
|
||||||
|
PyObject *wl = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, b->buf, b->pos);
|
||||||
|
if (!wl) return false;
|
||||||
|
int ret = PyList_Append(ans, wl); Py_DECREF(wl); if (ret != 0) return false;
|
||||||
|
b->pos = 0;
|
||||||
|
if (bg_is_active) { if(!insert_code(bg_segment->start_code, b)) return false; }
|
||||||
|
if (fg_is_active) { if(!insert_code(fg_segment->start_code, b)) return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LineBuffer b;
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
split_with_highlights(PyObject *self UNUSED, PyObject *args) {
|
split_with_highlights(PyObject *self UNUSED, PyObject *args) {
|
||||||
PyObject *line, *truncate_points_py, *fg_highlights, *bg_highlight;
|
PyObject *line, *truncate_points_py, *fg_highlights, *bg_highlight;
|
||||||
@@ -106,19 +126,19 @@ split_with_highlights(PyObject *self UNUSED, PyObject *args) {
|
|||||||
}
|
}
|
||||||
SegmentPointer fg_segment = { .sg = EMPTY_SEGMENT, .num = PyList_GET_SIZE(fg_highlights)}, bg_segment = { .sg = EMPTY_SEGMENT };
|
SegmentPointer fg_segment = { .sg = EMPTY_SEGMENT, .num = PyList_GET_SIZE(fg_highlights)}, bg_segment = { .sg = EMPTY_SEGMENT };
|
||||||
if (bg_highlight != Py_None) { if (!convert_segment(bg_highlight, &bg_segment.sg)) { Py_CLEAR(ans); return NULL; }; bg_segment.num = 1; }
|
if (bg_highlight != Py_None) { if (!convert_segment(bg_highlight, &bg_segment.sg)) { Py_CLEAR(ans); return NULL; }; bg_segment.num = 1; }
|
||||||
#define CHECK_CALL(func, ...) if (!func(__VA_ARGS__)) { Py_CLEAR(ans); if (!PyErr_Occurred()) PyErr_SetString(PyExc_ValueError, "line too long"); return NULL; }
|
#define CHECK_CALL(func, ...) if (!func(__VA_ARGS__)) { Py_CLEAR(ans); if (!PyErr_Occurred()) PyErr_SetString(PyExc_ValueError, "unknown error while processing line"); return NULL; }
|
||||||
CHECK_CALL(next_segment, &fg_segment, fg_highlights);
|
CHECK_CALL(next_segment, &fg_segment, fg_highlights);
|
||||||
|
|
||||||
#define NEXT_TRUNCATE_POINT truncate_point = (truncate_pos < num_truncate_pts) ? truncate_points[truncate_pos++] : UINT_MAX
|
#define NEXT_TRUNCATE_POINT truncate_point = (truncate_pos < num_truncate_pts) ? truncate_points[truncate_pos++] : UINT_MAX
|
||||||
NEXT_TRUNCATE_POINT;
|
NEXT_TRUNCATE_POINT;
|
||||||
|
|
||||||
#define INSERT_CODE(x) { CHECK_CALL(insert_code, x, buf, arraysz(buf), &buf_pos); }
|
#define INSERT_CODE(x) { CHECK_CALL(insert_code, x, &b); }
|
||||||
|
|
||||||
#define ADD_LINE CHECK_CALL(add_line, &bg_segment.sg, &fg_segment.sg, buf, arraysz(buf), &buf_pos, ans);
|
#define ADD_LINE CHECK_CALL(add_line, &bg_segment.sg, &fg_segment.sg, &b, ans);
|
||||||
|
|
||||||
#define ADD_CHAR(x) { \
|
#define ADD_CHAR(x) { \
|
||||||
buf[buf_pos++] = x; \
|
if (!ensure_space(&b, 1)) { Py_CLEAR(ans); return NULL; } \
|
||||||
if (buf_pos >= arraysz(buf)) { Py_CLEAR(ans); PyErr_SetString(PyExc_ValueError, "line too long"); return NULL; } \
|
b.buf[b.pos++] = x; \
|
||||||
}
|
}
|
||||||
#define CHECK_SEGMENT(sgp, is_fg) { \
|
#define CHECK_SEGMENT(sgp, is_fg) { \
|
||||||
if (i == sgp.sg.current_pos) { \
|
if (i == sgp.sg.current_pos) { \
|
||||||
@@ -137,15 +157,15 @@ split_with_highlights(PyObject *self UNUSED, PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int line_sz = PyUnicode_GET_LENGTH(line);
|
const unsigned int line_sz = PyUnicode_GET_LENGTH(line);
|
||||||
static Py_UCS4 buf[4096];
|
b.pos = 0;
|
||||||
unsigned int i = 0, buf_pos = 0;
|
unsigned int i = 0;
|
||||||
for (; i < line_sz; i++) {
|
for (; i < line_sz; i++) {
|
||||||
if (i == truncate_point) { ADD_LINE; NEXT_TRUNCATE_POINT; }
|
if (i == truncate_point) { ADD_LINE; NEXT_TRUNCATE_POINT; }
|
||||||
CHECK_SEGMENT(bg_segment, false);
|
CHECK_SEGMENT(bg_segment, false);
|
||||||
CHECK_SEGMENT(fg_segment, true)
|
CHECK_SEGMENT(fg_segment, true)
|
||||||
ADD_CHAR(PyUnicode_READ(PyUnicode_KIND(line), PyUnicode_DATA(line), i));
|
ADD_CHAR(PyUnicode_READ(PyUnicode_KIND(line), PyUnicode_DATA(line), i));
|
||||||
}
|
}
|
||||||
if (buf_pos) ADD_LINE;
|
if (b.pos) ADD_LINE;
|
||||||
return ans;
|
return ans;
|
||||||
#undef INSERT_CODE
|
#undef INSERT_CODE
|
||||||
#undef CHECK_SEGMENT
|
#undef CHECK_SEGMENT
|
||||||
@@ -155,6 +175,11 @@ split_with_highlights(PyObject *self UNUSED, PyObject *args) {
|
|||||||
#undef NEXT_TRUNCATE_POINT
|
#undef NEXT_TRUNCATE_POINT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_resources(void) {
|
||||||
|
free(b.buf); b.buf = NULL; b.capacity = 0; b.pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
{"changed_center", (PyCFunction)changed_center, METH_VARARGS, ""},
|
{"changed_center", (PyCFunction)changed_center, METH_VARARGS, ""},
|
||||||
{"split_with_highlights", (PyCFunction)split_with_highlights, METH_VARARGS, ""},
|
{"split_with_highlights", (PyCFunction)split_with_highlights, METH_VARARGS, ""},
|
||||||
@@ -175,5 +200,6 @@ PyInit_diff_speedup(void) {
|
|||||||
|
|
||||||
m = PyModule_Create(&module);
|
m = PyModule_Create(&module);
|
||||||
if (m == NULL) return NULL;
|
if (m == NULL) return NULL;
|
||||||
|
Py_AtExit(free_resources);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from typing import (
|
|||||||
|
|
||||||
from kitty.cli import parse_args
|
from kitty.cli import parse_args
|
||||||
from kitty.cli_stub import HintsCLIOptions
|
from kitty.cli_stub import HintsCLIOptions
|
||||||
|
from kitty.constants import website_url
|
||||||
from kitty.fast_data_types import set_clipboard_string
|
from kitty.fast_data_types import set_clipboard_string
|
||||||
from kitty.key_encoding import KeyEvent
|
from kitty.key_encoding import KeyEvent
|
||||||
from kitty.typing import BossType, KittyCommonOpts
|
from kitty.typing import BossType, KittyCommonOpts
|
||||||
@@ -94,6 +95,11 @@ def highlight_mark(m: Mark, text: str, current_input: str, alphabet: str, colors
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def debug(*a: Any, **kw: Any) -> None:
|
||||||
|
from ..tui.loop import debug as d
|
||||||
|
d(*a, **kw)
|
||||||
|
|
||||||
|
|
||||||
def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark_indices: Set[int], alphabet: str, colors: Dict[str, str]) -> str:
|
def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark_indices: Set[int], alphabet: str, colors: Dict[str, str]) -> str:
|
||||||
for mark in reversed(all_marks):
|
for mark in reversed(all_marks):
|
||||||
if mark.index in ignore_mark_indices:
|
if mark.index in ignore_mark_indices:
|
||||||
@@ -102,8 +108,7 @@ def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark
|
|||||||
text = text[:mark.start] + mtext + text[mark.end:]
|
text = text[:mark.start] + mtext + text[mark.end:]
|
||||||
|
|
||||||
text = text.replace('\0', '')
|
text = text.replace('\0', '')
|
||||||
|
return re.sub('[\r\n]', '\r\n', text).rstrip()
|
||||||
return text.replace('\n', '\r\n').rstrip()
|
|
||||||
|
|
||||||
|
|
||||||
class Hints(Handler):
|
class Hints(Handler):
|
||||||
@@ -306,7 +311,7 @@ def mark(pattern: str, post_processors: Iterable[PostprocessorFunc], text: str,
|
|||||||
except InvalidMatch:
|
except InvalidMatch:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mark_text = text[s:e].replace('\n', '').replace('\0', '')
|
mark_text = re.sub('[\r\n\0]', '', text[s:e])
|
||||||
yield Mark(idx, s, e, mark_text, groupdict)
|
yield Mark(idx, s, e, mark_text, groupdict)
|
||||||
|
|
||||||
|
|
||||||
@@ -342,12 +347,12 @@ def functions_for(args: HintsCLIOptions) -> Tuple[str, List[PostprocessorFunc]]:
|
|||||||
)
|
)
|
||||||
post_processors.append(url)
|
post_processors.append(url)
|
||||||
elif args.type == 'path':
|
elif args.type == 'path':
|
||||||
pattern = r'(?:\S*/\S+)|(?:\S+[.][a-zA-Z0-9]{2,7})'
|
pattern = r'(?:\S*?/[\r\S]+)|(?:\S[\r\S]*\.[a-zA-Z0-9\r]{2,7})'
|
||||||
post_processors.extend((brackets, quotes))
|
post_processors.extend((brackets, quotes))
|
||||||
elif args.type == 'line':
|
elif args.type == 'line':
|
||||||
pattern = '(?m)^\\s*(.+)[\\s\0]*$'
|
pattern = '(?m)^\\s*(.+)[\\s\0]*$'
|
||||||
elif args.type == 'hash':
|
elif args.type == 'hash':
|
||||||
pattern = '[0-9a-f]{7,128}'
|
pattern = '[0-9a-f][0-9a-f\r]{6,127}'
|
||||||
elif args.type == 'ip':
|
elif args.type == 'ip':
|
||||||
pattern = (
|
pattern = (
|
||||||
# # IPv4 with no validation
|
# # IPv4 with no validation
|
||||||
@@ -370,16 +375,22 @@ def functions_for(args: HintsCLIOptions) -> Tuple[str, List[PostprocessorFunc]]:
|
|||||||
|
|
||||||
def convert_text(text: str, cols: int) -> str:
|
def convert_text(text: str, cols: int) -> str:
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
empty_line = '\0' * cols
|
empty_line = '\0' * cols + '\n'
|
||||||
for full_line in text.split('\n'):
|
for full_line in text.split('\n'):
|
||||||
if full_line:
|
if full_line:
|
||||||
if not full_line.rstrip('\r'): # empty lines
|
if not full_line.rstrip('\r'): # empty lines
|
||||||
lines.extend(repeat(empty_line, len(full_line)))
|
lines.extend(repeat(empty_line, len(full_line)))
|
||||||
continue
|
continue
|
||||||
|
appended = False
|
||||||
for line in full_line.split('\r'):
|
for line in full_line.split('\r'):
|
||||||
if line:
|
if line:
|
||||||
lines.append(line.ljust(cols, '\0'))
|
lines.append(line.ljust(cols, '\0'))
|
||||||
return '\n'.join(lines)
|
lines.append('\r')
|
||||||
|
appended = True
|
||||||
|
if appended:
|
||||||
|
lines[-1] = '\n'
|
||||||
|
rstripped = re.sub('[\r\n]+$', '', ''.join(lines))
|
||||||
|
return rstripped
|
||||||
|
|
||||||
|
|
||||||
def parse_input(text: str) -> str:
|
def parse_input(text: str) -> str:
|
||||||
@@ -630,7 +641,7 @@ The foreground color for text pointed to by the hints
|
|||||||
--customize-processing
|
--customize-processing
|
||||||
Name of a python file in the kitty config directory which will be imported to provide
|
Name of a python file in the kitty config directory which will be imported to provide
|
||||||
custom implementations for pattern finding and performing actions
|
custom implementations for pattern finding and performing actions
|
||||||
on selected matches. See https://sw.kovidgoyal.net/kitty/kittens/hints.html
|
on selected matches. See {hints_url}
|
||||||
for details. You can also specify absolute paths to load the script from elsewhere.
|
for details. You can also specify absolute paths to load the script from elsewhere.
|
||||||
|
|
||||||
|
|
||||||
@@ -639,7 +650,8 @@ The window title for the hints window, default title is selected based on
|
|||||||
the type of text being hinted.
|
the type of text being hinted.
|
||||||
'''.format(
|
'''.format(
|
||||||
default_regex=DEFAULT_REGEX,
|
default_regex=DEFAULT_REGEX,
|
||||||
line='{{line}}', path='{{path}}'
|
line='{{line}}', path='{{path}}',
|
||||||
|
hints_url=website_url('kittens/hints'),
|
||||||
).format
|
).format
|
||||||
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
|
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
|
||||||
usage = ''
|
usage = ''
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
url_delimiters = '\x00-\x09\x0b-\x20\x7f-\xa0\xad\u0600-\u0605\u061c\u06dd\u070f\u08e2\u1680\u180e\u2000-\u200f\u2028-\u202f\u205f-\u2064\u2066-\u206f\u3000\ud800-\uf8ff\ufeff\ufff9-\ufffb\U000110bd\U000110cd\U00013430-\U00013438\U0001bca0-\U0001bca3\U0001d173-\U0001d17a\U000e0001\U000e0020-\U000e007f\U000f0000-\U000ffffd\U00100000-\U0010fffd' # noqa
|
# generated by gen-wcwidth.py, do not edit
|
||||||
|
|
||||||
|
url_delimiters = '\x00-\x09\x0b-\x0c\x0e-\x20\x7f-\xa0\xad\u0600-\u0605\u061c\u06dd\u070f\u08e2\u1680\u180e\u2000-\u200f\u2028-\u202f\u205f-\u2064\u2066-\u206f\u3000\ud800-\uf8ff\ufeff\ufff9-\ufffb\U000110bd\U000110cd\U00013430-\U00013438\U0001bca0-\U0001bca3\U0001d173-\U0001d17a\U000e0001\U000e0020-\U000e007f\U000f0000-\U000ffffd\U00100000-\U0010fffd' # noqa
|
||||||
@@ -87,7 +87,7 @@ class TerminalVersion(Query):
|
|||||||
@query
|
@query
|
||||||
class AllowHyperlinks(Query):
|
class AllowHyperlinks(Query):
|
||||||
name: str = 'allow_hyperlinks'
|
name: str = 'allow_hyperlinks'
|
||||||
help_text: str = 'yes, no or ask'
|
help_text: str = 'The :opt:`setting <allow_hyperlinks>` for allowing hyperlinks can be yes, no or ask'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_result(opts: Options) -> str:
|
def get_result(opts: Options) -> str:
|
||||||
@@ -152,6 +152,16 @@ class FontSize(Query):
|
|||||||
return f'{opts.font_size:g}'
|
return f'{opts.font_size:g}'
|
||||||
|
|
||||||
|
|
||||||
|
@query
|
||||||
|
class ClipboardControl(Query):
|
||||||
|
name: str = 'clipboard_control'
|
||||||
|
help_text: str = 'The :opt:`setting <clipboard_control>` for allowing reads/writes to/from the clipboard'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_result(opts: Options) -> str:
|
||||||
|
return ' '.join(opts.clipboard_control)
|
||||||
|
|
||||||
|
|
||||||
def get_result(name: str) -> Optional[str]:
|
def get_result(name: str) -> Optional[str]:
|
||||||
from kitty.fast_data_types import get_options
|
from kitty.fast_data_types import get_options
|
||||||
q = all_queries.get(name)
|
q = all_queries.get(name)
|
||||||
@@ -209,11 +219,12 @@ Note that when calling this from another program, be very
|
|||||||
careful not to perform any I/O on the terminal device
|
careful not to perform any I/O on the terminal device
|
||||||
until the kitten exits.
|
until the kitten exits.
|
||||||
|
|
||||||
Available queries are::
|
Available queries are:
|
||||||
|
|
||||||
{}
|
{}
|
||||||
'''.format(' ' + '\n '.join(
|
|
||||||
f'{name}: {c.help_text}' for name, c in all_queries.items()))
|
'''.format('\n'.join(
|
||||||
|
f'``{name}``\n {c.help_text}\n' for name, c in all_queries.items()))
|
||||||
usage = '[query1 query2 ...]'
|
usage = '[query1 query2 ...]'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
def resolved_kitten(k: str) -> str:
|
def resolved_kitten(k: str) -> str:
|
||||||
return aliases.get(k, k).replace('-', '_')
|
ans = aliases.get(k, k)
|
||||||
|
head, tail = os.path.split(ans)
|
||||||
|
tail = tail.replace('-', '_')
|
||||||
|
return os.path.join(head, tail)
|
||||||
|
|
||||||
|
|
||||||
def path_to_custom_kitten(config_dir: str, kitten: str) -> str:
|
def path_to_custom_kitten(config_dir: str, kitten: str) -> str:
|
||||||
|
|||||||
@@ -175,6 +175,18 @@ def get_connection_data(args: List[str]) -> Optional[SSHConnectionData]:
|
|||||||
return SSHConnectionData(found_ssh, arg, port)
|
return SSHConnectionData(found_ssh, arg, port)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidSSHArgs(ValueError):
|
||||||
|
|
||||||
|
def __init__(self, msg: str = ''):
|
||||||
|
super().__init__(msg)
|
||||||
|
self.err_msg = msg
|
||||||
|
|
||||||
|
def system_exit(self) -> None:
|
||||||
|
if self.err_msg:
|
||||||
|
print(self.err_msg, file=sys.stderr)
|
||||||
|
os.execlp('ssh', 'ssh')
|
||||||
|
|
||||||
|
|
||||||
def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]:
|
def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]:
|
||||||
boolean_ssh_args, other_ssh_args = get_ssh_cli()
|
boolean_ssh_args, other_ssh_args = get_ssh_cli()
|
||||||
passthrough_args = {'-' + x for x in 'Nnf'}
|
passthrough_args = {'-' + x for x in 'Nnf'}
|
||||||
@@ -182,11 +194,16 @@ def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]:
|
|||||||
server_args: List[str] = []
|
server_args: List[str] = []
|
||||||
expecting_option_val = False
|
expecting_option_val = False
|
||||||
passthrough = False
|
passthrough = False
|
||||||
|
stop_option_processing = False
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if len(server_args) > 1:
|
if len(server_args) > 1 or stop_option_processing:
|
||||||
server_args.append(arg)
|
server_args.append(arg)
|
||||||
continue
|
continue
|
||||||
if arg.startswith('-') and not expecting_option_val:
|
if arg.startswith('-') and not expecting_option_val:
|
||||||
|
if arg == '--':
|
||||||
|
stop_option_processing = True
|
||||||
|
continue
|
||||||
|
# could be a multi-character option
|
||||||
all_args = arg[1:]
|
all_args = arg[1:]
|
||||||
for i, arg in enumerate(all_args):
|
for i, arg in enumerate(all_args):
|
||||||
arg = '-' + arg
|
arg = '-' + arg
|
||||||
@@ -203,7 +220,7 @@ def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]:
|
|||||||
else:
|
else:
|
||||||
expecting_option_val = True
|
expecting_option_val = True
|
||||||
break
|
break
|
||||||
raise SystemExit('Unknown option: {}'.format(arg))
|
raise InvalidSSHArgs('unknown option -- {}'.format(arg[1:]))
|
||||||
continue
|
continue
|
||||||
if expecting_option_val:
|
if expecting_option_val:
|
||||||
ssh_args.append(arg)
|
ssh_args.append(arg)
|
||||||
@@ -211,7 +228,7 @@ def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]:
|
|||||||
continue
|
continue
|
||||||
server_args.append(arg)
|
server_args.append(arg)
|
||||||
if not server_args:
|
if not server_args:
|
||||||
raise SystemExit('Must specify server to connect to')
|
raise InvalidSSHArgs()
|
||||||
return ssh_args, server_args, passthrough
|
return ssh_args, server_args, passthrough
|
||||||
|
|
||||||
|
|
||||||
@@ -255,7 +272,10 @@ def main(args: List[str]) -> NoReturn:
|
|||||||
if args and args[0] == 'use-python':
|
if args and args[0] == 'use-python':
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
use_posix = False
|
use_posix = False
|
||||||
ssh_args, server_args, passthrough = parse_ssh_args(args)
|
try:
|
||||||
|
ssh_args, server_args, passthrough = parse_ssh_args(args)
|
||||||
|
except InvalidSSHArgs as e:
|
||||||
|
e.system_exit()
|
||||||
cmd = ['ssh'] + ssh_args
|
cmd = ['ssh'] + ssh_args
|
||||||
if passthrough:
|
if passthrough:
|
||||||
cmd += server_args
|
cmd += server_args
|
||||||
@@ -263,6 +283,7 @@ def main(args: List[str]) -> NoReturn:
|
|||||||
hostname, remote_args = server_args[0], server_args[1:]
|
hostname, remote_args = server_args[0], server_args[1:]
|
||||||
if not remote_args:
|
if not remote_args:
|
||||||
cmd.append('-t')
|
cmd.append('-t')
|
||||||
|
cmd.append('--')
|
||||||
cmd.append(hostname)
|
cmd.append(hostname)
|
||||||
terminfo = subprocess.check_output(['infocmp', '-a']).decode('utf-8')
|
terminfo = subprocess.check_output(['infocmp', '-a']).decode('utf-8')
|
||||||
f = get_posix_cmd if use_posix else get_python_cmd
|
f = get_posix_cmd if use_posix else get_python_cmd
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ class Handler:
|
|||||||
def on_eot(self) -> None:
|
def on_eot(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def on_writing_finished(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
def on_kitty_cmd_response(self, response: Dict) -> None:
|
def on_kitty_cmd_response(self, response: Dict) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,15 @@ from contextlib import suppress
|
|||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from itertools import count
|
from itertools import count
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Callable, DefaultDict, Deque, Dict, Iterator, List, Optional,
|
Any, Callable, ClassVar, DefaultDict, Deque, Dict, Generic, Iterator, List,
|
||||||
Sequence, Tuple, Union
|
Optional, Sequence, Tuple, Type, TypeVar, Union, cast
|
||||||
)
|
)
|
||||||
|
|
||||||
from kitty.conf.utils import positive_float, positive_int
|
from kitty.conf.utils import positive_float, positive_int
|
||||||
from kitty.fast_data_types import create_canvas
|
from kitty.fast_data_types import create_canvas
|
||||||
from kitty.typing import (
|
from kitty.typing import (
|
||||||
CompletedProcess, GRT_a, GRT_d, GRT_f, GRT_m, GRT_o, GRT_t, HandlerType
|
GRT_C, CompletedProcess, GRT_a, GRT_d, GRT_f, GRT_m, GRT_o, GRT_t,
|
||||||
|
HandlerType
|
||||||
)
|
)
|
||||||
from kitty.utils import ScreenSize, find_exe, fit_image
|
from kitty.utils import ScreenSize, find_exe, fit_image
|
||||||
|
|
||||||
@@ -298,49 +299,75 @@ def can_display_images() -> bool:
|
|||||||
|
|
||||||
ImageKey = Tuple[str, int, int]
|
ImageKey = Tuple[str, int, int]
|
||||||
SentImageKey = Tuple[int, int, int]
|
SentImageKey = Tuple[int, int, int]
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
|
class Alias(Generic[T]):
|
||||||
|
|
||||||
|
currently_processing: ClassVar[str] = ''
|
||||||
|
|
||||||
|
def __init__(self, defval: T) -> None:
|
||||||
|
self.name = ''
|
||||||
|
self.defval = defval
|
||||||
|
|
||||||
|
def __get__(self, instance: Optional['GraphicsCommand'], cls: Optional[Type['GraphicsCommand']] = None) -> T:
|
||||||
|
if instance is None:
|
||||||
|
return self.defval
|
||||||
|
return cast(T, instance._actual_values.get(self.name, self.defval))
|
||||||
|
|
||||||
|
def __set__(self, instance: 'GraphicsCommand', val: T) -> None:
|
||||||
|
if val == self.defval:
|
||||||
|
instance._actual_values.pop(self.name, None)
|
||||||
|
else:
|
||||||
|
instance._actual_values[self.name] = val
|
||||||
|
|
||||||
|
def __set_name__(self, owner: Type['GraphicsCommand'], name: str) -> None:
|
||||||
|
if len(name) == 1:
|
||||||
|
Alias.currently_processing = name
|
||||||
|
self.name = Alias.currently_processing
|
||||||
|
|
||||||
|
|
||||||
class GraphicsCommand:
|
class GraphicsCommand:
|
||||||
a: GRT_a = 't' # action
|
a = action = Alias(cast(GRT_a, 't'))
|
||||||
q: int = 0 # suppress responses
|
q = quiet = Alias(0)
|
||||||
f: GRT_f = 32 # image data format
|
f = format = Alias(32)
|
||||||
t: GRT_t = 'd' # transmission medium
|
t = transmission_type = Alias(cast(GRT_t, 'd'))
|
||||||
s: int = 0 # sent image width
|
s = data_width = animation_state = Alias(0)
|
||||||
v: int = 0 # sent image height
|
v = data_height = loop_count = Alias(0)
|
||||||
S: int = 0 # size of data to read from file
|
S = data_size = Alias(0)
|
||||||
O: int = 0 # offset of data to read from file
|
O = data_offset = Alias(0) # noqa
|
||||||
i: int = 0 # image id
|
i = image_id = Alias(0)
|
||||||
I: int = 0 # image number
|
I = image_number = Alias(0) # noqa
|
||||||
p: int = 0 # placement id
|
p = placement_id = Alias(0)
|
||||||
o: Optional[GRT_o] = None # type of compression
|
o = compression = Alias(cast(Optional[GRT_o], None))
|
||||||
m: GRT_m = 0 # 0 or 1 whether there is more chunked data
|
m = more = Alias(cast(GRT_m, 0))
|
||||||
x: int = 0 # left edge of image area to display
|
x = left_edge = Alias(0)
|
||||||
y: int = 0 # top edge of image area to display
|
y = top_edge = Alias(0)
|
||||||
w: int = 0 # image width to display
|
w = width = Alias(0)
|
||||||
h: int = 0 # image height to display
|
h = height = Alias(0)
|
||||||
X: int = 0 # X-offset within cell
|
X = cell_x_offset = blend_mode = Alias(0)
|
||||||
Y: int = 0 # Y-offset within cell
|
Y = cell_y_offset = bgcolor = Alias(0)
|
||||||
c: int = 0 # number of cols to display image over
|
c = columns = other_frame_number = dest_frame = Alias(0)
|
||||||
r: int = 0 # number of rows to display image over
|
r = rows = frame_number = source_frame = Alias(0)
|
||||||
z: int = 0 # z-index
|
z = z_index = gap = Alias(0)
|
||||||
d: GRT_d = 'a' # what to delete
|
C = cursor_movement = compose_mode = Alias(cast(GRT_C, 0))
|
||||||
|
d = delete_action = Alias(cast(GRT_d, 'a'))
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._actual_values: Dict[str, Any] = {}
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return self.serialize().decode('ascii').replace('\033', '^]')
|
return self.serialize().decode('ascii').replace('\033', '^]')
|
||||||
|
|
||||||
def clone(self) -> 'GraphicsCommand':
|
def clone(self) -> 'GraphicsCommand':
|
||||||
ans = GraphicsCommand()
|
ans = GraphicsCommand()
|
||||||
for k in GraphicsCommand.__annotations__:
|
ans._actual_values = self._actual_values.copy()
|
||||||
setattr(ans, k, getattr(self, k))
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def serialize(self, payload: Union[bytes, str] = b'') -> bytes:
|
def serialize(self, payload: Union[bytes, str] = b'') -> bytes:
|
||||||
items = []
|
items = []
|
||||||
for k in GraphicsCommand.__annotations__:
|
for k, val in self._actual_values.items():
|
||||||
val: Union[str, None, int] = getattr(self, k)
|
items.append('{}={}'.format(k, val))
|
||||||
defval: Union[str, None, int] = getattr(GraphicsCommand, k)
|
|
||||||
if val != defval and val is not None:
|
|
||||||
items.append('{}={}'.format(k, val))
|
|
||||||
|
|
||||||
ans: List[bytes] = []
|
ans: List[bytes] = []
|
||||||
w = ans.append
|
w = ans.append
|
||||||
@@ -355,9 +382,27 @@ class GraphicsCommand:
|
|||||||
return b''.join(ans)
|
return b''.join(ans)
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
for k in GraphicsCommand.__annotations__:
|
self._actual_values = {}
|
||||||
defval: Union[str, None, int] = getattr(GraphicsCommand, k)
|
|
||||||
setattr(self, k, defval)
|
def iter_transmission_chunks(self, data: Optional[bytes] = None, level: int = -1, compression_threshold: int = 1024) -> Iterator[bytes]:
|
||||||
|
if data is None:
|
||||||
|
yield self.serialize()
|
||||||
|
return
|
||||||
|
gc = self.clone()
|
||||||
|
gc.S = len(data)
|
||||||
|
if level and len(data) >= compression_threshold:
|
||||||
|
import zlib
|
||||||
|
compressed = zlib.compress(data, level)
|
||||||
|
if len(compressed) < len(data):
|
||||||
|
gc.o = 'z'
|
||||||
|
data = compressed
|
||||||
|
gc.S = len(data)
|
||||||
|
data = standard_b64encode(data)
|
||||||
|
while data:
|
||||||
|
chunk, data = data[:4096], data[4096:]
|
||||||
|
gc.m = 1 if data else 0
|
||||||
|
yield gc.serialize(chunk)
|
||||||
|
gc.clear()
|
||||||
|
|
||||||
|
|
||||||
class Placement:
|
class Placement:
|
||||||
|
|||||||
@@ -39,20 +39,27 @@ class BinaryWrite(Protocol):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def debug_write(*a: Any, **kw: Any) -> None:
|
||||||
|
from base64 import standard_b64encode
|
||||||
|
fobj = kw.pop('file', sys.stderr.buffer)
|
||||||
|
buf = io.StringIO()
|
||||||
|
kw['file'] = buf
|
||||||
|
print(*a, **kw)
|
||||||
|
stext = buf.getvalue()
|
||||||
|
for i in range(0, len(stext), 256):
|
||||||
|
chunk = stext[i:i + 256]
|
||||||
|
text = b'\x1bP@kitty-print|' + standard_b64encode(chunk.encode('utf-8')) + b'\x1b\\'
|
||||||
|
fobj.write(text)
|
||||||
|
fobj.flush()
|
||||||
|
|
||||||
|
|
||||||
class Debug:
|
class Debug:
|
||||||
|
|
||||||
fobj: Optional[BinaryWrite] = None
|
fobj: Optional[BinaryWrite] = None
|
||||||
|
|
||||||
def __call__(self, *a: Any, **kw: Any) -> None:
|
def __call__(self, *a: Any, **kw: Any) -> None:
|
||||||
from base64 import standard_b64encode
|
kw['file'] = self.fobj or sys.stdout.buffer
|
||||||
buf = io.StringIO()
|
debug_write(*a, **kw)
|
||||||
kw['file'] = buf
|
|
||||||
print(*a, **kw)
|
|
||||||
stext = buf.getvalue()
|
|
||||||
text = b'\x1bP@kitty-print|' + standard_b64encode(stext.encode('utf-8')) + b'\x1b\\'
|
|
||||||
fobj = self.fobj or sys.stdout.buffer
|
|
||||||
fobj.write(text)
|
|
||||||
fobj.flush()
|
|
||||||
|
|
||||||
|
|
||||||
debug = Debug()
|
debug = Debug()
|
||||||
@@ -336,6 +343,7 @@ class Loop:
|
|||||||
self.write_buf: List[bytes] = []
|
self.write_buf: List[bytes] = []
|
||||||
self.asycio_loop.remove_writer(fd)
|
self.asycio_loop.remove_writer(fd)
|
||||||
self.waiting_for_writes = False
|
self.waiting_for_writes = False
|
||||||
|
handler.on_writing_finished()
|
||||||
else:
|
else:
|
||||||
consumed = 0
|
consumed = 0
|
||||||
for i, buf in enumerate(self.write_buf):
|
for i, buf in enumerate(self.write_buf):
|
||||||
|
|||||||
@@ -352,24 +352,17 @@ def set_default_colors(
|
|||||||
|
|
||||||
@cmd
|
@cmd
|
||||||
def write_to_clipboard(data: Union[str, bytes], use_primary: bool = False) -> str:
|
def write_to_clipboard(data: Union[str, bytes], use_primary: bool = False) -> str:
|
||||||
if isinstance(data, str):
|
|
||||||
data = data.encode('utf-8')
|
|
||||||
from base64 import standard_b64encode
|
from base64 import standard_b64encode
|
||||||
fmt = 'p' if use_primary else 'c'
|
fmt = 'p' if use_primary else 'c'
|
||||||
|
if isinstance(data, str):
|
||||||
def esc(chunk: str) -> str:
|
data = data.encode('utf-8')
|
||||||
return '\x1b]52;{};{}\x07'.format(fmt, chunk)
|
payload = standard_b64encode(data).decode('ascii')
|
||||||
|
return f'\x1b]52;{fmt};{payload}\a'
|
||||||
ans = esc('!') # clear clipboard buffer
|
|
||||||
for chunk in (data[i:i+512] for i in range(0, len(data), 512)):
|
|
||||||
s = standard_b64encode(chunk).decode('ascii')
|
|
||||||
ans += esc(s)
|
|
||||||
return ans
|
|
||||||
|
|
||||||
|
|
||||||
@cmd
|
@cmd
|
||||||
def request_from_clipboard(use_primary: bool = False) -> str:
|
def request_from_clipboard(use_primary: bool = False) -> str:
|
||||||
return '\x1b]52;{};?\x07'.format('p' if use_primary else 'c')
|
return '\x1b]52;{};?\a'.format('p' if use_primary else 'c')
|
||||||
|
|
||||||
|
|
||||||
# Boilerplate to make operations available via Handler.cmd {{{
|
# Boilerplate to make operations available via Handler.cmd {{{
|
||||||
|
|||||||
2
kittens/unicode_input/names.h
generated
2
kittens/unicode_input/names.h
generated
@@ -1,4 +1,4 @@
|
|||||||
// unicode data, built from the unicode standard on: 2021-04-02
|
// unicode data, built from the unicode standard on: 2021-07-19
|
||||||
// see gen-wcwidth.py
|
// see gen-wcwidth.py
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
|
|||||||
111
kitty/actions.py
Normal file
111
kitty/actions.py
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
from typing import Dict, List, NamedTuple
|
||||||
|
|
||||||
|
from .boss import Boss
|
||||||
|
from .tabs import Tab
|
||||||
|
from .types import run_once
|
||||||
|
from .window import Window
|
||||||
|
|
||||||
|
|
||||||
|
class Action(NamedTuple):
|
||||||
|
name: str
|
||||||
|
group: str
|
||||||
|
short_help: str
|
||||||
|
long_help: str
|
||||||
|
|
||||||
|
|
||||||
|
groups = {
|
||||||
|
'cp': 'Copy/paste',
|
||||||
|
'sc': 'Scrolling',
|
||||||
|
'win': 'Window management',
|
||||||
|
'tab': 'Tab management',
|
||||||
|
'mouse': 'Mouse actions',
|
||||||
|
'mk': 'Marks',
|
||||||
|
'lay': 'Layouts',
|
||||||
|
'misc': 'Miscellaneous',
|
||||||
|
}
|
||||||
|
group_title = groups.__getitem__
|
||||||
|
|
||||||
|
|
||||||
|
@run_once
|
||||||
|
def get_all_actions() -> Dict[str, List[Action]]:
|
||||||
|
|
||||||
|
ans: Dict[str, List[Action]] = {}
|
||||||
|
|
||||||
|
def is_action(x: object) -> bool:
|
||||||
|
doc = getattr(x, '__doc__', '')
|
||||||
|
return bool(doc and doc.strip().startswith('@ac:'))
|
||||||
|
|
||||||
|
def as_action(x: object) -> Action:
|
||||||
|
doc = inspect.cleandoc(x.__doc__ or '')
|
||||||
|
lines = doc.splitlines()
|
||||||
|
first = lines.pop(0)
|
||||||
|
parts = first.split(':', 2)
|
||||||
|
grp = parts[1].strip()
|
||||||
|
short_help = parts[2].strip()
|
||||||
|
long_help = '\n'.join(lines).strip()
|
||||||
|
return Action(getattr(x, '__name__'), grp, short_help, long_help)
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
for cls in (Window, Tab, Boss):
|
||||||
|
for (name, func) in inspect.getmembers(cls, is_action):
|
||||||
|
ac = as_action(func)
|
||||||
|
if ac.name not in seen:
|
||||||
|
ans.setdefault(ac.group, []).append(ac)
|
||||||
|
seen.add(ac.name)
|
||||||
|
for i, which in enumerate('first second third fourth fifth sixth seventh eighth ninth tenth'.split()):
|
||||||
|
name = f'{which}_window'
|
||||||
|
if name not in seen:
|
||||||
|
seen.add(name)
|
||||||
|
ans['win'].append(Action(name, 'win', f'Focus the {which} window', ''))
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def dump() -> None:
|
||||||
|
from pprint import pprint
|
||||||
|
pprint(get_all_actions())
|
||||||
|
|
||||||
|
|
||||||
|
def as_rst() -> str:
|
||||||
|
from .options.definition import definition
|
||||||
|
from .conf.types import Mapping
|
||||||
|
allg = get_all_actions()
|
||||||
|
lines: List[str] = []
|
||||||
|
a = lines.append
|
||||||
|
maps: Dict[str, List[Mapping]] = {}
|
||||||
|
for m in definition.iter_all_maps():
|
||||||
|
if m.documented:
|
||||||
|
func = m.action_def.split()[0]
|
||||||
|
maps.setdefault(func, []).append(m)
|
||||||
|
|
||||||
|
for group in sorted(allg, key=lambda x: group_title(x).lower()):
|
||||||
|
title = group_title(group)
|
||||||
|
a('')
|
||||||
|
a(f'.. _action-group-{group}:')
|
||||||
|
a('')
|
||||||
|
a(title)
|
||||||
|
a('-' * len(title))
|
||||||
|
a('')
|
||||||
|
|
||||||
|
for action in allg[group]:
|
||||||
|
a('')
|
||||||
|
a(f'.. _action-{action.name}:')
|
||||||
|
a('')
|
||||||
|
a(action.name)
|
||||||
|
a('+' * len(action.name))
|
||||||
|
a('')
|
||||||
|
a(action.short_help)
|
||||||
|
a('')
|
||||||
|
if action.long_help:
|
||||||
|
a(action.long_help)
|
||||||
|
if action.name in maps:
|
||||||
|
a('')
|
||||||
|
a('Default shortcuts using this action:')
|
||||||
|
scs = {f':sc:`kitty.{m.name}`' for m in maps[action.name]}
|
||||||
|
a(', '.join(sorted(scs)))
|
||||||
|
return '\n'.join(lines)
|
||||||
195
kitty/boss.py
195
kitty/boss.py
@@ -24,7 +24,7 @@ from .conf.utils import BadLine, KeyAction, to_cmdline
|
|||||||
from .config import common_opts_as_dict, prepare_config_file_for_editing
|
from .config import common_opts_as_dict, prepare_config_file_for_editing
|
||||||
from .constants import (
|
from .constants import (
|
||||||
appname, config_dir, is_macos, is_wayland, kitty_exe,
|
appname, config_dir, is_macos, is_wayland, kitty_exe,
|
||||||
supports_primary_selection
|
supports_primary_selection, website_url
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
CLOSE_BEING_CONFIRMED, IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED,
|
CLOSE_BEING_CONFIRMED, IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED,
|
||||||
@@ -32,11 +32,12 @@ from .fast_data_types import (
|
|||||||
background_opacity_of, change_background_opacity, change_os_window_state,
|
background_opacity_of, change_background_opacity, change_os_window_state,
|
||||||
cocoa_set_menubar_title, create_os_window,
|
cocoa_set_menubar_title, create_os_window,
|
||||||
current_application_quit_request, current_os_window, destroy_global_data,
|
current_application_quit_request, current_os_window, destroy_global_data,
|
||||||
focus_os_window, get_clipboard_string, get_options, global_font_size,
|
focus_os_window, get_clipboard_string, get_options, get_os_window_size,
|
||||||
mark_os_window_for_close, os_window_font_size, patch_global_colors,
|
global_font_size, mark_os_window_for_close, os_window_font_size,
|
||||||
safe_pipe, set_application_quit_request, set_background_image, set_boss,
|
patch_global_colors, safe_pipe, set_application_quit_request,
|
||||||
set_clipboard_string, set_in_sequence_mode, set_options, thread_write,
|
set_background_image, set_boss, set_clipboard_string, set_in_sequence_mode,
|
||||||
toggle_fullscreen, toggle_maximized
|
set_options, set_os_window_size, thread_write, toggle_fullscreen,
|
||||||
|
toggle_maximized
|
||||||
)
|
)
|
||||||
from .keys import get_shortcut, shortcut_matches
|
from .keys import get_shortcut, shortcut_matches
|
||||||
from .layout.base import set_layout_options
|
from .layout.base import set_layout_options
|
||||||
@@ -52,10 +53,11 @@ from .tabs import (
|
|||||||
from .types import SingleKey
|
from .types import SingleKey
|
||||||
from .typing import PopenType, TypedDict
|
from .typing import PopenType, TypedDict
|
||||||
from .utils import (
|
from .utils import (
|
||||||
func_name, get_editor, get_primary_selection, is_path_in_temp_dir,
|
func_name, get_editor, get_new_os_window_size, get_primary_selection,
|
||||||
log_error, open_url, parse_address_spec, parse_uri_list,
|
is_path_in_temp_dir, log_error, open_url, parse_address_spec,
|
||||||
platform_window_id, read_shell_environment, remove_socket_file, safe_print,
|
parse_uri_list, platform_window_id, read_shell_environment,
|
||||||
set_primary_selection, single_instance, startup_notification_handler
|
remove_socket_file, safe_print, set_primary_selection, single_instance,
|
||||||
|
startup_notification_handler
|
||||||
)
|
)
|
||||||
from .window import MatchPatternType, Window
|
from .window import MatchPatternType, Window
|
||||||
|
|
||||||
@@ -332,6 +334,7 @@ class Boss:
|
|||||||
return self.add_os_window(startup_session)
|
return self.add_os_window(startup_session)
|
||||||
|
|
||||||
def new_os_window(self, *args: str) -> None:
|
def new_os_window(self, *args: str) -> None:
|
||||||
|
'@ac:win: New OS Window'
|
||||||
self._new_os_window(args)
|
self._new_os_window(args)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -341,6 +344,7 @@ class Boss:
|
|||||||
return t.active_window_for_cwd
|
return t.active_window_for_cwd
|
||||||
|
|
||||||
def new_os_window_with_cwd(self, *args: str) -> None:
|
def new_os_window_with_cwd(self, *args: str) -> None:
|
||||||
|
'@ac:win: New OS Window with the same working directory as the currently active window'
|
||||||
w = self.active_window_for_cwd
|
w = self.active_window_for_cwd
|
||||||
cwd_from = w.child.pid_for_cwd if w is not None else None
|
cwd_from = w.child.pid_for_cwd if w is not None else None
|
||||||
self._new_os_window(args, cwd_from)
|
self._new_os_window(args, cwd_from)
|
||||||
@@ -377,6 +381,15 @@ class Boss:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def remote_control(self, *args: str) -> None:
|
def remote_control(self, *args: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Run a remote control command
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
map F1 remote_control set-spacing margin=30
|
||||||
|
|
||||||
|
See :ref:`rc_mapping` for details.
|
||||||
|
'''
|
||||||
from .rc.base import (
|
from .rc.base import (
|
||||||
PayloadGetter, command_for_name, parse_subcommand_cli
|
PayloadGetter, command_for_name, parse_subcommand_cli
|
||||||
)
|
)
|
||||||
@@ -489,6 +502,7 @@ class Boss:
|
|||||||
self.child_monitor.mark_for_close(window.id)
|
self.child_monitor.mark_for_close(window.id)
|
||||||
|
|
||||||
def close_tab(self, tab: Optional[Tab] = None) -> None:
|
def close_tab(self, tab: Optional[Tab] = None) -> None:
|
||||||
|
'@ac:tab: Close the current tab'
|
||||||
tab = tab or self.active_tab
|
tab = tab or self.active_tab
|
||||||
if tab:
|
if tab:
|
||||||
self.confirm_tab_close(tab)
|
self.confirm_tab_close(tab)
|
||||||
@@ -520,11 +534,13 @@ class Boss:
|
|||||||
for window in tab:
|
for window in tab:
|
||||||
self.close_window(window)
|
self.close_window(window)
|
||||||
|
|
||||||
def toggle_fullscreen(self) -> None:
|
def toggle_fullscreen(self, os_window_id: int = 0) -> None:
|
||||||
toggle_fullscreen()
|
'@ac:win: Toggle the fullscreen status of the active OS Window'
|
||||||
|
toggle_fullscreen(os_window_id)
|
||||||
|
|
||||||
def toggle_maximized(self) -> None:
|
def toggle_maximized(self, os_window_id: int = 0) -> None:
|
||||||
toggle_maximized()
|
'@ac:win: Toggle the maximized status of the active OS Window'
|
||||||
|
toggle_maximized(os_window_id)
|
||||||
|
|
||||||
def start(self, first_os_window_id: int) -> None:
|
def start(self, first_os_window_id: int) -> None:
|
||||||
if not getattr(self, 'io_thread_started', False):
|
if not getattr(self, 'io_thread_started', False):
|
||||||
@@ -551,6 +567,21 @@ class Boss:
|
|||||||
tm.resize()
|
tm.resize()
|
||||||
|
|
||||||
def clear_terminal(self, action: str, only_active: bool) -> None:
|
def clear_terminal(self, action: str, only_active: bool) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Clear the terminal
|
||||||
|
|
||||||
|
See :sc:`reset_terminal` for details. For example::
|
||||||
|
|
||||||
|
# Reset the terminal
|
||||||
|
map kitty_mod+f9 clear_terminal reset active
|
||||||
|
# Clear the terminal screen by erasing all contents
|
||||||
|
map kitty_mod+f10 clear_terminal clear active
|
||||||
|
# Clear the terminal scrollback by erasing it
|
||||||
|
map kitty_mod+f11 clear_terminal scrollback active
|
||||||
|
# Scroll the contents of the screen into the scrollback
|
||||||
|
map kitty_mod+f12 clear_terminal scroll active
|
||||||
|
|
||||||
|
'''
|
||||||
if only_active:
|
if only_active:
|
||||||
windows = []
|
windows = []
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
@@ -585,6 +616,11 @@ class Boss:
|
|||||||
self.change_font_size(True, None, new_size)
|
self.change_font_size(True, None, new_size)
|
||||||
|
|
||||||
def change_font_size(self, all_windows: bool, increment_operation: Optional[str], amt: float) -> None:
|
def change_font_size(self, all_windows: bool, increment_operation: Optional[str], amt: float) -> None:
|
||||||
|
'''
|
||||||
|
@ac:win: Change the font size for the current or all OS Windows
|
||||||
|
|
||||||
|
See :ref:`conf-kitty-shortcuts.fonts` for details.
|
||||||
|
'''
|
||||||
def calc_new_size(old_size: float) -> float:
|
def calc_new_size(old_size: float) -> float:
|
||||||
new_size = old_size
|
new_size = old_size
|
||||||
if amt == 0:
|
if amt == 0:
|
||||||
@@ -641,6 +677,15 @@ class Boss:
|
|||||||
change_background_opacity(os_window_id, max(0.1, min(opacity, 1.0)))
|
change_background_opacity(os_window_id, max(0.1, min(opacity, 1.0)))
|
||||||
|
|
||||||
def set_background_opacity(self, opacity: str) -> None:
|
def set_background_opacity(self, opacity: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:win: Set the background opacity for the active OS Window
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
map f1 set_background_opacity +0.1
|
||||||
|
map f2 set_background_opacity -0.1
|
||||||
|
map f3 set_background_opacity 0.5
|
||||||
|
'''
|
||||||
window = self.active_window
|
window = self.active_window
|
||||||
if window is None or not opacity:
|
if window is None or not opacity:
|
||||||
return
|
return
|
||||||
@@ -717,6 +762,11 @@ class Boss:
|
|||||||
self.dispatch_action(matched_action)
|
self.dispatch_action(matched_action)
|
||||||
|
|
||||||
def start_resizing_window(self) -> None:
|
def start_resizing_window(self) -> None:
|
||||||
|
'''
|
||||||
|
@ac:win: Resize the active window interactively
|
||||||
|
|
||||||
|
See :ref:`window_resizing` for details.
|
||||||
|
'''
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
if w is None:
|
if w is None:
|
||||||
return
|
return
|
||||||
@@ -736,6 +786,16 @@ class Boss:
|
|||||||
return None
|
return None
|
||||||
return tab.resize_window_by(window.id, increment, is_horizontal)
|
return tab.resize_window_by(window.id, increment, is_horizontal)
|
||||||
|
|
||||||
|
def resize_os_window(self, os_window_id: int, width: int, height: int, unit: str, incremental: bool = False) -> None:
|
||||||
|
if not incremental and (width < 0 or height < 0):
|
||||||
|
return
|
||||||
|
metrics = get_os_window_size(os_window_id)
|
||||||
|
if metrics is None:
|
||||||
|
return
|
||||||
|
has_window_scaling = is_macos or is_wayland()
|
||||||
|
w, h = get_new_os_window_size(metrics, width, height, unit, incremental, has_window_scaling)
|
||||||
|
set_os_window_size(os_window_id, w, h)
|
||||||
|
|
||||||
def default_bg_changed_for(self, window_id: int) -> None:
|
def default_bg_changed_for(self, window_id: int) -> None:
|
||||||
w = self.window_id_map.get(window_id)
|
w = self.window_id_map.get(window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
@@ -756,7 +816,8 @@ class Boss:
|
|||||||
|
|
||||||
def report_match(f: Callable) -> None:
|
def report_match(f: Callable) -> None:
|
||||||
if self.args.debug_keyboard:
|
if self.args.debug_keyboard:
|
||||||
print(f'\x1b[35m{dispatch_type}\x1b[m matched action:', func_name(f), flush=True)
|
prefix = '\n' if dispatch_type == 'KeyPress' else ''
|
||||||
|
print(f'{prefix}\x1b[35m{dispatch_type}\x1b[m matched action:', func_name(f), flush=True)
|
||||||
|
|
||||||
if key_action is not None:
|
if key_action is not None:
|
||||||
f = getattr(self, key_action.func, None)
|
f = getattr(self, key_action.func, None)
|
||||||
@@ -783,6 +844,17 @@ class Boss:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def combine(self, *actions: KeyAction) -> None:
|
def combine(self, *actions: KeyAction) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Combine multiple actions and map to a single keypress
|
||||||
|
|
||||||
|
The syntax is::
|
||||||
|
|
||||||
|
map key combine <separator> action1 <separator> action2 <separator> action3 ...
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
map kitty_mod+e combine : new_window : next_layout
|
||||||
|
'''
|
||||||
for key_action in actions:
|
for key_action in actions:
|
||||||
self.dispatch_action(key_action)
|
self.dispatch_action(key_action)
|
||||||
|
|
||||||
@@ -818,6 +890,7 @@ class Boss:
|
|||||||
w.paste(text)
|
w.paste(text)
|
||||||
|
|
||||||
def close_os_window(self) -> None:
|
def close_os_window(self) -> None:
|
||||||
|
'@ac:win: Close the currently active OS Window'
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
self.confirm_os_window_close(tm.os_window_id)
|
self.confirm_os_window_close(tm.os_window_id)
|
||||||
@@ -857,6 +930,7 @@ class Boss:
|
|||||||
action()
|
action()
|
||||||
|
|
||||||
def quit(self, *args: Any) -> None:
|
def quit(self, *args: Any) -> None:
|
||||||
|
'@ac:win: Quit, closing all windows'
|
||||||
tm = self.active_tab
|
tm = self.active_tab
|
||||||
num = 0
|
num = 0
|
||||||
for q in self.os_window_map.values():
|
for q in self.os_window_map.values():
|
||||||
@@ -917,6 +991,7 @@ class Boss:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def edit_config_file(self, *a: Any) -> None:
|
def edit_config_file(self, *a: Any) -> None:
|
||||||
|
'@ac:misc: Edit the kitty.conf config file in your favorite text editor'
|
||||||
confpath = prepare_config_file_for_editing()
|
confpath = prepare_config_file_for_editing()
|
||||||
# On macOS vim fails to handle SIGWINCH if it occurs early, so add a
|
# On macOS vim fails to handle SIGWINCH if it occurs early, so add a
|
||||||
# small delay.
|
# small delay.
|
||||||
@@ -1007,6 +1082,7 @@ class Boss:
|
|||||||
return overlay_window
|
return overlay_window
|
||||||
|
|
||||||
def kitten(self, kitten: str, *args: str) -> None:
|
def kitten(self, kitten: str, *args: str) -> None:
|
||||||
|
'@ac:misc: Run the specified kitten. See :doc:`/kittens/custom` for details'
|
||||||
import shlex
|
import shlex
|
||||||
cmdline = args[0] if args else ''
|
cmdline = args[0] if args else ''
|
||||||
kargs = shlex.split(cmdline) if cmdline else []
|
kargs = shlex.split(cmdline) if cmdline else []
|
||||||
@@ -1023,9 +1099,11 @@ class Boss:
|
|||||||
end_kitten(data, target_window_id, self)
|
end_kitten(data, target_window_id, self)
|
||||||
|
|
||||||
def input_unicode_character(self) -> None:
|
def input_unicode_character(self) -> None:
|
||||||
|
'@ac:misc: Input an arbitrary unicode character. See :doc:`/kittens/unicode-input` for details.'
|
||||||
self._run_kitten('unicode_input')
|
self._run_kitten('unicode_input')
|
||||||
|
|
||||||
def set_tab_title(self) -> None:
|
def set_tab_title(self) -> None:
|
||||||
|
'@ac:tab: Change the title of the active tab'
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
if tab:
|
if tab:
|
||||||
args = ['--name=tab-title', '--message', _('Enter the new title for this tab below.'), 'do_set_tab_title', str(tab.id)]
|
args = ['--name=tab-title', '--message', _('Enter the new title for this tab below.'), 'do_set_tab_title', str(tab.id)]
|
||||||
@@ -1044,6 +1122,7 @@ class Boss:
|
|||||||
self._run_kitten('show_error', args=['--title', title], input_data=msg)
|
self._run_kitten('show_error', args=['--title', title], input_data=msg)
|
||||||
|
|
||||||
def create_marker(self) -> None:
|
def create_marker(self) -> None:
|
||||||
|
'@ac:mk: Create a new marker'
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
if w:
|
if w:
|
||||||
spec = None
|
spec = None
|
||||||
@@ -1062,11 +1141,12 @@ class Boss:
|
|||||||
|
|
||||||
self._run_kitten('ask', [
|
self._run_kitten('ask', [
|
||||||
'--name=create-marker', '--message',
|
'--name=create-marker', '--message',
|
||||||
_('Create marker, for example:\ntext 1 ERROR\nSee https://sw.kovidgoyal.net/kitty/marks.html\n')
|
_('Create marker, for example:\ntext 1 ERROR\nSee {}\n').format(website_url('marks'))
|
||||||
],
|
],
|
||||||
custom_callback=done, action_on_removal=done2)
|
custom_callback=done, action_on_removal=done2)
|
||||||
|
|
||||||
def kitty_shell(self, window_type: str) -> None:
|
def kitty_shell(self, window_type: str = 'window') -> None:
|
||||||
|
'@ac:misc: Run the kitty shell to control kitty with commands'
|
||||||
kw: Dict[str, Any] = {}
|
kw: Dict[str, Any] = {}
|
||||||
cmd = [kitty_exe(), '@']
|
cmd = [kitty_exe(), '@']
|
||||||
aw = self.active_window
|
aw = self.active_window
|
||||||
@@ -1114,6 +1194,10 @@ class Boss:
|
|||||||
if not found_action:
|
if not found_action:
|
||||||
open_url(url, program or get_options().open_url_with, cwd=cwd)
|
open_url(url, program or get_options().open_url_with, cwd=cwd)
|
||||||
|
|
||||||
|
def open_url_with_hints(self) -> None:
|
||||||
|
'@ac:misc: Click a URL using the keyboard'
|
||||||
|
self._run_kitten('hints')
|
||||||
|
|
||||||
def drain_actions(self, actions: List) -> None:
|
def drain_actions(self, actions: List) -> None:
|
||||||
|
|
||||||
def callback(timer_id: Optional[int]) -> None:
|
def callback(timer_id: Optional[int]) -> None:
|
||||||
@@ -1140,6 +1224,7 @@ class Boss:
|
|||||||
w.paste(text)
|
w.paste(text)
|
||||||
|
|
||||||
def paste_from_clipboard(self) -> None:
|
def paste_from_clipboard(self) -> None:
|
||||||
|
'@ac:cp: Paste from the clipboard to the active window'
|
||||||
text = get_clipboard_string()
|
text = get_clipboard_string()
|
||||||
self.paste_to_active_window(text)
|
self.paste_to_active_window(text)
|
||||||
|
|
||||||
@@ -1150,6 +1235,7 @@ class Boss:
|
|||||||
return get_primary_selection() if supports_primary_selection else get_clipboard_string()
|
return get_primary_selection() if supports_primary_selection else get_clipboard_string()
|
||||||
|
|
||||||
def paste_from_selection(self) -> None:
|
def paste_from_selection(self) -> None:
|
||||||
|
'@ac:cp: Paste from the clipboard to the active window'
|
||||||
text = self.current_primary_selection_or_clipboard()
|
text = self.current_primary_selection_or_clipboard()
|
||||||
self.paste_to_active_window(text)
|
self.paste_to_active_window(text)
|
||||||
|
|
||||||
@@ -1163,6 +1249,11 @@ class Boss:
|
|||||||
self.copy_to_buffer(get_options().copy_on_select)
|
self.copy_to_buffer(get_options().copy_on_select)
|
||||||
|
|
||||||
def copy_to_buffer(self, buffer_name: str) -> None:
|
def copy_to_buffer(self, buffer_name: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:cp: Copy the selection from the active window to the specified buffer
|
||||||
|
|
||||||
|
See :ref:`cpbuf` for details.
|
||||||
|
'''
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
if w is not None and not w.destroyed:
|
if w is not None and not w.destroyed:
|
||||||
text = w.text_for_selection()
|
text = w.text_for_selection()
|
||||||
@@ -1175,6 +1266,11 @@ class Boss:
|
|||||||
self.clipboard_buffers[buffer_name] = text
|
self.clipboard_buffers[buffer_name] = text
|
||||||
|
|
||||||
def paste_from_buffer(self, buffer_name: str) -> None:
|
def paste_from_buffer(self, buffer_name: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:cp: Paste from the specified buffer to the active window
|
||||||
|
|
||||||
|
See :ref:`cpbuf` for details.
|
||||||
|
'''
|
||||||
if buffer_name == 'clipboard':
|
if buffer_name == 'clipboard':
|
||||||
text: Optional[str] = get_clipboard_string()
|
text: Optional[str] = get_clipboard_string()
|
||||||
elif buffer_name == 'primary':
|
elif buffer_name == 'primary':
|
||||||
@@ -1185,6 +1281,11 @@ class Boss:
|
|||||||
self.paste_to_active_window(text)
|
self.paste_to_active_window(text)
|
||||||
|
|
||||||
def goto_tab(self, tab_num: int) -> None:
|
def goto_tab(self, tab_num: int) -> None:
|
||||||
|
'''
|
||||||
|
@ac:tab: Go to the specified tab, by number, starting with 1
|
||||||
|
|
||||||
|
Zero and negative numbers go to previously active tabs
|
||||||
|
'''
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.goto_tab(tab_num - 1)
|
tm.goto_tab(tab_num - 1)
|
||||||
@@ -1196,11 +1297,13 @@ class Boss:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def next_tab(self) -> None:
|
def next_tab(self) -> None:
|
||||||
|
'@ac:tab: Make the next tab active'
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.next_tab()
|
tm.next_tab()
|
||||||
|
|
||||||
def previous_tab(self) -> None:
|
def previous_tab(self) -> None:
|
||||||
|
'@ac:tab: Make the previous tab active'
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.next_tab(-1)
|
tm.next_tab(-1)
|
||||||
@@ -1360,9 +1463,11 @@ class Boss:
|
|||||||
self._new_tab(args, as_neighbor=as_neighbor, cwd_from=cwd_from)
|
self._new_tab(args, as_neighbor=as_neighbor, cwd_from=cwd_from)
|
||||||
|
|
||||||
def new_tab(self, *args: str) -> None:
|
def new_tab(self, *args: str) -> None:
|
||||||
|
'@ac:tab: Create a new tab'
|
||||||
self._create_tab(list(args))
|
self._create_tab(list(args))
|
||||||
|
|
||||||
def new_tab_with_cwd(self, *args: str) -> None:
|
def new_tab_with_cwd(self, *args: str) -> None:
|
||||||
|
'@ac:tab: Create a new tab with working directory for the window in it set to the same as the active window'
|
||||||
w = self.active_window_for_cwd
|
w = self.active_window_for_cwd
|
||||||
cwd_from = w.child.pid_for_cwd if w is not None else None
|
cwd_from = w.child.pid_for_cwd if w is not None else None
|
||||||
self._create_tab(list(args), cwd_from=cwd_from)
|
self._create_tab(list(args), cwd_from=cwd_from)
|
||||||
@@ -1390,9 +1495,11 @@ class Boss:
|
|||||||
return tab.new_window(cwd_from=cwd_from, location=location, allow_remote_control=allow_remote_control)
|
return tab.new_window(cwd_from=cwd_from, location=location, allow_remote_control=allow_remote_control)
|
||||||
|
|
||||||
def new_window(self, *args: str) -> None:
|
def new_window(self, *args: str) -> None:
|
||||||
|
'@ac:win: Create a new window'
|
||||||
self._new_window(list(args))
|
self._new_window(list(args))
|
||||||
|
|
||||||
def new_window_with_cwd(self, *args: str) -> None:
|
def new_window_with_cwd(self, *args: str) -> None:
|
||||||
|
'@ac:win: Create a new window with working directory same as that of the active window'
|
||||||
w = self.active_window_for_cwd
|
w = self.active_window_for_cwd
|
||||||
if w is None:
|
if w is None:
|
||||||
return self.new_window(*args)
|
return self.new_window(*args)
|
||||||
@@ -1400,21 +1507,33 @@ class Boss:
|
|||||||
self._new_window(list(args), cwd_from=cwd_from)
|
self._new_window(list(args), cwd_from=cwd_from)
|
||||||
|
|
||||||
def launch(self, *args: str) -> None:
|
def launch(self, *args: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Launch the specified program in a new window/tab/etc.
|
||||||
|
|
||||||
|
See :doc:`launch` for details
|
||||||
|
'''
|
||||||
from kitty.launch import launch, parse_launch_args
|
from kitty.launch import launch, parse_launch_args
|
||||||
opts, args_ = parse_launch_args(args)
|
opts, args_ = parse_launch_args(args)
|
||||||
launch(self, opts, args_)
|
launch(self, opts, args_)
|
||||||
|
|
||||||
def move_tab_forward(self) -> None:
|
def move_tab_forward(self) -> None:
|
||||||
|
'@ac:tab: Move the active tab forward'
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.move_tab(1)
|
tm.move_tab(1)
|
||||||
|
|
||||||
def move_tab_backward(self) -> None:
|
def move_tab_backward(self) -> None:
|
||||||
|
'@ac:tab: Move the active tab backward'
|
||||||
tm = self.active_tab_manager
|
tm = self.active_tab_manager
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.move_tab(-1)
|
tm.move_tab(-1)
|
||||||
|
|
||||||
def disable_ligatures_in(self, where: Union[str, Iterable[Window]], strategy: int) -> None:
|
def disable_ligatures_in(self, where: Union[str, Iterable[Window]], strategy: int) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Turn on/off ligatures in the specified window
|
||||||
|
|
||||||
|
See :opt:`disable_ligatures` for details
|
||||||
|
'''
|
||||||
if isinstance(where, str):
|
if isinstance(where, str):
|
||||||
windows: List[Window] = []
|
windows: List[Window] = []
|
||||||
if where == 'active':
|
if where == 'active':
|
||||||
@@ -1472,6 +1591,15 @@ class Boss:
|
|||||||
w.refresh()
|
w.refresh()
|
||||||
|
|
||||||
def load_config_file(self, *paths: str, apply_overrides: bool = True) -> None:
|
def load_config_file(self, *paths: str, apply_overrides: bool = True) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Reload the config file
|
||||||
|
|
||||||
|
If mapped without arguments reloads the default config file, otherwise loads
|
||||||
|
the specified config files, in order. Loading a config file *replaces* all
|
||||||
|
config options. For example::
|
||||||
|
|
||||||
|
map f5 load_config_file /path/to/some/kitty.conf
|
||||||
|
'''
|
||||||
from .config import load_config
|
from .config import load_config
|
||||||
old_opts = get_options()
|
old_opts = get_options()
|
||||||
paths = paths or old_opts.config_paths
|
paths = paths or old_opts.config_paths
|
||||||
@@ -1529,6 +1657,13 @@ class Boss:
|
|||||||
self.show_error(_('Errors in kitty.conf'), msg)
|
self.show_error(_('Errors in kitty.conf'), msg)
|
||||||
|
|
||||||
def set_colors(self, *args: str) -> None:
|
def set_colors(self, *args: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:misc: Change colors in the specified windows
|
||||||
|
|
||||||
|
For details, see :ref:`at_set-colors`. For example::
|
||||||
|
|
||||||
|
map f5 set_colors --configured /path/to/some/config/file/colors.conf
|
||||||
|
'''
|
||||||
from kitty.rc.base import (
|
from kitty.rc.base import (
|
||||||
PayloadGetter, command_for_name, parse_subcommand_cli
|
PayloadGetter, command_for_name, parse_subcommand_cli
|
||||||
)
|
)
|
||||||
@@ -1556,14 +1691,17 @@ class Boss:
|
|||||||
target_tab = tm.new_tab(empty_tab=True)
|
target_tab = tm.new_tab(empty_tab=True)
|
||||||
else:
|
else:
|
||||||
target_os_window_id = target_os_window_id or current_os_window()
|
target_os_window_id = target_os_window_id or current_os_window()
|
||||||
if target_tab_id == 'new':
|
if isinstance(target_tab_id, str):
|
||||||
if not isinstance(target_os_window_id, int):
|
if not isinstance(target_os_window_id, int):
|
||||||
q = self.active_tab_manager
|
q = self.active_tab_manager
|
||||||
assert q is not None
|
assert q is not None
|
||||||
tm = q
|
tm = q
|
||||||
else:
|
else:
|
||||||
tm = self.os_window_map[target_os_window_id]
|
tm = self.os_window_map[target_os_window_id]
|
||||||
target_tab = tm.new_tab(empty_tab=True)
|
if target_tab_id == 'new':
|
||||||
|
target_tab = tm.new_tab(empty_tab=True)
|
||||||
|
else:
|
||||||
|
target_tab = tm.tab_at_location(target_tab_id) or tm.new_tab(empty_tab=True)
|
||||||
else:
|
else:
|
||||||
for tab in self.all_tabs:
|
for tab in self.all_tabs:
|
||||||
if tab.id == target_tab_id:
|
if tab.id == target_tab_id:
|
||||||
@@ -1591,6 +1729,7 @@ class Boss:
|
|||||||
target_tab.make_active()
|
target_tab.make_active()
|
||||||
|
|
||||||
def select_tab(self) -> None:
|
def select_tab(self) -> None:
|
||||||
|
'@ac:tab: Interactively select a tab to switch to'
|
||||||
title = 'Choose a tab to switch to'
|
title = 'Choose a tab to switch to'
|
||||||
lines = [title, '']
|
lines = [title, '']
|
||||||
fmt = ': {1}'
|
fmt = ': {1}'
|
||||||
@@ -1623,10 +1762,16 @@ class Boss:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def detach_window(self, *args: str) -> None:
|
def detach_window(self, *args: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:win: Detach a window, moving it to another tab or OS Window
|
||||||
|
|
||||||
|
See :ref:`detaching windows <detach_window>` for details.
|
||||||
|
'''
|
||||||
if not args or args[0] == 'new':
|
if not args or args[0] == 'new':
|
||||||
return self._move_window_to(target_os_window_id='new')
|
return self._move_window_to(target_os_window_id='new')
|
||||||
if args[0] == 'new-tab':
|
if args[0] in ('new-tab', 'tab-prev', 'tab-left', 'tab-right'):
|
||||||
return self._move_window_to(target_tab_id='new')
|
where = 'new' if args[0] == 'new-tab' else args[0][4:]
|
||||||
|
return self._move_window_to(target_tab_id=where)
|
||||||
title = 'Choose a tab to move the window to'
|
title = 'Choose a tab to move the window to'
|
||||||
lines = [title, '']
|
lines = [title, '']
|
||||||
fmt = ': {1}'
|
fmt = ': {1}'
|
||||||
@@ -1673,6 +1818,11 @@ class Boss:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def detach_tab(self, *args: str) -> None:
|
def detach_tab(self, *args: str) -> None:
|
||||||
|
'''
|
||||||
|
@ac:tab: Detach a tab, moving it to another OS Window
|
||||||
|
|
||||||
|
See :ref:`detaching windows <detach_window>` for details.
|
||||||
|
'''
|
||||||
if not args or args[0] == 'new':
|
if not args or args[0] == 'new':
|
||||||
return self._move_tab_to()
|
return self._move_tab_to()
|
||||||
|
|
||||||
@@ -1745,6 +1895,7 @@ class Boss:
|
|||||||
w.report_notification_activated(identifier)
|
w.report_notification_activated(identifier)
|
||||||
|
|
||||||
def show_kitty_env_vars(self) -> None:
|
def show_kitty_env_vars(self) -> None:
|
||||||
|
'@ac:misc: Show the environment variables that the kitty process sees'
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
if w:
|
if w:
|
||||||
output = '\n'.join(f'{k}={v}' for k, v in os.environ.items())
|
output = '\n'.join(f'{k}={v}' for k, v in os.environ.items())
|
||||||
@@ -1769,6 +1920,7 @@ class Boss:
|
|||||||
tab.remove_window(w)
|
tab.remove_window(w)
|
||||||
|
|
||||||
def debug_config(self) -> None:
|
def debug_config(self) -> None:
|
||||||
|
'@ac:misc: Show the effective configuration kitty is running with'
|
||||||
from .debug_config import debug_config
|
from .debug_config import debug_config
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
if w is not None:
|
if w is not None:
|
||||||
@@ -1778,5 +1930,6 @@ class Boss:
|
|||||||
self.display_scrollback(w, output, title=_('Current kitty options'))
|
self.display_scrollback(w, output, title=_('Current kitty options'))
|
||||||
|
|
||||||
def discard_event(self) -> None:
|
def discard_event(self) -> None:
|
||||||
|
'@ac:misc: Discard this event completely ignoring it'
|
||||||
pass
|
pass
|
||||||
mouse_discard_event = discard_event
|
mouse_discard_event = discard_event
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow
|
|||||||
ans->is_visible = false;
|
ans->is_visible = false;
|
||||||
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return;
|
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return;
|
||||||
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
|
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
|
||||||
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after));
|
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && !cursor->non_blinking && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after));
|
||||||
bool do_draw_cursor = true;
|
bool do_draw_cursor = true;
|
||||||
if (cursor_blinking) {
|
if (cursor_blinking) {
|
||||||
int t = monotonic_t_to_ms(time_since_start_blink);
|
int t = monotonic_t_to_ms(time_since_start_blink);
|
||||||
|
|||||||
41
kitty/cli.py
41
kitty/cli.py
@@ -12,7 +12,7 @@ from typing import (
|
|||||||
|
|
||||||
from .cli_stub import CLIOptions
|
from .cli_stub import CLIOptions
|
||||||
from .conf.utils import resolve_config
|
from .conf.utils import resolve_config
|
||||||
from .constants import appname, defconf, is_macos, str_version
|
from .constants import appname, defconf, is_macos, str_version, website_url
|
||||||
from .options.types import Options as KittyOpts
|
from .options.types import Options as KittyOpts
|
||||||
from .typing import BadLineType, TypedDict
|
from .typing import BadLineType, TypedDict
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ If this option is not specified, config files are searched for in the order:
|
|||||||
:file:`$XDG_CONFIG_DIRS/{appname}/{conf_name}.conf`. The first one that exists is used as the
|
:file:`$XDG_CONFIG_DIRS/{appname}/{conf_name}.conf`. The first one that exists is used as the
|
||||||
config file.
|
config file.
|
||||||
|
|
||||||
If the environment variable :env:`KITTY_CONFIG_DIRECTORY` is specified, that
|
If the environment variable :envvar:`KITTY_CONFIG_DIRECTORY` is specified, that
|
||||||
directory is always used and the above searching does not happen.
|
directory is always used and the above searching does not happen.
|
||||||
|
|
||||||
If :file:`/etc/xdg/{appname}/{conf_name}.conf` exists it is merged before (i.e. with lower
|
If :file:`/etc/xdg/{appname}/{conf_name}.conf` exists it is merged before (i.e. with lower
|
||||||
@@ -57,42 +57,60 @@ def surround(x: str, start: int, end: int) -> str:
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
role_map: Dict[str, Callable[[str], str]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def role(func: Callable[[str], str]) -> Callable[[str], str]:
|
||||||
|
role_map[func.__name__] = func
|
||||||
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def emph(x: str) -> str:
|
def emph(x: str) -> str:
|
||||||
return surround(x, 91, 39)
|
return surround(x, 91, 39)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def cyan(x: str) -> str:
|
def cyan(x: str) -> str:
|
||||||
return surround(x, 96, 39)
|
return surround(x, 96, 39)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def green(x: str) -> str:
|
def green(x: str) -> str:
|
||||||
return surround(x, 32, 39)
|
return surround(x, 32, 39)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def blue(x: str) -> str:
|
def blue(x: str) -> str:
|
||||||
return surround(x, 34, 39)
|
return surround(x, 34, 39)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def yellow(x: str) -> str:
|
def yellow(x: str) -> str:
|
||||||
return surround(x, 93, 39)
|
return surround(x, 93, 39)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def italic(x: str) -> str:
|
def italic(x: str) -> str:
|
||||||
return surround(x, 3, 23)
|
return surround(x, 3, 23)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def bold(x: str) -> str:
|
def bold(x: str) -> str:
|
||||||
return surround(x, 1, 22)
|
return surround(x, 1, 22)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def title(x: str) -> str:
|
def title(x: str) -> str:
|
||||||
return blue(bold(x))
|
return blue(bold(x))
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def opt(text: str) -> str:
|
def opt(text: str) -> str:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def option(x: str) -> str:
|
def option(x: str) -> str:
|
||||||
idx = x.rfind('--')
|
idx = x.rfind('--')
|
||||||
if idx < 0:
|
if idx < 0:
|
||||||
@@ -103,24 +121,32 @@ def option(x: str) -> str:
|
|||||||
return ' '.join(parts)
|
return ' '.join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def code(x: str) -> str:
|
def code(x: str) -> str:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def kbd(x: str) -> str:
|
def kbd(x: str) -> str:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def env(x: str) -> str:
|
def env(x: str) -> str:
|
||||||
return italic(x)
|
return italic(x)
|
||||||
|
|
||||||
|
|
||||||
|
role_map['envvar'] = role_map['env']
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def file(x: str) -> str:
|
def file(x: str) -> str:
|
||||||
return italic(x)
|
return italic(x)
|
||||||
|
|
||||||
|
|
||||||
|
@role
|
||||||
def doc(x: str) -> str:
|
def doc(x: str) -> str:
|
||||||
return f'https://sw.kovidgoyal.net/kitty/{x}.html'
|
return website_url(x)
|
||||||
|
|
||||||
|
|
||||||
OptionSpecSeq = List[Union[str, OptionDict]]
|
OptionSpecSeq = List[Union[str, OptionDict]]
|
||||||
@@ -197,11 +223,13 @@ def parse_option_spec(spec: Optional[str] = None) -> Tuple[OptionSpecSeq, Option
|
|||||||
|
|
||||||
|
|
||||||
def prettify(text: str) -> str:
|
def prettify(text: str) -> str:
|
||||||
role_map = globals()
|
|
||||||
|
def identity(x: str) -> str:
|
||||||
|
return x
|
||||||
|
|
||||||
def sub(m: Match) -> str:
|
def sub(m: Match) -> str:
|
||||||
role, text = m.group(1, 2)
|
role, text = m.group(1, 2)
|
||||||
return str(role_map[role](text))
|
return role_map.get(role, identity)(text)
|
||||||
|
|
||||||
text = re.sub(r':([a-z]+):`([^`]+)`', sub, text)
|
text = re.sub(r':([a-z]+):`([^`]+)`', sub, text)
|
||||||
return text
|
return text
|
||||||
@@ -265,7 +293,8 @@ Run the :italic:`{appname}` terminal emulator. You can also specify the :italic:
|
|||||||
to run inside :italic:`{appname}` as normal arguments following the :italic:`options`.
|
to run inside :italic:`{appname}` as normal arguments following the :italic:`options`.
|
||||||
For example: {appname} sh -c "echo hello, world. Press ENTER to quit; read"
|
For example: {appname} sh -c "echo hello, world. Press ENTER to quit; read"
|
||||||
|
|
||||||
For comprehensive documentation for kitty, please see: https://sw.kovidgoyal.net/kitty/''').format(appname=appname)
|
For comprehensive documentation for kitty, please see: {url}''').format(
|
||||||
|
appname=appname, url=website_url())
|
||||||
|
|
||||||
|
|
||||||
class PrintHelpForSeq:
|
class PrintHelpForSeq:
|
||||||
|
|||||||
@@ -208,10 +208,27 @@ def write_osc(code: int, string: str = '') -> None:
|
|||||||
|
|
||||||
|
|
||||||
set_dynamic_color = set_color_table_color = process_cwd_notification = write_osc
|
set_dynamic_color = set_color_table_color = process_cwd_notification = write_osc
|
||||||
|
clipboard_control_pending: str = ''
|
||||||
|
|
||||||
|
|
||||||
|
def clipboard_control(payload: str) -> None:
|
||||||
|
global clipboard_control_pending
|
||||||
|
code, data = payload.split(';', 1)
|
||||||
|
if code == '-52':
|
||||||
|
if clipboard_control_pending:
|
||||||
|
clipboard_control_pending += data.lstrip(';')
|
||||||
|
else:
|
||||||
|
clipboard_control_pending = payload
|
||||||
|
return
|
||||||
|
if clipboard_control_pending:
|
||||||
|
clipboard_control_pending += data.lstrip(';')
|
||||||
|
payload = clipboard_control_pending
|
||||||
|
clipboard_control_pending = ''
|
||||||
|
write(OSC + payload + '\x07')
|
||||||
|
|
||||||
|
|
||||||
def replay(raw: str) -> None:
|
def replay(raw: str) -> None:
|
||||||
specials = {'draw', 'set_title', 'set_icon', 'set_dynamic_color', 'set_color_table_color', 'process_cwd_notification'}
|
specials = {'draw', 'set_title', 'set_icon', 'set_dynamic_color', 'set_color_table_color', 'process_cwd_notification', 'clipboard_control'}
|
||||||
for line in raw.splitlines():
|
for line in raw.splitlines():
|
||||||
if line.strip() and not line.startswith('#'):
|
if line.strip() and not line.startswith('#'):
|
||||||
cmd, rest = line.partition(' ')[::2]
|
cmd, rest = line.partition(' ')[::2]
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ class MatchGroup:
|
|||||||
|
|
||||||
|
|
||||||
def debug(*a: Any, **kw: Any) -> None:
|
def debug(*a: Any, **kw: Any) -> None:
|
||||||
kw['file'] = sys.stderr
|
from kittens.tui.loop import debug_write
|
||||||
print(*a, **kw)
|
debug_write(*a, **kw)
|
||||||
|
|
||||||
|
|
||||||
class Delegate:
|
class Delegate:
|
||||||
@@ -222,7 +222,6 @@ def zsh_output_serializer(ans: Completions) -> str:
|
|||||||
desc = desc[:truncate_point_for_length(desc, max_desc_len - 2)]
|
desc = desc[:truncate_point_for_length(desc, max_desc_len - 2)]
|
||||||
desc += '…'
|
desc += '…'
|
||||||
|
|
||||||
word = f'\x1b[32m{word}\x1b[39m'
|
|
||||||
if multiline:
|
if multiline:
|
||||||
ans = f'{word}\n {desc}'
|
ans = f'{word}\n {desc}'
|
||||||
else:
|
else:
|
||||||
@@ -264,8 +263,9 @@ def zsh_output_serializer(ans: Completions) -> str:
|
|||||||
lines.append('shift words')
|
lines.append('shift words')
|
||||||
lines.append('(( CURRENT-- ))')
|
lines.append('(( CURRENT-- ))')
|
||||||
lines.append(f'_normal -p "{ans.delegate.precommand}"')
|
lines.append(f'_normal -p "{ans.delegate.precommand}"')
|
||||||
# debug('\n'.join(lines))
|
result = '\n'.join(lines)
|
||||||
return '\n'.join(lines)
|
# debug(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@output_serializer
|
@output_serializer
|
||||||
@@ -478,7 +478,7 @@ def complete_icat_args(ans: Completions, opt: Optional[OptionDict], prefix: str,
|
|||||||
from .guess_mime_type import guess_type
|
from .guess_mime_type import guess_type
|
||||||
|
|
||||||
def icat_file_predicate(filename: str) -> bool:
|
def icat_file_predicate(filename: str) -> bool:
|
||||||
mt = guess_type(filename)
|
mt = guess_type(filename, allow_filesystem_access=True)
|
||||||
if mt and mt.startswith('image/'):
|
if mt and mt.startswith('image/'):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -182,6 +182,8 @@ def generate_class(defn: Definition, loc: str) -> Tuple[str, str]:
|
|||||||
a(' config_overrides: typing.Tuple[str, ...] = ()')
|
a(' config_overrides: typing.Tuple[str, ...] = ()')
|
||||||
a('')
|
a('')
|
||||||
a(' def __init__(self, options_dict: typing.Optional[typing.Dict[str, typing.Any]] = None) -> None:')
|
a(' def __init__(self, options_dict: typing.Optional[typing.Dict[str, typing.Any]] = None) -> None:')
|
||||||
|
if defn.has_color_table:
|
||||||
|
a(' self.color_table = array(self.color_table.typecode, self.color_table)')
|
||||||
a(' if options_dict is not None:')
|
a(' if options_dict is not None:')
|
||||||
a(' for key in option_names:')
|
a(' for key in option_names:')
|
||||||
a(' setattr(self, key, options_dict[key])')
|
a(' setattr(self, key, options_dict[key])')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from typing import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import kitty.conf.utils as generic_parsers
|
import kitty.conf.utils as generic_parsers
|
||||||
|
from kitty.constants import website_url
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
Only = typing.Literal['macos', 'linux', '']
|
Only = typing.Literal['macos', 'linux', '']
|
||||||
@@ -41,14 +42,15 @@ def expand_opt_references(conf_name: str, text: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def remove_markup(text: str) -> str:
|
def remove_markup(text: str) -> str:
|
||||||
|
ref_map = {
|
||||||
|
'layouts': f'{website_url("overview")}#layouts',
|
||||||
|
'sessions': f'{website_url("overview")}#layouts',
|
||||||
|
'functional': f'{website_url("keyboard-protocol")}#functional-key-definitions',
|
||||||
|
}
|
||||||
|
|
||||||
def sub(m: Match) -> str:
|
def sub(m: Match) -> str:
|
||||||
if m.group(1) == 'ref':
|
if m.group(1) == 'ref':
|
||||||
return {
|
return ref_map[m.group(2)]
|
||||||
'layouts': 'https://sw.kovidgoyal.net/kitty/index.html#layouts',
|
|
||||||
'sessions': 'https://sw.kovidgoyal.net/kitty/index.html#sessions',
|
|
||||||
'functional': 'https://sw.kovidgoyal.net/kitty/keyboard-protocol.html#functional-key-definitions',
|
|
||||||
}[m.group(2)]
|
|
||||||
return str(m.group(2))
|
return str(m.group(2))
|
||||||
|
|
||||||
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
||||||
@@ -428,7 +430,7 @@ class Group:
|
|||||||
a(f'.. _conf-{conf_name}-{self.name}:')
|
a(f'.. _conf-{conf_name}-{self.name}:')
|
||||||
a('')
|
a('')
|
||||||
a(self.title)
|
a(self.title)
|
||||||
heading_level = '+' if level > 1 else '^'
|
heading_level = '+' if level > 1 else '-'
|
||||||
a(heading_level * (len(self.title) + 20))
|
a(heading_level * (len(self.title) + 20))
|
||||||
a('')
|
a('')
|
||||||
if self.start_text:
|
if self.start_text:
|
||||||
@@ -463,7 +465,7 @@ class Group:
|
|||||||
a(render_block(self.start_text))
|
a(render_block(self.start_text))
|
||||||
a('')
|
a('')
|
||||||
else:
|
else:
|
||||||
ans.extend(('# vim:fileencoding=utf-8:ft=conf:foldmethod=marker', ''))
|
ans.extend(('# vim:fileencoding=utf-8:foldmethod=marker', ''))
|
||||||
|
|
||||||
for item in self.iter_with_coalesced_options():
|
for item in self.iter_with_coalesced_options():
|
||||||
if isinstance(item, Option):
|
if isinstance(item, Option):
|
||||||
@@ -566,9 +568,9 @@ class Definition:
|
|||||||
|
|
||||||
def iter_all_maps(self, which: str = 'map') -> Iterator[Union[ShortcutMapping, MouseMapping]]:
|
def iter_all_maps(self, which: str = 'map') -> Iterator[Union[ShortcutMapping, MouseMapping]]:
|
||||||
for x in self.iter_all_non_groups():
|
for x in self.iter_all_non_groups():
|
||||||
if isinstance(x, ShortcutMapping) and which == 'map':
|
if isinstance(x, ShortcutMapping) and which in ('map', '*'):
|
||||||
yield x
|
yield x
|
||||||
elif isinstance(x, MouseMapping) and which == 'mouse_map':
|
elif isinstance(x, MouseMapping) and which in ('mouse_map', '*'):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
def parser_func(self, name: str) -> Callable:
|
def parser_func(self, name: str) -> Callable:
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ def to_cmdline(x: str) -> List[str]:
|
|||||||
|
|
||||||
|
|
||||||
def python_string(text: str) -> str:
|
def python_string(text: str) -> str:
|
||||||
import ast
|
from ast import literal_eval
|
||||||
ans: str = ast.literal_eval("'''" + text.replace("'''", "'\\''") + "'''")
|
ans: str = literal_eval("'''" + text.replace("'''", "'\\''") + "'''")
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
@@ -310,7 +310,8 @@ def save_type_stub(text: str, fpath: str) -> None:
|
|||||||
fpath += 'i'
|
fpath += 'i'
|
||||||
preamble = '# Update this file by running: ./test.py mypy\n\n'
|
preamble = '# Update this file by running: ./test.py mypy\n\n'
|
||||||
try:
|
try:
|
||||||
existing = open(fpath).read()
|
with open(fpath) as fs:
|
||||||
|
existing = fs.read()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
existing = ''
|
existing = ''
|
||||||
current = preamble + text
|
current = preamble + text
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Version(NamedTuple):
|
|||||||
|
|
||||||
appname: str = 'kitty'
|
appname: str = 'kitty'
|
||||||
kitty_face = '🐱'
|
kitty_face = '🐱'
|
||||||
version: Version = Version(0, 21, 2)
|
version: Version = Version(0, 22, 2)
|
||||||
str_version: str = '.'.join(map(str, version))
|
str_version: str = '.'.join(map(str, version))
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos: bool = 'darwin' in _plat
|
is_macos: bool = 'darwin' in _plat
|
||||||
@@ -186,3 +186,11 @@ def read_kitty_resource(name: str) -> bytes:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from importlib_resources import read_binary # type: ignore
|
from importlib_resources import read_binary # type: ignore
|
||||||
return read_binary('kitty', name)
|
return read_binary('kitty', name)
|
||||||
|
|
||||||
|
|
||||||
|
def website_url(doc_name: str = '') -> str:
|
||||||
|
if doc_name:
|
||||||
|
doc_name = doc_name.rstrip('/')
|
||||||
|
if doc_name:
|
||||||
|
doc_name += '/'
|
||||||
|
return f'https://sw.kovidgoyal.net/kitty/{doc_name}'
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ dealloc(Cursor* self) {
|
|||||||
|
|
||||||
#define EQ(x) (a->x == b->x)
|
#define EQ(x) (a->x == b->x)
|
||||||
static int __eq__(Cursor *a, Cursor *b) {
|
static int __eq__(Cursor *a, Cursor *b) {
|
||||||
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(dim) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink);
|
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(dim) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(non_blinking);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" };
|
static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" };
|
||||||
@@ -35,7 +35,7 @@ repr(Cursor *self) {
|
|||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, dim=%R, decoration=%d, decoration_fg=#%08x)",
|
"Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, dim=%R, decoration=%d, decoration_fg=#%08x)",
|
||||||
self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES ? cursor_names[self->shape] : "INVALID"),
|
self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES ? cursor_names[self->shape] : "INVALID"),
|
||||||
BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), BOOL(self->dim), self->decoration, self->decoration_fg
|
BOOL(!self->non_blinking), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), BOOL(self->dim), self->decoration, self->decoration_fg
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,12 +232,12 @@ reset_display_attrs(Cursor *self, PyObject *a UNUSED) {
|
|||||||
void cursor_reset(Cursor *self) {
|
void cursor_reset(Cursor *self) {
|
||||||
cursor_reset_display_attrs(self);
|
cursor_reset_display_attrs(self);
|
||||||
self->x = 0; self->y = 0;
|
self->x = 0; self->y = 0;
|
||||||
self->shape = NO_CURSOR_SHAPE; self->blink = false;
|
self->shape = NO_CURSOR_SHAPE; self->non_blinking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
||||||
#define CCY(x) dest->x = src->x;
|
#define CCY(x) dest->x = src->x;
|
||||||
CCY(x); CCY(y); CCY(shape); CCY(blink);
|
CCY(x); CCY(y); CCY(shape); CCY(non_blinking);
|
||||||
CCY(bold); CCY(italic); CCY(strikethrough); CCY(dim); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
CCY(bold); CCY(italic); CCY(strikethrough); CCY(dim); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +252,11 @@ BOOL_GETSET(Cursor, italic)
|
|||||||
BOOL_GETSET(Cursor, reverse)
|
BOOL_GETSET(Cursor, reverse)
|
||||||
BOOL_GETSET(Cursor, strikethrough)
|
BOOL_GETSET(Cursor, strikethrough)
|
||||||
BOOL_GETSET(Cursor, dim)
|
BOOL_GETSET(Cursor, dim)
|
||||||
BOOL_GETSET(Cursor, blink)
|
|
||||||
|
static PyObject* blink_get(Cursor *self, void UNUSED *closure) { PyObject *ans = !self->non_blinking ? Py_True : Py_False; Py_INCREF(ans); return ans; }
|
||||||
|
|
||||||
|
static int blink_set(Cursor *self, PyObject *value, void UNUSED *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); return -1; } self->non_blinking = PyObject_IsTrue(value) ? false : true; return 0; }
|
||||||
|
|
||||||
|
|
||||||
static PyMemberDef members[] = {
|
static PyMemberDef members[] = {
|
||||||
{"x", T_UINT, offsetof(Cursor, x), 0, "x"},
|
{"x", T_UINT, offsetof(Cursor, x), 0, "x"},
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
bool bold, italic, reverse, strikethrough, blink, dim;
|
bool bold, italic, reverse, strikethrough, dim, non_blinking;
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
uint8_t decoration;
|
uint8_t decoration;
|
||||||
CursorShape shape;
|
CursorShape shape;
|
||||||
|
|||||||
@@ -4,20 +4,31 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Callable, Dict, Generator, Iterable, Set, Tuple
|
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
from typing import Callable, Dict, Generator, Iterable, Set, Tuple
|
||||||
|
|
||||||
from .cli import green, title, version
|
from kittens.tui.operations import colored, styled
|
||||||
|
|
||||||
|
from .cli import version
|
||||||
from .conf.utils import KeyAction
|
from .conf.utils import KeyAction
|
||||||
from .constants import is_macos, is_wayland
|
from .constants import is_macos, is_wayland
|
||||||
from .options.types import Options as KittyOpts, defaults
|
from .options.types import Options as KittyOpts, defaults
|
||||||
from .options.utils import MouseMap
|
from .options.utils import MouseMap
|
||||||
|
from .rgb import Color, color_as_sharp
|
||||||
from .types import MouseEvent, SingleKey
|
from .types import MouseEvent, SingleKey
|
||||||
from .typing import SequenceMap
|
from .typing import SequenceMap
|
||||||
|
|
||||||
ShortcutMap = Dict[Tuple[SingleKey, ...], KeyAction]
|
ShortcutMap = Dict[Tuple[SingleKey, ...], KeyAction]
|
||||||
|
|
||||||
|
|
||||||
|
def green(x: str) -> str:
|
||||||
|
return colored(x, 'green')
|
||||||
|
|
||||||
|
|
||||||
|
def title(x: str) -> str:
|
||||||
|
return colored(x, 'blue', intense=True)
|
||||||
|
|
||||||
|
|
||||||
def mod_to_names(mods: int) -> Generator[str, None, None]:
|
def mod_to_names(mods: int) -> Generator[str, None, None]:
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
GLFW_MOD_ALT, GLFW_MOD_CAPS_LOCK, GLFW_MOD_CONTROL, GLFW_MOD_HYPER,
|
GLFW_MOD_ALT, GLFW_MOD_CAPS_LOCK, GLFW_MOD_CONTROL, GLFW_MOD_HYPER,
|
||||||
@@ -104,6 +115,7 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
|||||||
]
|
]
|
||||||
field_len = max(map(len, changed_opts)) if changed_opts else 20
|
field_len = max(map(len, changed_opts)) if changed_opts else 20
|
||||||
fmt = '{{:{:d}s}}'.format(field_len)
|
fmt = '{{:{:d}s}}'.format(field_len)
|
||||||
|
colors = []
|
||||||
for f in changed_opts:
|
for f in changed_opts:
|
||||||
val = getattr(opts, f)
|
val = getattr(opts, f)
|
||||||
if isinstance(val, dict):
|
if isinstance(val, dict):
|
||||||
@@ -114,7 +126,11 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
|||||||
else:
|
else:
|
||||||
print(pformat(val))
|
print(pformat(val))
|
||||||
else:
|
else:
|
||||||
print(title(fmt.format(f)), str(getattr(opts, f)))
|
val = getattr(opts, f)
|
||||||
|
if isinstance(val, Color):
|
||||||
|
colors.append(fmt.format(f) + ' ' + color_as_sharp(val) + ' ' + styled(' ', bg=val))
|
||||||
|
else:
|
||||||
|
print(fmt.format(f), str(getattr(opts, f)))
|
||||||
|
|
||||||
compare_mousemaps(opts.mousemap, default_opts.mousemap, print)
|
compare_mousemaps(opts.mousemap, default_opts.mousemap, print)
|
||||||
final_, initial_ = opts.keymap, default_opts.keymap
|
final_, initial_ = opts.keymap, default_opts.keymap
|
||||||
@@ -124,6 +140,9 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
|
|||||||
final.update(final_s)
|
final.update(final_s)
|
||||||
initial.update(initial_s)
|
initial.update(initial_s)
|
||||||
compare_keymaps(final, initial, print)
|
compare_keymaps(final, initial, print)
|
||||||
|
if colors:
|
||||||
|
print(f'{title("Colors")}:', end='\n\t')
|
||||||
|
print('\n\t'.join(sorted(colors)))
|
||||||
|
|
||||||
|
|
||||||
def debug_config(opts: KittyOpts) -> str:
|
def debug_config(opts: KittyOpts) -> str:
|
||||||
|
|||||||
2
kitty/emoji.h
generated
2
kitty/emoji.h
generated
@@ -1,4 +1,4 @@
|
|||||||
// unicode data, built from the unicode standard on: 2021-04-02
|
// unicode data, built from the unicode standard on: 2021-07-19
|
||||||
// see gen-wcwidth.py
|
// see gen-wcwidth.py
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ MOUSE_SELECTION_NORMAL: int
|
|||||||
MOUSE_SELECTION_WORD: int
|
MOUSE_SELECTION_WORD: int
|
||||||
MOUSE_SELECTION_RECTANGLE: int
|
MOUSE_SELECTION_RECTANGLE: int
|
||||||
MOUSE_SELECTION_LINE_FROM_POINT: int
|
MOUSE_SELECTION_LINE_FROM_POINT: int
|
||||||
|
MOUSE_SELECTION_MOVE_END: int
|
||||||
KITTY_VCS_REV: str
|
KITTY_VCS_REV: str
|
||||||
NO_CLOSE_REQUESTED: int
|
NO_CLOSE_REQUESTED: int
|
||||||
IMPERATIVE_CLOSE_REQUESTED: int
|
IMPERATIVE_CLOSE_REQUESTED: int
|
||||||
@@ -569,11 +570,11 @@ def free_font_data() -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def toggle_maximized() -> bool:
|
def toggle_maximized(os_window_id: int = 0) -> bool:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def toggle_fullscreen() -> bool:
|
def toggle_fullscreen(os_window_id: int = 0) -> bool:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -1186,3 +1187,24 @@ def mouse_selection(os_window_id: int, tab_id: int, window_id: int, code: int, b
|
|||||||
|
|
||||||
def apply_options_update() -> None:
|
def apply_options_update() -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def set_os_window_size(os_window_id: int, x: int, y: int) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OSWindowSize(TypedDict):
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
framebuffer_width: int
|
||||||
|
framebuffer_height: int
|
||||||
|
xscale: float
|
||||||
|
yscale: float
|
||||||
|
xdpi: float
|
||||||
|
ydpi: float
|
||||||
|
cell_width: int
|
||||||
|
cell_height: int
|
||||||
|
|
||||||
|
|
||||||
|
def get_os_window_size(os_window_id: int) -> Optional[OSWindowSize]:
|
||||||
|
pass
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user