mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-17 05:57:50 +02:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04807453ec | ||
|
|
1b7582e85c | ||
|
|
e106562ef1 | ||
|
|
d3a20f00d6 | ||
|
|
de5443a4db | ||
|
|
e8b19e08fa | ||
|
|
a574081012 | ||
|
|
4f06ce9d72 | ||
|
|
6713580455 | ||
|
|
86f6c946b3 | ||
|
|
9194d1db6b | ||
|
|
420a1b018a | ||
|
|
8009b85073 | ||
|
|
2a58af2be9 | ||
|
|
4decac26f6 | ||
|
|
a6b74f190f | ||
|
|
bfbe60c90e | ||
|
|
384b2f8462 | ||
|
|
d875615c03 | ||
|
|
9aefcfe56f | ||
|
|
266e70222f | ||
|
|
d4639e2aea | ||
|
|
ca8975891b | ||
|
|
bed3d2eb50 | ||
|
|
78495a7f64 | ||
|
|
f66914f7bb | ||
|
|
58e1f6ee1f | ||
|
|
0625035202 | ||
|
|
f8fc272f58 | ||
|
|
6d61de8a8f | ||
|
|
4c08709df1 | ||
|
|
58a28da94d | ||
|
|
26b976d17d | ||
|
|
3141fc3f05 | ||
|
|
a45d6c8b55 | ||
|
|
dadf496a68 | ||
|
|
dae8ae33f0 |
20
__main__.py
20
__main__.py
@@ -31,14 +31,26 @@ def runpy(args: List[str]) -> None:
|
||||
|
||||
def hold(args: List[str]) -> None:
|
||||
import subprocess
|
||||
import tty
|
||||
import termios
|
||||
from contextlib import suppress
|
||||
from kittens.tui.operations import init_state, set_cursor_visible
|
||||
ret = subprocess.Popen(args[1:]).wait()
|
||||
with suppress(BaseException):
|
||||
print('\n\x1b[1;32mPress any key to exit', end='', flush=True)
|
||||
print(
|
||||
'\n\x1b[1;32mPress Enter to exit',
|
||||
end=init_state(alternate_screen=False, kitty_keyboard_mode=False) + set_cursor_visible(False),
|
||||
flush=True)
|
||||
with suppress(BaseException):
|
||||
tty.setraw(sys.stdin.fileno())
|
||||
sys.stdin.buffer.read(1)
|
||||
fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fd)
|
||||
new = old[:]
|
||||
new[3] &= ~termios.ECHO # 3 == 'lflags'
|
||||
tcsetattr_flags = termios.TCSAFLUSH
|
||||
if hasattr(termios, 'TCSASOFT'):
|
||||
tcsetattr_flags |= getattr(termios, 'TCSASOFT')
|
||||
termios.tcsetattr(fd, tcsetattr_flags, new)
|
||||
with suppress(KeyboardInterrupt):
|
||||
input()
|
||||
raise SystemExit(ret)
|
||||
|
||||
|
||||
|
||||
6
docs/_static/custom.css
vendored
6
docs/_static/custom.css
vendored
@@ -28,3 +28,9 @@ details > summary {
|
||||
text-decoration-color: var(--color-link-underline);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
/* pygments adds an underline to some white-space, this is particularly visible in
|
||||
* dark mode. Remove it. */
|
||||
.highlight .w {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
@@ -73,6 +73,23 @@ command.
|
||||
Detailed list of changes
|
||||
-------------------------------------
|
||||
|
||||
0.24.1 [2022-01-06]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Shell integration: Work around conflicts with some zsh plugins (:iss:`4428`)
|
||||
|
||||
- Have the zero width space and various other characters from the *Other,
|
||||
formatting* Unicode category be treated as combining characters (:iss:`4439`)
|
||||
|
||||
- Fix using ``--shell-integration`` with :file:`setup.py` broken (:iss:`4434`)
|
||||
|
||||
- Fix showing debug information not working if kitty's :file:`STDIN` is not a tty
|
||||
(:iss:`4424`)
|
||||
|
||||
- Linux: Fix a regression that broke rendering of emoji with variation selectors
|
||||
(:iss:`4444`)
|
||||
|
||||
|
||||
0.24.0 [2022-01-04]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -129,11 +129,6 @@ different shells.
|
||||
and sources the original :file:`.zshenv`. It then loads the shell integration code.
|
||||
The remainder of zsh's startup process proceeds as normal.
|
||||
|
||||
.. tab:: bash
|
||||
|
||||
For bash, kitty adds a couple of lines to the bottom of :file:`~/.bashrc`
|
||||
(in an atomic manner) to load the shell integration code.
|
||||
|
||||
.. tab:: fish
|
||||
|
||||
For fish, to make it automatically load the integration code provided by
|
||||
@@ -142,6 +137,12 @@ different shells.
|
||||
process and will be cleaned up by the integration script after startup. No files
|
||||
are added or modified.
|
||||
|
||||
.. tab:: bash
|
||||
|
||||
For bash, kitty adds a couple of lines to the bottom of :file:`~/.bashrc`
|
||||
(in an atomic manner) to load the shell integration code.
|
||||
|
||||
|
||||
Then, when launching the shell, kitty sets the environment variable
|
||||
:envvar:`KITTY_SHELL_INTEGRATION` to the value of the :opt:`shell_integration`
|
||||
option. The shell integration code reads the environment variable, turns on the
|
||||
@@ -197,15 +198,6 @@ First, in :file:`kitty.conf` set:
|
||||
|
||||
Then in your shell's rc file, add the lines:
|
||||
|
||||
.. tab:: bash
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
if test -n "$KITTY_INSTALLATION_DIR"; then
|
||||
export KITTY_SHELL_INTEGRATION="enabled"
|
||||
source "$KITTY_INSTALLATION_DIR/shell-integration/bash/kitty.bash"
|
||||
fi
|
||||
|
||||
.. tab:: zsh
|
||||
|
||||
.. code-block:: sh
|
||||
@@ -228,6 +220,15 @@ Then in your shell's rc file, add the lines:
|
||||
end
|
||||
|
||||
|
||||
.. tab:: bash
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
if test -n "$KITTY_INSTALLATION_DIR"; then
|
||||
export KITTY_SHELL_INTEGRATION="enabled"
|
||||
source "$KITTY_INSTALLATION_DIR/shell-integration/bash/kitty.bash"
|
||||
fi
|
||||
|
||||
The value of :envvar:`KITTY_SHELL_INTEGRATION` is the same as that for
|
||||
:opt:`shell_integration`, except if you want to disable shell integration
|
||||
completely, in which case simply do not set the
|
||||
|
||||
@@ -49,11 +49,10 @@ class_maps: Dict[str, Set[int]] = {}
|
||||
all_symbols: Set[int] = set()
|
||||
name_map: Dict[int, str] = {}
|
||||
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
||||
zwj = 0x200d
|
||||
soft_hyphen = 0xad
|
||||
flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
|
||||
# See https://github.com/harfbuzz/harfbuzz/issues/169
|
||||
marks = set(emoji_skin_tone_modifiers) | {zwj} | flag_codepoints
|
||||
marks = set(emoji_skin_tone_modifiers) | flag_codepoints
|
||||
not_assigned = set(range(0, sys.maxunicode))
|
||||
property_maps: Dict[str, Set[int]] = defaultdict(set)
|
||||
|
||||
@@ -69,7 +68,6 @@ def parse_prop_list() -> None:
|
||||
property_maps[name] |= chars
|
||||
# see https://www.unicode.org/faq/unsup_char.html#3
|
||||
marks |= property_maps['Other_Default_Ignorable_Code_Point']
|
||||
marks.add(soft_hyphen)
|
||||
|
||||
|
||||
def parse_ucd() -> None:
|
||||
@@ -113,6 +111,12 @@ def parse_ucd() -> None:
|
||||
marks.add(codepoint)
|
||||
elif category.startswith('S'):
|
||||
all_symbols.add(codepoint)
|
||||
elif category == 'Cf':
|
||||
# we add Cf to marks as it contains things like tags and zero
|
||||
# width chars. Not sure if *all* of Cf should be treated as
|
||||
# combining chars, might need to add individual exceptions in
|
||||
# the future.
|
||||
marks.add(codepoint)
|
||||
|
||||
with open('nerd-fonts-glyphs.txt') as f:
|
||||
for line in f:
|
||||
@@ -382,9 +386,9 @@ def gen_ucd() -> None:
|
||||
ascii_range='false'
|
||||
)
|
||||
category_test(
|
||||
'is_non_rendered_char', p, 'Cc Cs'.split(),
|
||||
'is_non_rendered_char', p, 'Cc Cs Cf'.split(),
|
||||
'Other_Default_Ignorable_Code_Point and soft hyphen',
|
||||
extra_chars=property_maps['Other_Default_Ignorable_Code_Point'] | {soft_hyphen},
|
||||
extra_chars=property_maps['Other_Default_Ignorable_Code_Point'] | set(range(0xfe00, 0xfe0f + 1)),
|
||||
ascii_range='false'
|
||||
)
|
||||
category_test('is_word_char', p, {c for c in class_maps if c[0] in 'LN'}, 'L and N categories')
|
||||
|
||||
@@ -271,9 +271,13 @@ def brackets(text: str, s: int, e: int) -> Tuple[int, int]:
|
||||
# Remove matching brackets
|
||||
if s < e <= len(text):
|
||||
before = text[s]
|
||||
if before in '({[<' and text[e-1] == closing_bracket_map[before]:
|
||||
s += 1
|
||||
e -= 1
|
||||
if before in '({[<':
|
||||
q = closing_bracket_map[before]
|
||||
if text[e-1] == q:
|
||||
s += 1
|
||||
e -= 1
|
||||
elif text[e:e+1] == q:
|
||||
s += 1
|
||||
return s, e
|
||||
|
||||
|
||||
@@ -282,9 +286,12 @@ def quotes(text: str, s: int, e: int) -> Tuple[int, int]:
|
||||
# Remove matching quotes
|
||||
if s < e <= len(text):
|
||||
before = text[s]
|
||||
if before in '\'"' and text[e-1] == before:
|
||||
s += 1
|
||||
e -= 1
|
||||
if before in '\'"':
|
||||
if text[e-1] == before:
|
||||
s += 1
|
||||
e -= 1
|
||||
elif text[e:e+1] == before:
|
||||
s += 1
|
||||
return s, e
|
||||
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@ class MouseTracking(Enum):
|
||||
full = auto()
|
||||
|
||||
|
||||
def init_state(alternate_screen: bool = True, mouse_tracking: MouseTracking = MouseTracking.none) -> str:
|
||||
def init_state(alternate_screen: bool = True, mouse_tracking: MouseTracking = MouseTracking.none, kitty_keyboard_mode: bool = True) -> str:
|
||||
sc = SAVE_CURSOR if alternate_screen else ''
|
||||
ans = (
|
||||
S7C1T + sc + SAVE_PRIVATE_MODE_VALUES + reset_mode(Mode.LNM) +
|
||||
@@ -314,7 +314,10 @@ def init_state(alternate_screen: bool = True, mouse_tracking: MouseTracking = Mo
|
||||
ans += set_mode(Mode.MOUSE_MOTION_TRACKING)
|
||||
elif mouse_tracking is MouseTracking.full:
|
||||
ans += set_mode(Mode.MOUSE_MOVE_TRACKING)
|
||||
ans += '\033[>31u' # extended keyboard mode
|
||||
if kitty_keyboard_mode:
|
||||
ans += '\033[>31u' # extended keyboard mode
|
||||
else:
|
||||
ans += '\033[>u' # legacy keyboard mode
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
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-10-07
|
||||
// unicode data, built from the unicode standard on: 2022-01-05
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
|
||||
@@ -22,7 +22,7 @@ class Version(NamedTuple):
|
||||
|
||||
appname: str = 'kitty'
|
||||
kitty_face = '🐱'
|
||||
version: Version = Version(0, 24, 0)
|
||||
version: Version = Version(0, 24, 1)
|
||||
str_version: str = '.'.join(map(str, version))
|
||||
_plat = sys.platform.lower()
|
||||
is_macos: bool = 'darwin' in _plat
|
||||
|
||||
@@ -7,11 +7,10 @@ import socket
|
||||
import sys
|
||||
import termios
|
||||
import time
|
||||
from contextlib import suppress
|
||||
from functools import partial
|
||||
from pprint import pformat
|
||||
from typing import (
|
||||
IO, Callable, Dict, Generator, Iterable, Iterator, Optional, Set, Tuple
|
||||
)
|
||||
from typing import IO, Callable, Dict, Iterable, Iterator, Optional, Set, Tuple
|
||||
|
||||
from kittens.tui.operations import colored, styled
|
||||
|
||||
@@ -19,7 +18,7 @@ from .cli import version
|
||||
from .constants import (
|
||||
extensions_dir, is_macos, is_wayland, kitty_base_dir, kitty_exe, shell_path
|
||||
)
|
||||
from .fast_data_types import num_users, Color
|
||||
from .fast_data_types import Color, num_users
|
||||
from .options.types import Options as KittyOpts, defaults
|
||||
from .options.utils import MouseMap
|
||||
from .rgb import color_as_sharp
|
||||
@@ -41,7 +40,7 @@ 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) -> Iterator[str]:
|
||||
from .fast_data_types import (
|
||||
GLFW_MOD_ALT, GLFW_MOD_CAPS_LOCK, GLFW_MOD_CONTROL, GLFW_MOD_HYPER,
|
||||
GLFW_MOD_META, GLFW_MOD_NUM_LOCK, GLFW_MOD_SHIFT, GLFW_MOD_SUPER
|
||||
@@ -162,16 +161,22 @@ class IssueData:
|
||||
def __init__(self) -> None:
|
||||
self.uname = os.uname()
|
||||
self.s, self.n, self.r, self.v, self.m = self.uname
|
||||
self.hostname = self.o = socket.gethostname()
|
||||
try:
|
||||
self.hostname = self.o = socket.gethostname()
|
||||
except Exception:
|
||||
self.hostname = self.o = 'localhost'
|
||||
_time = time.localtime()
|
||||
self.formatted_time = self.d = time.strftime('%a %b %d %Y', _time)
|
||||
self.formatted_date = self.t = time.strftime('%H:%M:%S', _time)
|
||||
try:
|
||||
self.tty_name = format_tty_name(os.ttyname(sys.stdin.fileno()))
|
||||
self.tty_name = format_tty_name(os.ctermid())
|
||||
except OSError:
|
||||
self.tty_name = '(none)'
|
||||
self.l = self.tty_name # noqa
|
||||
self.baud_rate = termios.tcgetattr(sys.stdin.fileno())[5]
|
||||
self.baud_rate = 0
|
||||
if sys.stdin.isatty():
|
||||
with suppress(OSError):
|
||||
self.baud_rate = termios.tcgetattr(sys.stdin.fileno())[5]
|
||||
self.b = str(self.baud_rate)
|
||||
try:
|
||||
self.num_users = num_users()
|
||||
@@ -218,8 +223,18 @@ def debug_config(opts: KittyOpts) -> str:
|
||||
import subprocess
|
||||
p(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip())
|
||||
if os.path.exists('/etc/issue'):
|
||||
with open('/etc/issue', encoding='utf-8', errors='replace') as f:
|
||||
p(end=''.join(IssueData().parse_issue_file(f)))
|
||||
try:
|
||||
idata = IssueData()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
with open('/etc/issue', encoding='utf-8', errors='replace') as f:
|
||||
try:
|
||||
datums = idata.parse_issue_file(f)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
p(end=''.join(datums))
|
||||
if os.path.exists('/etc/lsb-release'):
|
||||
with open('/etc/lsb-release', encoding='utf-8', errors='replace') as f:
|
||||
p(f.read().strip())
|
||||
|
||||
26
kitty/emoji.h
generated
26
kitty/emoji.h
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2021-10-07
|
||||
// unicode data, built from the unicode standard on: 2022-01-05
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
@@ -276,7 +276,7 @@ is_emoji(char_type code) {
|
||||
return true;
|
||||
case 0x1f6d5 ... 0x1f6d7:
|
||||
return true;
|
||||
case 0x1f6e0 ... 0x1f6e5:
|
||||
case 0x1f6dd ... 0x1f6e5:
|
||||
return true;
|
||||
case 0x1f6e9:
|
||||
return true;
|
||||
@@ -288,29 +288,31 @@ is_emoji(char_type code) {
|
||||
return true;
|
||||
case 0x1f7e0 ... 0x1f7eb:
|
||||
return true;
|
||||
case 0x1f7f0:
|
||||
return true;
|
||||
case 0x1f90c ... 0x1f93a:
|
||||
return true;
|
||||
case 0x1f93c ... 0x1f945:
|
||||
return true;
|
||||
case 0x1f947 ... 0x1f978:
|
||||
return true;
|
||||
case 0x1f97a ... 0x1f9cb:
|
||||
return true;
|
||||
case 0x1f9cd ... 0x1f9ff:
|
||||
case 0x1f947 ... 0x1f9ff:
|
||||
return true;
|
||||
case 0x1fa70 ... 0x1fa74:
|
||||
return true;
|
||||
case 0x1fa78 ... 0x1fa7a:
|
||||
case 0x1fa78 ... 0x1fa7c:
|
||||
return true;
|
||||
case 0x1fa80 ... 0x1fa86:
|
||||
return true;
|
||||
case 0x1fa90 ... 0x1faa8:
|
||||
case 0x1fa90 ... 0x1faac:
|
||||
return true;
|
||||
case 0x1fab0 ... 0x1fab6:
|
||||
case 0x1fab0 ... 0x1faba:
|
||||
return true;
|
||||
case 0x1fac0 ... 0x1fac2:
|
||||
case 0x1fac0 ... 0x1fac5:
|
||||
return true;
|
||||
case 0x1fad0 ... 0x1fad6:
|
||||
case 0x1fad0 ... 0x1fad9:
|
||||
return true;
|
||||
case 0x1fae0 ... 0x1fae7:
|
||||
return true;
|
||||
case 0x1faf0 ... 0x1faf6:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,8 @@ has_cell_text(Font *self, CPUCell *cell) {
|
||||
char_type combining_chars[arraysz(cell->cc_idx)];
|
||||
unsigned num_cc = 0;
|
||||
for (unsigned i = 0; i < arraysz(cell->cc_idx) && cell->cc_idx[i]; i++) {
|
||||
if (!is_non_rendered_char(cell->cc_idx[i])) combining_chars[num_cc++] = codepoint_for_mark(cell->cc_idx[i]);
|
||||
const char_type ccp = codepoint_for_mark(cell->cc_idx[i]);
|
||||
if (!is_non_rendered_char(ccp)) combining_chars[num_cc++] = ccp;
|
||||
}
|
||||
if (num_cc == 0) return true;
|
||||
if (num_cc == 1) {
|
||||
|
||||
@@ -795,6 +795,17 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags, int modifiers) {
|
||||
if (t) w = t->windows + t->active_window;
|
||||
}
|
||||
if (!w) return;
|
||||
// Also update mouse cursor position while kitty OS window is not focused.
|
||||
// Allows scroll events to be delivered to the child with correct pointer co-ordinates even when
|
||||
// the window is not focused on macOS
|
||||
if (!osw->is_focused) {
|
||||
unsigned int x = 0, y = 0;
|
||||
bool in_left_half_of_cell;
|
||||
if (cell_for_pos(w, &x, &y, &in_left_half_of_cell, osw)) {
|
||||
w->mouse_pos.cell_x = x; w->mouse_pos.cell_y = y;
|
||||
w->mouse_pos.in_left_half_of_cell = in_left_half_of_cell;
|
||||
}
|
||||
}
|
||||
Screen *screen = w->render_data.screen;
|
||||
|
||||
enum MomentumData { NoMomentumData, MomentumPhaseBegan, MomentumPhaseStationary, MomentumPhaseActive, MomentumPhaseEnded, MomentumPhaseCancelled, MomentumPhaseMayBegin };
|
||||
|
||||
@@ -232,7 +232,7 @@ opt('cursor_text_color', '#111111',
|
||||
Choose the color of text under the cursor. If you want it rendered with the
|
||||
background color of the cell underneath instead, use the special keyword:
|
||||
background. Note that if :opt:`cursor` is set to :code:`none` then this setting
|
||||
if ignored.
|
||||
is ignored.
|
||||
'''
|
||||
)
|
||||
|
||||
@@ -987,7 +987,9 @@ The tab bar style, can be one of:
|
||||
A user-supplied Python function called draw_tab is loaded from the file
|
||||
:file:`tab_bar.py` in the kitty config directory. For examples of how to
|
||||
write such a function, see the functions named :code:`draw_tab_with_*` in
|
||||
kitty's source code: :file:`kitty/tab_bar.py`.
|
||||
kitty's source code: :file:`kitty/tab_bar.py`. See also `this discussion
|
||||
<https://github.com/kovidgoyal/kitty/discussions/4447>`_ for examples from
|
||||
kitty users.
|
||||
:code:`hidden`
|
||||
The tab bar is hidden. If you use this, you might want to create a
|
||||
mapping for the :ref:`action-select_tab`
|
||||
|
||||
701
kitty/unicode-data.c
generated
701
kitty/unicode-data.c
generated
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
#include "data-types.h"
|
||||
#include "state.h"
|
||||
// START_KNOWN_MARKS
|
||||
static const combining_type VS15 = 1325, VS16 = 1326;
|
||||
static const combining_type VS15 = 1362, VS16 = 1363;
|
||||
// END_KNOWN_MARKS
|
||||
|
||||
bool is_combining_char(char_type ch);
|
||||
|
||||
118
kitty/wcwidth-std.h
generated
118
kitty/wcwidth-std.h
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2021-10-07
|
||||
// unicode data, built from the unicode standard on: 2022-01-05
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
@@ -14,7 +14,7 @@ wcwidth_std(int32_t code) {
|
||||
return 2;
|
||||
// }}}
|
||||
|
||||
// Marks (6189 codepoints) {{{
|
||||
// Marks (6350 codepoints) {{{
|
||||
case 0x0:
|
||||
return 0;
|
||||
case 0xad:
|
||||
@@ -33,13 +33,17 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x5c7:
|
||||
return 0;
|
||||
case 0x600 ... 0x605:
|
||||
return 0;
|
||||
case 0x610 ... 0x61a:
|
||||
return 0;
|
||||
case 0x61c:
|
||||
return 0;
|
||||
case 0x64b ... 0x65f:
|
||||
return 0;
|
||||
case 0x670:
|
||||
return 0;
|
||||
case 0x6d6 ... 0x6dc:
|
||||
case 0x6d6 ... 0x6dd:
|
||||
return 0;
|
||||
case 0x6df ... 0x6e4:
|
||||
return 0;
|
||||
@@ -47,6 +51,8 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x6ea ... 0x6ed:
|
||||
return 0;
|
||||
case 0x70f:
|
||||
return 0;
|
||||
case 0x711:
|
||||
return 0;
|
||||
case 0x730 ... 0x74a:
|
||||
@@ -67,11 +73,11 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x859 ... 0x85b:
|
||||
return 0;
|
||||
case 0x890 ... 0x891:
|
||||
return 0;
|
||||
case 0x898 ... 0x89f:
|
||||
return 0;
|
||||
case 0x8ca ... 0x8e1:
|
||||
return 0;
|
||||
case 0x8e3 ... 0x903:
|
||||
case 0x8ca ... 0x903:
|
||||
return 0;
|
||||
case 0x93a ... 0x93c:
|
||||
return 0;
|
||||
@@ -271,9 +277,7 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x17dd:
|
||||
return 0;
|
||||
case 0x180b ... 0x180d:
|
||||
return 0;
|
||||
case 0x180f:
|
||||
case 0x180b ... 0x180f:
|
||||
return 0;
|
||||
case 0x1885 ... 0x1886:
|
||||
return 0;
|
||||
@@ -319,9 +323,11 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x1dc0 ... 0x1dff:
|
||||
return 0;
|
||||
case 0x200d:
|
||||
case 0x200b ... 0x200f:
|
||||
return 0;
|
||||
case 0x2065:
|
||||
case 0x202a ... 0x202e:
|
||||
return 0;
|
||||
case 0x2060 ... 0x206f:
|
||||
return 0;
|
||||
case 0x20d0 ... 0x20f0:
|
||||
return 0;
|
||||
@@ -405,9 +411,11 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0xfe20 ... 0xfe2f:
|
||||
return 0;
|
||||
case 0xfeff:
|
||||
return 0;
|
||||
case 0xffa0:
|
||||
return 0;
|
||||
case 0xfff0 ... 0xfff8:
|
||||
case 0xfff0 ... 0xfffb:
|
||||
return 0;
|
||||
case 0x101fd:
|
||||
return 0;
|
||||
@@ -447,8 +455,12 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x110b0 ... 0x110ba:
|
||||
return 0;
|
||||
case 0x110bd:
|
||||
return 0;
|
||||
case 0x110c2:
|
||||
return 0;
|
||||
case 0x110cd:
|
||||
return 0;
|
||||
case 0x11100 ... 0x11102:
|
||||
return 0;
|
||||
case 0x11127 ... 0x11134:
|
||||
@@ -563,6 +575,8 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x11ef3 ... 0x11ef6:
|
||||
return 0;
|
||||
case 0x13430 ... 0x13438:
|
||||
return 0;
|
||||
case 0x16af0 ... 0x16af4:
|
||||
return 0;
|
||||
case 0x16b30 ... 0x16b36:
|
||||
@@ -579,15 +593,15 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x1bc9d ... 0x1bc9e:
|
||||
return 0;
|
||||
case 0x1bca0 ... 0x1bca3:
|
||||
return 0;
|
||||
case 0x1cf00 ... 0x1cf2d:
|
||||
return 0;
|
||||
case 0x1cf30 ... 0x1cf46:
|
||||
return 0;
|
||||
case 0x1d165 ... 0x1d169:
|
||||
return 0;
|
||||
case 0x1d16d ... 0x1d172:
|
||||
return 0;
|
||||
case 0x1d17b ... 0x1d182:
|
||||
case 0x1d16d ... 0x1d182:
|
||||
return 0;
|
||||
case 0x1d185 ... 0x1d18b:
|
||||
return 0;
|
||||
@@ -629,63 +643,17 @@ wcwidth_std(int32_t code) {
|
||||
return 0;
|
||||
case 0x1f3fb ... 0x1f3ff:
|
||||
return 0;
|
||||
case 0xe0000:
|
||||
return 0;
|
||||
case 0xe0002 ... 0xe001f:
|
||||
return 0;
|
||||
case 0xe0080 ... 0xe0fff:
|
||||
case 0xe0000 ... 0xe0fff:
|
||||
return 0;
|
||||
// }}}
|
||||
|
||||
// Non-printing characters (2273 codepoints) {{{
|
||||
// Non-printing characters (2112 codepoints) {{{
|
||||
case 0x1 ... 0x1f:
|
||||
return -1;
|
||||
case 0x7f ... 0x9f:
|
||||
return -1;
|
||||
case 0x600 ... 0x605:
|
||||
return -1;
|
||||
case 0x61c:
|
||||
return -1;
|
||||
case 0x6dd:
|
||||
return -1;
|
||||
case 0x70f:
|
||||
return -1;
|
||||
case 0x890 ... 0x891:
|
||||
return -1;
|
||||
case 0x8e2:
|
||||
return -1;
|
||||
case 0x180e:
|
||||
return -1;
|
||||
case 0x200b ... 0x200c:
|
||||
return -1;
|
||||
case 0x200e ... 0x200f:
|
||||
return -1;
|
||||
case 0x202a ... 0x202e:
|
||||
return -1;
|
||||
case 0x2060 ... 0x2064:
|
||||
return -1;
|
||||
case 0x2066 ... 0x206f:
|
||||
return -1;
|
||||
case 0xd800 ... 0xdfff:
|
||||
return -1;
|
||||
case 0xfeff:
|
||||
return -1;
|
||||
case 0xfff9 ... 0xfffb:
|
||||
return -1;
|
||||
case 0x110bd:
|
||||
return -1;
|
||||
case 0x110cd:
|
||||
return -1;
|
||||
case 0x13430 ... 0x13438:
|
||||
return -1;
|
||||
case 0x1bca0 ... 0x1bca3:
|
||||
return -1;
|
||||
case 0x1d173 ... 0x1d17a:
|
||||
return -1;
|
||||
case 0xe0001:
|
||||
return -1;
|
||||
case 0xe0020 ... 0xe007f:
|
||||
return -1;
|
||||
// }}}
|
||||
|
||||
// Private use (137468 codepoints) {{{
|
||||
@@ -3203,7 +3171,7 @@ is_emoji_presentation_base(uint32_t code) {
|
||||
return true;
|
||||
case 0x1f6d5 ... 0x1f6d7:
|
||||
return true;
|
||||
case 0x1f6e0 ... 0x1f6e5:
|
||||
case 0x1f6dd ... 0x1f6e5:
|
||||
return true;
|
||||
case 0x1f6e9:
|
||||
return true;
|
||||
@@ -3215,29 +3183,31 @@ is_emoji_presentation_base(uint32_t code) {
|
||||
return true;
|
||||
case 0x1f7e0 ... 0x1f7eb:
|
||||
return true;
|
||||
case 0x1f7f0:
|
||||
return true;
|
||||
case 0x1f90c ... 0x1f93a:
|
||||
return true;
|
||||
case 0x1f93c ... 0x1f945:
|
||||
return true;
|
||||
case 0x1f947 ... 0x1f978:
|
||||
return true;
|
||||
case 0x1f97a ... 0x1f9cb:
|
||||
return true;
|
||||
case 0x1f9cd ... 0x1f9ff:
|
||||
case 0x1f947 ... 0x1f9ff:
|
||||
return true;
|
||||
case 0x1fa70 ... 0x1fa74:
|
||||
return true;
|
||||
case 0x1fa78 ... 0x1fa7a:
|
||||
case 0x1fa78 ... 0x1fa7c:
|
||||
return true;
|
||||
case 0x1fa80 ... 0x1fa86:
|
||||
return true;
|
||||
case 0x1fa90 ... 0x1faa8:
|
||||
case 0x1fa90 ... 0x1faac:
|
||||
return true;
|
||||
case 0x1fab0 ... 0x1fab6:
|
||||
case 0x1fab0 ... 0x1faba:
|
||||
return true;
|
||||
case 0x1fac0 ... 0x1fac2:
|
||||
case 0x1fac0 ... 0x1fac5:
|
||||
return true;
|
||||
case 0x1fad0 ... 0x1fad6:
|
||||
case 0x1fad0 ... 0x1fad9:
|
||||
return true;
|
||||
case 0x1fae0 ... 0x1fae7:
|
||||
return true;
|
||||
case 0x1faf0 ... 0x1faf6:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,12 @@ class TestScreen(BaseTest):
|
||||
s.draw(q)
|
||||
self.ae(q, str(s.line(0)))
|
||||
self.ae(s.cursor.x, 8)
|
||||
for x in '\u200b\u200c\u200d':
|
||||
s = self.create_screen()
|
||||
q = f'X{x}Y'
|
||||
s.draw(q)
|
||||
self.ae(q, str(s.line(0)))
|
||||
self.ae(s.cursor.x, 2)
|
||||
|
||||
def test_char_manipulation(self):
|
||||
s = self.create_screen()
|
||||
|
||||
15
setup.py
15
setup.py
@@ -19,8 +19,8 @@ from contextlib import suppress
|
||||
from functools import lru_cache, partial
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
Callable, Dict, Iterable, Iterator, List, Optional, Sequence, Set, Tuple,
|
||||
Union
|
||||
Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional, Sequence,
|
||||
Set, Tuple, Union
|
||||
)
|
||||
|
||||
from glfw import glfw
|
||||
@@ -231,7 +231,7 @@ def test_compile(
|
||||
with open(os.path.join(tdir, f'source.{source_ext}'), 'w', encoding='utf-8') as srcf:
|
||||
print(src, file=srcf)
|
||||
return subprocess.Popen(
|
||||
cc + list(cflags) + ([] if link_also else ['-c']) +
|
||||
cc + ['-Werror=implicit-function-declaration'] + list(cflags) + ([] if link_also else ['-c']) +
|
||||
['-o', os.path.join(tdir, 'source.output'), srcf.name] +
|
||||
[f'-l{x}' for x in libraries] + list(ldflags),
|
||||
stdout=subprocess.DEVNULL, stdin=subprocess.DEVNULL,
|
||||
@@ -1161,10 +1161,13 @@ def package(args: Options, bundle_type: str) -> None:
|
||||
if for_freeze:
|
||||
shutil.copytree('kitty_tests', os.path.join(libdir, 'kitty_tests'))
|
||||
|
||||
def repl(name: str, raw: str, defval: Union[str, float], val: Union[str, float]) -> str:
|
||||
def repl(name: str, raw: str, defval: Union[str, float, FrozenSet[str]], val: Union[str, float, FrozenSet[str]]) -> str:
|
||||
if defval == val:
|
||||
return raw
|
||||
prefix = f'{name}: {type(defval).__name__} ='
|
||||
tname = type(defval).__name__
|
||||
if tname == 'frozenset':
|
||||
tname = 'typing.FrozenSet[str]'
|
||||
prefix = f'{name}: {tname} ='
|
||||
nraw = raw.replace(f'{prefix} {defval!r}', f'{prefix} {val!r}', 1)
|
||||
if nraw == raw:
|
||||
raise SystemExit(f'Failed to change the value of {name}')
|
||||
@@ -1173,7 +1176,7 @@ def package(args: Options, bundle_type: str) -> None:
|
||||
with open(os.path.join(libdir, 'kitty/options/types.py'), 'r+', encoding='utf-8') as f:
|
||||
oraw = raw = f.read()
|
||||
raw = repl('update_check_interval', raw, Options.update_check_interval, args.update_check_interval)
|
||||
raw = repl('shell_integration', raw, Options.shell_integration, args.shell_integration)
|
||||
raw = repl('shell_integration', raw, frozenset(Options.shell_integration.split()), frozenset(args.shell_integration.split()))
|
||||
if raw != oraw:
|
||||
f.seek(0), f.truncate(), f.write(raw)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ _ksi_main() {
|
||||
if [[ -z "$KITTY_SHELL_INTEGRATION" ]]; then return; fi
|
||||
declare -A _ksi_prompt=( [cursor]='y' [title]='y' [mark]='y' [complete]='y' )
|
||||
set -f
|
||||
for i in ${KITTY_SHELL_INTEGRATION}; do
|
||||
for i in ${KITTY_SHELL_INTEGRATION[@]}; do
|
||||
set +f
|
||||
if [[ "$i" == "no-cursor" ]]; then _ksi_prompt[cursor]='n'; fi
|
||||
if [[ "$i" == "no-title" ]]; then _ksi_prompt[title]='n'; fi
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# builtins with `builtin` to avoid accidentally invoking user-defined functions.
|
||||
# We avoid `function` reserved word as an additional defensive measure.
|
||||
|
||||
builtin emulate -L zsh -o no_warn_create_global
|
||||
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
||||
|
||||
[[ -o interactive ]] || builtin return 0 # non-interactive shell
|
||||
[[ -n $KITTY_SHELL_INTEGRATION ]] || builtin return 0 # integration disabled
|
||||
@@ -32,14 +32,42 @@ builtin emulate -L zsh -o no_warn_create_global
|
||||
# 2: none of the above.
|
||||
builtin typeset -gi _ksi_state
|
||||
|
||||
# Attempt to create a writable file descriptor to the TTY so that we can print
|
||||
# to the TTY later even when STDOUT is redirected. This code is fairly subtle.
|
||||
#
|
||||
# - It's tempting to do `[[ -t 1 ]] && exec {_ksi_state}>&1` but we cannot do this
|
||||
# because it'll create a file descriptor >= 10 without O_CLOEXEC. This file
|
||||
# descriptor will leak to child processes.
|
||||
# - If we do `exec {3}>&1`, the file descriptor won't leak to the child processes
|
||||
# but it'll still leak if the current process is replaced with another. In
|
||||
# addition, it'll break user code that relies on fd 3 being available.
|
||||
# - Zsh doesn't expose dup3, which would have allowed us to copy STDOUT with
|
||||
# O_CLOEXEC. The only way to create a file descriptor with O_CLOEXEC is via
|
||||
# sysopen.
|
||||
# - `zmodload zsh/system` and `sysopen -o cloexec -wu _ksi_fd -- /dev/tty` can
|
||||
# fail with an error message to STDERR (the latter can happen even if /dev/tty
|
||||
# is writable), hence the redirection of STDERR. We do it for the whole block
|
||||
# for performance reasons (redirections are slow).
|
||||
# - We must open the file descriptor right here rather than in _ksi_deferred_init
|
||||
# because there are broken zsh plugins out there that run `exec {fd}< <(cmd)`
|
||||
# and then close the file descriptor more than once while suppressing errors.
|
||||
# This could end up closing our file descriptor if we opened it in
|
||||
# _ksi_deferred_init.
|
||||
typeset -gi _ksi_fd
|
||||
{
|
||||
zmodload zsh/system && (( $+builtins[sysopen] )) && {
|
||||
{ [[ -w $TTY ]] && sysopen -o cloexec -wu _ksi_fd -- $TTY } ||
|
||||
{ [[ -w /dev/tty ]] && sysopen -o cloexec -wu _ksi_fd -- /dev/tty }
|
||||
}
|
||||
} 2>/dev/null || (( _ksi_fd = 1 ))
|
||||
|
||||
# Asks kitty to print $@ to its STDOUT. This is for debugging.
|
||||
_ksi_debug_print() {
|
||||
builtin local data saved
|
||||
saved="$IFS"
|
||||
IFS=" "
|
||||
data=$(command base64 <<< "$*")
|
||||
IFS="$saved"
|
||||
builtin printf '\eP@kitty-print|%s\e\\' "${data//$'\n'}"
|
||||
builtin local data
|
||||
data=$(command base64 <<<"${(j: :)@}") || builtin return
|
||||
# Removing all spaces rather than just \n allows this code to
|
||||
# work on broken systems where base64 outputs \r\n.
|
||||
builtin print -nu "$_ksi_fd" '\eP@kitty-print|'"${data//[[:space:]]}"'\e\\'
|
||||
}
|
||||
|
||||
# We defer initialization until precmd for several reasons:
|
||||
@@ -49,12 +77,12 @@ _ksi_debug_print() {
|
||||
# - By deferring initialization we allow user rc files to opt out from some
|
||||
# parts of integration. For example, if a zshrc theme prints OSC 133
|
||||
# marks, it can append " no-prompt-mark" to KITTY_SHELL_INTEGRATION during
|
||||
# intialization to avoid redundant marks from our code.
|
||||
# initialization to avoid redundant marks from our code.
|
||||
builtin typeset -ag precmd_functions
|
||||
precmd_functions+=(_ksi_deferred_init)
|
||||
|
||||
_ksi_deferred_init() {
|
||||
builtin emulate -L zsh -o no_warn_create_global
|
||||
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
||||
|
||||
# Recognized options: no-cursor, no-title, no-prompt-mark, no-complete.
|
||||
builtin local -a opt
|
||||
@@ -69,7 +97,6 @@ _ksi_deferred_init() {
|
||||
builtin local comp_dir=$self_dir/completions
|
||||
|
||||
# Enable completions for `kitty` command.
|
||||
_ksi_debug_print "$self_dir"
|
||||
if (( ! opt[(Ie)no-complete] )) && [[ -r $comp_dir/_kitty ]]; then
|
||||
if (( $+functions[compdef] )); then
|
||||
# If compdef is defined, then either compinit has already run or it's
|
||||
@@ -99,8 +126,10 @@ _ksi_deferred_init() {
|
||||
# themselves with a blinking block cursor within fzf.
|
||||
_ksi_zle_line_init _ksi_zle_line_finish _ksi_zle_keymap_select() {
|
||||
case ${KEYMAP-} in
|
||||
vicmd|visual) builtin print -n '\e[1 q';; # blinking block cursor
|
||||
*) builtin print -n '\e[5 q';; # blinking bar cursor
|
||||
# Blinking block cursor.
|
||||
vicmd|visual) builtin print -nu "$_ksi_fd" '\e[1 q';;
|
||||
# Blinking bar cursor.
|
||||
*) builtin print -nu "$_ksi_fd" '\e[5 q';;
|
||||
esac
|
||||
}
|
||||
fi
|
||||
@@ -109,7 +138,7 @@ _ksi_deferred_init() {
|
||||
if (( ! opt[(Ie)no-prompt-mark] )); then
|
||||
_ksi_precmd() {
|
||||
builtin local -i cmd_status=$?
|
||||
builtin emulate -L zsh -o no_warn_create_global
|
||||
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
||||
|
||||
# Don't write OSC 133 D when our precmd handler is invoked from zle.
|
||||
# Some plugins do that to update prompt on cd.
|
||||
@@ -126,11 +155,11 @@ _ksi_deferred_init() {
|
||||
if (( _ksi_state == 1 )); then
|
||||
# The last written OSC 133 C has not been closed with D yet.
|
||||
# Close it and supply status.
|
||||
builtin printf '\e]133;D;%s\a' $cmd_status
|
||||
builtin print -nu $_ksi_fd '\e]133;D;'$cmd_status'\a'
|
||||
(( _ksi_state = 2 ))
|
||||
elif (( _ksi_state == 2 )); then
|
||||
# There might be an unclosed OSC 133 C. Close that.
|
||||
builtin print -n '\e]133;D\a'
|
||||
builtin print -nu $_ksi_fd '\e]133;D\a'
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -152,6 +181,7 @@ _ksi_deferred_init() {
|
||||
# - False positive (with prompt_percent): PS1="%(?.$mark1.)"
|
||||
# - False negative (with prompt_subst): PS1='$mark1'
|
||||
[[ $PS1 == *$mark1* ]] || PS1=${mark1}${PS1}
|
||||
# PS2 mark is needed when clearing the prompt on resize
|
||||
[[ $PS2 == *$mark2* ]] || PS2=${mark2}${PS2}
|
||||
(( _ksi_state = 2 ))
|
||||
else
|
||||
@@ -168,7 +198,7 @@ _ksi_deferred_init() {
|
||||
# already have a mark, so the following reset-prompt will write
|
||||
# it. If it doesn't, there is nothing we can do.
|
||||
if ! builtin zle; then
|
||||
builtin print -rn -- $mark1[3,-3]
|
||||
builtin print -rnu $_ksi_fd -- $mark1[3,-3]
|
||||
(( _ksi_state = 2 ))
|
||||
fi
|
||||
fi
|
||||
@@ -176,13 +206,13 @@ _ksi_deferred_init() {
|
||||
# Without prompt_percent we cannot patch prompt. Just print the
|
||||
# mark, except when we are invoked from zle. In the latter case we
|
||||
# cannot do anything.
|
||||
builtin print -rn -- $mark1[3,-3]
|
||||
builtin print -rnu $_ksi_fd -- $mark1[3,-3]
|
||||
(( _ksi_state = 2 ))
|
||||
fi
|
||||
}
|
||||
|
||||
_ksi_preexec() {
|
||||
builtin emulate -L zsh -o no_warn_create_global
|
||||
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
||||
|
||||
# This can potentially break user prompt. Oh well. The robustness of
|
||||
# this code can be improved in the case prompt_subst is set because
|
||||
@@ -198,12 +228,15 @@ _ksi_deferred_init() {
|
||||
# its preexec hook before us, we'll incorrectly mark its output as
|
||||
# belonging to the command (as if the user typed it into zle) rather
|
||||
# than command output.
|
||||
builtin print -n '\e]133;C\a'
|
||||
builtin print -nu $_ksi_fd '\e]133;C\a'
|
||||
(( _ksi_state = 1 ))
|
||||
}
|
||||
|
||||
functions[_ksi_zle_line_init]+='
|
||||
builtin print -n "\\e]133;B\\a"'
|
||||
# the following two lines are commented out as currently kitty doesn't use B prompt marking
|
||||
# and hooking zle widgets in ZSH is a total minefield, see https://github.com/kovidgoyal/kitty/issues/4428
|
||||
# so we can at least tell users to use no-cursor and with that avoid hooking ZLE widgets at all
|
||||
# functions[_ksi_zle_line_init]+='
|
||||
# builtin print -nu "$_ksi_fd" "\\e]133;B\\a"'
|
||||
fi
|
||||
|
||||
# Enable terminal title changes.
|
||||
@@ -214,10 +247,10 @@ _ksi_deferred_init() {
|
||||
# We use (V) in preexec to convert control characters to something visible
|
||||
# (LF becomes \n, etc.). This isn't necessary in precmd because (%) does it
|
||||
# for us.
|
||||
functions[_ksi_precmd]+='
|
||||
builtin printf "\\e]2;%s\\a" "${(%):-%(4~|…/%3~|%~)}"'
|
||||
functions[_ksi_preexec]+='
|
||||
builtin printf "\\e]2;%s\\a" "${(V)1}"'
|
||||
functions[_ksi_precmd]+="
|
||||
builtin print -rnu $_ksi_fd \$'\\e]2;'\"\${(%):-%(4~|…/%3~|%~)}\"\$'\\a'"
|
||||
functions[_ksi_preexec]+="
|
||||
builtin print -rnu $_ksi_fd \$'\\e]2;'\"\${(V)1}\"\$'\\a'"
|
||||
fi
|
||||
|
||||
# Some zsh users manually run `source ~/.zshrc` in order to apply rc file
|
||||
@@ -231,16 +264,44 @@ _ksi_deferred_init() {
|
||||
# current shell is `exec zsh`. This will remove our integration from the shell
|
||||
# unless it's explicitly invoked from .zshrc. This is not an issue with
|
||||
# `exec zsh` but rather with our implementation of automatic shell integration.
|
||||
builtin autoload -Uz add-zle-hook-widget
|
||||
if (( $+functions[_ksi_zle_line_init] )); then
|
||||
add-zle-hook-widget line-init _ksi_zle_line_init
|
||||
fi
|
||||
if (( $+functions[_ksi_zle_line_finish] )); then
|
||||
add-zle-hook-widget line-finish _ksi_zle_line_finish
|
||||
fi
|
||||
if (( $+functions[_ksi_zle_keymap_select] )); then
|
||||
add-zle-hook-widget keymap-select _ksi_zle_keymap_select
|
||||
fi
|
||||
|
||||
# In the ideal world we would use add-zle-hook-widget to hook zle-line-init
|
||||
# and similar widget. This breaks user configs though, so we have do this
|
||||
# horrible thing instead.
|
||||
builtin local hook func widget orig_widget flag
|
||||
for hook in line-init line-finish keymap-select; do
|
||||
func=_ksi_zle_${hook/-/_}
|
||||
(( $+functions[$func] )) || builtin continue
|
||||
widget=zle-$hook
|
||||
if [[ $widgets[$widget] == user:azhw:* &&
|
||||
$+functions[add-zle-hook-widget] -eq 1 ]]; then
|
||||
# If the widget is already hooked by add-zle-hook-widget at the top
|
||||
# level, add our hook at the end. We MUST do it this way. We cannot
|
||||
# just wrap the widget ourselves in this case because it would
|
||||
# trigger bugs in add-zle-hook-widget.
|
||||
add-zle-hook-widget $hook $func
|
||||
else
|
||||
if (( $+widgets[$widget] )); then
|
||||
# There is a widget but it's not from add-zle-hook-widget. We
|
||||
# can rename the original widget, install our own and invoke
|
||||
# the original when we are called.
|
||||
#
|
||||
# Note: The leading dot is to work around bugs in
|
||||
# zsh-syntax-highlighting.
|
||||
orig_widget=._ksi_orig_$widget
|
||||
builtin zle -A $widget $orig_widget
|
||||
if [[ $widgets[$widget] == user:* ]]; then
|
||||
# No -w here to preserve $WIDGET within the original widget.
|
||||
flag=
|
||||
else
|
||||
flag=w
|
||||
fi
|
||||
functions[$func]+="
|
||||
builtin zle $orig_widget -N$flag -- \"$@\""
|
||||
fi
|
||||
builtin zle -N $widget $func
|
||||
fi
|
||||
done
|
||||
|
||||
if (( $+functions[_ksi_preexec] )); then
|
||||
builtin typeset -ag preexec_functions
|
||||
|
||||
Reference in New Issue
Block a user