Compare commits

..

35 Commits

Author SHA1 Message Date
Kovid Goyal
95245ee473 version 0.36.1 2024-08-24 06:22:42 +05:30
Kovid Goyal
40bc1d4f38 DRYer 2024-08-24 06:21:27 +05:30
Kovid Goyal
808c68dd0b ... 2024-08-23 15:44:33 +05:30
Kovid Goyal
c26b441105 Dont output falling back to menlo message for the symbols nerd font mono family 2024-08-23 15:37:26 +05:30
Kovid Goyal
036241fc6c macOS: Fix a regression in the previous release that caused --single-instance to not work when using macos-launch-services-cmdline 2024-08-23 15:27:26 +05:30
Kovid Goyal
0c1d239b5f Exclude bypy/b from go test discovery 2024-08-23 11:27:54 +05:30
Kovid Goyal
e51fda041e ... 2024-08-22 20:29:08 +05:30
Kovid Goyal
4315bcfdc9 Fix off by one in mark color indexing in shader
Fixes #7768
2024-08-22 15:48:22 +05:30
Kovid Goyal
86797ff96d Fix #7763 2024-08-21 20:46:05 +05:30
Kovid Goyal
173bf4a4a3 Disable in band resize notifications in a few more places 2024-08-21 12:11:14 +05:30
Kovid Goyal
807e14684f Fix #7762 2024-08-21 12:01:12 +05:30
Kovid Goyal
d75d372da0 Reset base64 streaming decoder after invalid input
Fixes #7757
2024-08-20 17:37:25 +05:30
Kovid Goyal
2ac26b0e6d Fix #7752 2024-08-20 17:27:13 +05:30
Kovid Goyal
6d06415ec5 Another kitty icon 2024-08-20 07:15:02 +05:30
Kovid Goyal
8dc1dfed48 ... 2024-08-19 21:38:15 +05:30
Kovid Goyal
3b27381a9b ... 2024-08-19 21:34:32 +05:30
Kovid Goyal
3abf808843 Improve some documentation 2024-08-19 21:30:42 +05:30
Kovid Goyal
e74188fcf0 Switch to using ps to get all processes
The Go process module is very slow to get Exe() on non-Linux systems
without CGO as it works by calling lsof on the pid. So we anyway have to
filter by command line first. So might as well just use ps in that case.
2024-08-19 20:54:54 +05:30
Kovid Goyal
9708959438 When reloading in all kitty instances, only use readlink on processes that contain "kitty" in the image name
Apparently there are some machines where a few hundred/thousand readlink calls
take 30 seconds! See #7744
2024-08-19 19:18:37 +05:30
Kovid Goyal
4ed01bdd1e ... 2024-08-19 10:27:40 +05:30
Kovid Goyal
b3b2f56890 Installer: allow installing specific versions 2024-08-19 10:25:51 +05:30
Kovid Goyal
7c4977146f Fix #7741 2024-08-19 08:51:08 +05:30
Kovid Goyal
9ba34941e5 Merge branch 'master' of https://github.com/f0rc/kitty 2024-08-19 08:41:34 +05:30
f0rc
d0ac1c62fe shift before control 2024-08-18 15:53:07 -05:00
Kovid Goyal
0084f93e1b MacOS Intel: Fix a crash in the choose-fonts kitten when displaying previews of variable fonts
Looks like a bug in Py_BuildValue for s# values on that platform. Workaround by
constructing the string directly and passing to to Py_BuildValue.

Fixes #7734
2024-08-18 17:22:12 +05:30
Kovid Goyal
33fa9a08e4 Allow turning off stripping in update-on-ox 2024-08-18 15:30:38 +05:30
Kovid Goyal
80ec6ae4b6 DRYer 2024-08-18 13:41:59 +05:30
Kovid Goyal
6fabb47aa2 ... 2024-08-18 13:04:43 +05:30
Kovid Goyal
eab801cd17 DRYer 2024-08-18 11:59:34 +05:30
Kovid Goyal
79983897b5 Show how to combine multiple key presses in the FAQ 2024-08-18 10:16:43 +05:30
Kovid Goyal
91273276b5 Merge branch 'patch-1' of https://github.com/jaywonchung/kitty 2024-08-18 08:47:48 +05:30
Jae-Won Chung
8a98b3f4ef Fix typo in notify kitten usage 2024-08-17 22:08:15 -04:00
Kovid Goyal
519b4e43a2 ... 2024-08-17 16:04:15 +05:30
Kovid Goyal
554a2b1811 Allow unfocused cursor shape to remain unchanged
Fixes #7728
2024-08-17 15:49:55 +05:30
Kovid Goyal
aa83860628 Cleanup formatting 2024-08-17 12:46:19 +05:30
43 changed files with 197 additions and 100 deletions

View File

@@ -40,7 +40,7 @@ Action Shortcut
======================== =======================
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
Close tab :sc:`close_tab` (also :kbd:`⌘+w` on macOS)
Next tab :sc:`next_tab` (also :kbd:`⌃+⇥` and :kbd:`⇧+⌘+]` on macOS)
Next tab :sc:`next_tab` (also :kbd:`⇧+⌃+⇥` and :kbd:`⇧+⌘+]` on macOS)
Previous tab :sc:`previous_tab` (also :kbd:`⇧+⌃+⇥` and :kbd:`⇧+⌘+[` on macOS)
Next layout :sc:`next_layout`
Move tab forward :sc:`move_tab_forward`

View File

@@ -99,12 +99,12 @@ Customizing the installation
_kitty_install_cmd \
installer=nightly dest=/some/other/location
* You can specify a different install location, with ``dest``:
* You can specify a specific version to install, with:
.. code-block:: sh
_kitty_install_cmd \
dest=/some/other/location
installer=version-0.35.2
* You can tell the installer not to launch |kitty| after installing it with
``launch=n``:

View File

@@ -74,6 +74,19 @@ consumption to do the same tasks.
Detailed list of changes
-------------------------------------
0.36.1 [2024-08-24]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Allow specifying that the :opt:`cursor shape for unfocused windows <cursor_shape_unfocused>` should remain unchanged (:pull:`7728`)
- MacOS Intel: Fix a crash in the choose-fonts kitten when displaying previews of variable fonts (:iss:`7734`)
- Remote control: Fix a regression causing an escape code to leak when using @ launch with ``--no-response`` over the TTY (:iss:`7752`)
- OSC 52: Fix a regression in the previous release that broke handling of invalid base64 encoded data in OSC 52 requests (:iss:`7757`)
- macOS: Fix a regression in the previous release that caused :option:`kitty --single-instance` to not work when using :file:`macos-launch-services-cmdline`
0.36.0 [2024-08-17]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -141,22 +141,24 @@ compatibility, but a sane, rigorously specified subset is chosen.
RGB colors are encoded in one of three forms:
rgb:<red>/<green>/<blue>
<red>, <green>, <blue> := h | hh | hhh | hhhh
h := single hexadecimal digits (case insignificant)
Note that h indicates the value scaled in 4 bits, hh the value scaled in 8 bits, hhh the value scaled in 12 bits, and hhhh the value scaled
in 16 bits, respectively.
``rgb:<red>/<green>/<blue>``
| <red>, <green>, <blue> := h | hh | hhh | hhhh
| h := single hexadecimal digits (case insignificant)
| Note that h indicates the value scaled in 4 bits, hh the value scaled in 8 bits,
hhh the value scaled in 12 bits, and hhhh the value scaled in 16 bits, respectively.
#<h...>
h := single hexadecimal digits (case insignificant)
#RGB (4 bits each)
#RRGGBB (8 bits each)
#RRRGGGBBB (12 bits each)
#RRRRGGGGBBBB (16 bits each)
The R, G, and B represent single hexadecimal digits. When fewer than 16 bits each are specified, they represent the most significant bits
of the value (unlike the “rgb:” syntax, in which values are scaled). For example, the string ``#3a7`` is the same as ``#3000a0007000``.
``#<h...>``
| h := single hexadecimal digits (case insignificant)
| #RGB (4 bits each)
| #RRGGBB (8 bits each)
| #RRRGGGBBB (12 bits each)
| #RRRRGGGGBBBB (16 bits each)
| The R, G, and B represent single hexadecimal digits. When fewer than 16 bits
each are specified, they represent the most significant bits of the value
(unlike the “rgb:” syntax, in which values are scaled). For example,
the string ``#3a7`` is the same as ``#3000a0007000``.
rgbi:<red>/<green>/<blue>
``rgbi:<red>/<green>/<blue>``
red, green, and blue are floating-point values between 0.0 and 1.0, inclusive. The input format for these values is an optional
sign, a string of numbers possibly containing a decimal point, and an optional exponent field containing an E or e followed by a possibly
signed integer string.

View File

@@ -280,7 +280,7 @@ with::
On macOS, you can open *Font Book* and look in the :guilabel:`Fixed width`
collection to see all monospaced fonts on your system.
Note that the spacing property is calculated by fontconfig based on actual glyph
Note that **on Linux**, the spacing property is calculated by fontconfig based on actual glyph
widths in the font. If for some reason fontconfig concludes your favorite
monospace font does not have ``spacing=100`` you can override it by using the
following :file:`~/.config/fontconfig/fonts.conf`::
@@ -346,6 +346,10 @@ many alternate icons available, click on an icon to visit its homepage:
:target: https://github.com/samholmes/whiskers
:width: 256
.. image:: https://github.com/user-attachments/assets/a37d7830-4a8c-45a8-988a-3e98a41ea541
:target: https://github.com/diegobit/kitty-icon
:width: 256
.. image:: https://github.com/eccentric-j/eccentric-icons/raw/main/icons/kitty-terminal/2d/kitty-preview.png
:target: https://github.com/eccentric-j/eccentric-icons
:width: 256
@@ -399,9 +403,11 @@ This is accomplished by using ``map`` with :ac:`send_key` in :file:`kitty.conf`.
For example::
map alt+s send_key ctrl+s
map ctrl+alt+2 combine : send_key ctrl+c : send_key h : send_key a
This causes the program running in kitty to receive the :kbd:`ctrl+s` key when
you press the :kbd:`alt+s` key. To see this in action, run::
you press the :kbd:`alt+s` key and several keystrokes when you press
:kbd:`ctrl+alt+2`. To see this in action, run::
kitten show-key -m kitty

View File

@@ -98,6 +98,9 @@ get_release_url() {
get_file_url "v$release_version" "$release_version"
}
get_version_url() {
get_file_url "v$1" "$1"
}
get_nightly_url() {
get_file_url "nightly" "nightly"
@@ -108,6 +111,7 @@ get_download_url() {
case "$installer" in
"nightly") get_nightly_url ;;
"") get_release_url ;;
version-*) get_version_url "${installer#*-}";;
*) installer_is_file="y" ;;
esac
}
@@ -126,20 +130,24 @@ download_installer() {
}
}
ensure_dest() {
printf "%s\n" "Installing to $dest"
command rm -rf "$dest" || die "Failed to delete $dest"
command mkdir -p "$dest" || die "Failed to mkdir -p $dest"
command rm -rf "$dest" || die "Failed to delete $dest"
}
linux_install() {
command mkdir "$tdir/mp"
command tar -C "$tdir/mp" "-xJof" "$installer" || die "Failed to extract kitty tarball"
printf "%s\n" "Installing to $dest"
command rm -rf "$dest" || die "Failed to delete $dest"
ensure_dest
command mv "$tdir/mp" "$dest" || die "Failed to move kitty.app to $dest"
}
macos_install() {
command mkdir "$tdir/mp"
command hdiutil attach "$installer" "-mountpoint" "$tdir/mp" || die "Failed to mount kitty.dmg"
printf "%s\n" "Installing to $dest"
command rm -rf "$dest"
command mkdir -p "$dest" || die "Failed to create the directory: $dest"
ensure_dest
command ditto -v "$tdir/mp/kitty.app" "$dest"
rc="$?"
command hdiutil detach "$tdir/mp"

View File

@@ -38,11 +38,15 @@ In addition to kitty, this protocol is also implemented in:
* The `WezTerm terminal <https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html>`__
* The `alacritty terminal <https://github.com/alacritty/alacritty/pull/7125>`__
* The `rio terminal <https://github.com/raphamorim/rio/commit/cd463ca37677a0fc48daa8795ea46dadc92b1e95>`__
* The `notcurses library
<https://github.com/dankamongmen/notcurses/issues/2131>`__
* The `crossterm library
<https://github.com/crossterm-rs/crossterm/pull/688>`__
Libraries implementing this protocol:
* The `notcurses library <https://github.com/dankamongmen/notcurses/issues/2131>`__
* The `crossterm library <https://github.com/crossterm-rs/crossterm/pull/688>`__
* The `textual library <https://github.com/Textualize/textual/pull/4631>`__
Programs implementing this protocol:
* The `Vim text editor <https://github.com/vim/vim/commit/63a2e360cca2c70ab0a85d14771d3259d4b3aafa>`__
* The `Emacs text editor via the kkp package <https://github.com/benjaminor/kkp>`__
* The `Neovim text editor <https://github.com/neovim/neovim/pull/18181>`__
@@ -52,6 +56,10 @@ In addition to kitty, this protocol is also implemented in:
* The `far2l file manager <https://github.com/elfmz/far2l/commit/e1f2ee0ef2b8332e5fa3ad7f2e4afefe7c96fc3b>`__
* The `Yazi file manager <https://github.com/sxyazi/yazi>`__
* The `awrit web browser <https://github.com/chase/awrit>`__
* The `Turbo Vision <https://github.com/magiblot/tvision/commit/6e5a7b46c6634079feb2ac98f0b890bbed59f1ba>`/`Free Vision <https://gitlab.com/freepascal.org/fpc/source/-/issues/40673#note_2061428120>`__ IDEs
Shells implementing this protocol:
* The `nushell shell <https://github.com/nushell/nushell/pull/10540>`__
* The `fish shell <https://github.com/fish-shell/fish-shell/commit/8bf8b10f685d964101f491b9cc3da04117a308b4>`__

View File

@@ -73,6 +73,9 @@ would pass to ``kitten @``. For example:
shown above or ``--self``.
Run, ``kitten @ --help`` in a kitty terminal, to see all the remote control
commands available to you.
Passing arguments to kittens
------------------------------

View File

@@ -114,11 +114,14 @@ Watching launched windows
The :option:`launch --watcher` option allows you to specify Python functions
that will be called at specific events, such as when the window is resized or
closed. Simply specify the path to a Python module that specifies callback
functions for the events you are interested in, for example:
closed. Note that you can also specify watchers that are loaded for all windows,
via :opt:`watcher`. To create a watcher, specify the path to a Python module
that specifies callback functions for the events you are interested in, for
create :file:`~/.config/kitty/mywatcher.py` and use :option:`launch --watcher` = :file:`mywatcher.py`:
.. code-block:: python
# ~/.config/kitty/mywatcher.py
from typing import Any, Dict
from kitty.boss import Boss
@@ -127,36 +130,53 @@ functions for the events you are interested in, for example:
def on_resize(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# Here data will contain old_geometry and new_geometry
# Note that resize is also called the first time a window is created
# which can be detected as old_geometry will have all zero values, in
# particular, old_geometry.xnum and old_geometry.ynum will be zero.
...
def on_focus_change(boss: Boss, window: Window, data: Dict[str, Any])-> None:
# Here data will contain focused
...
def on_close(boss: Boss, window: Window, data: Dict[str, Any])-> None:
# called when window is closed, typically when the program running in
# it exits
...
def on_set_user_var(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when a "user variable" is set or deleted on a window. Here
# data will contain key and value
...
def on_title_change(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when the window title is changed on a window. Here
# data will contain title and from_child. from_child will be True
# when a title change was requested via escape code from the program
# running in the terminal
...
def on_cmd_startstop(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when the shell starts/stops executing a command. Here
# data will contain is_start, cmdline and time.
...
Every callback is passed a reference to the global ``Boss`` object as well as
the ``Window`` object the action is occurring on. The ``data`` object is a dict
that contains event dependent data. Some useful methods and attributes for the
``Window`` object are: ``as_text(as_ans=False, add_history=False,
add_wrap_markers=False, alternate_screen=False)`` with which you can get the
contents of the window and its scrollback buffer. Similarly,
``window.child.pid`` is the PID of the processes that was launched
in the window and ``window.id`` is the internal kitty ``id`` of the window.
that contains event dependent data. You have full access to kitty internals in
the watcher scripts, however kitty internals are not documented/stable so for
most things you are better off using the kitty :doc:`Remote control API </remote-control>`.
Simply call :code:`boss.call_remote_control()`, with the same arguments you
would pass to ``kitten @``. For example:
.. code-block:: python
def on_resize(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# send some text to the resized window
boss.call_remote_control(window, ('send-text', f'--match=id:{window.id}', 'hello world'))
Run, ``kitten @ --help`` in a kitty terminal, to see all the remote control
commands available to you.
Finding executables

View File

@@ -110,7 +110,7 @@ func run_plain_text_loop(opts *Options) (err error) {
defer tempfile.Close()
}
}
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking, loop.NoInBandResizeNotifications)
if err != nil {
return
}

View File

@@ -282,7 +282,7 @@ func parse_aliases(raw []string) (map[string][]string, error) {
}
func run_get_loop(opts *Options, args []string) (err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking, loop.NoInBandResizeNotifications)
if err != nil {
return err
}

View File

@@ -46,7 +46,7 @@ func (self *Input) has_mime_matching(predicate func(string) bool) bool {
}
func write_loop(inputs []*Input, opts *Options) (err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking, loop.NoInBandResizeNotifications)
if err != nil {
return err
}

View File

@@ -21,7 +21,7 @@ func DetectSupport(timeout time.Duration) (memory, files, direct bool, err error
temp_files_to_delete := make([]string, 0, 8)
shm_files_to_delete := make([]shm.MMap, 0, 8)
var direct_query_id, file_query_id, memory_query_id uint32
lp, e := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
lp, e := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking, loop.NoInBandResizeNotifications)
if e != nil {
err = e
return

View File

@@ -112,7 +112,7 @@ func (p *parsed_data) generate_chunks(callback func(string)) {
}
func (p *parsed_data) run_loop() (err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking, loop.NoInBandResizeNotifications)
if err != nil {
return err
}

View File

@@ -111,7 +111,7 @@ with the specified identifier is closed.
usage = 'TITLE [BODY ...]'
if __name__ == '__main__':
raise SystemExit('This should be run as kitten clipboard')
raise SystemExit('This should be run as `kitten notify ...`')
elif __name__ == '__doc__':
cd = sys.cli_docs # type: ignore
cd['usage'] = usage

View File

@@ -26,7 +26,7 @@ func main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) {
queries[i] = x
}
}
lp, err := loop.New(loop.NoAlternateScreen, loop.NoKeyboardStateChange, loop.NoMouseTracking, loop.NoRestoreColors)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoKeyboardStateChange, loop.NoMouseTracking, loop.NoRestoreColors, loop.NoInBandResizeNotifications)
if err != nil {
return 1, err
}

View File

@@ -159,7 +159,7 @@ void main() {
int mark = int(text_attrs >> MARK_SHIFT) & MARK_MASK;
uint has_mark = uint(step(1, float(mark)));
uint bg_as_uint = resolve_color(colors[bg_index], default_colors[bg_index]);
bg_as_uint = has_mark * color_table[NUM_COLORS + mark] + (ONE - has_mark) * bg_as_uint;
bg_as_uint = has_mark * color_table[NUM_COLORS + mark - 1] + (ONE - has_mark) * bg_as_uint;
vec3 bg = color_to_vec(bg_as_uint);
uint fg_as_uint = resolve_color(colors[fg_index], default_colors[fg_index]);
// }}}
@@ -169,7 +169,7 @@ void main() {
// Foreground
fg_as_uint = has_mark * color_table[NUM_COLORS + MARK_MASK + 1 + mark] + (ONE - has_mark) * fg_as_uint;
fg_as_uint = has_mark * color_table[NUM_COLORS + MARK_MASK + mark] + (ONE - has_mark) * fg_as_uint;
foreground = color_to_vec(fg_as_uint);
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim);

View File

@@ -289,7 +289,12 @@ class WriteRequest:
def write_base64_data(self, b: bytes) -> None:
if not self.max_size_exceeded:
decoded = self.decoder.decode(b)
try:
decoded = self.decoder.decode(b)
except ValueError:
log_error('Clipboard write request has invalid data, ignoring this chunk of data')
self.decoder.reset()
decoded = b''
if decoded:
self.tempfile.write(decoded)
if self.max_size > 0 and self.tempfile.tell() > (self.max_size * 1024 * 1024):

View File

@@ -23,7 +23,7 @@ class Version(NamedTuple):
appname: str = 'kitty'
kitty_face = '🐱'
version: Version = Version(0, 36, 0)
version: Version = Version(0, 36, 1)
str_version: str = '.'.join(map(str, version))
_plat = sys.platform.lower()
is_macos: bool = 'darwin' in _plat

View File

@@ -854,10 +854,11 @@ render_sample_text(CTFace *self, PyObject *args) {
}
render_glyphs(font, canvas_width, canvas_height, baseline, num_glyphs);
uint8_t r = (fg >> 16) & 0xff, g = (fg >> 8) & 0xff, b = fg & 0xff;
const uint8_t *last_pixel = (uint8_t*)PyBytes_AS_STRING(pbuf) + PyBytes_GET_SIZE(pbuf) - sizeof(pixel);
for (
uint8_t *p = (uint8_t*)PyBytes_AS_STRING(pbuf), *s = buffers.render_buf;
p < (uint8_t*)PyBytes_AS_STRING(pbuf) + sizeof(pixel) * canvas_width * canvas_height;
p += 4, s++
p <= last_pixel;
p += sizeof(pixel), s++
) {
p[0] = r; p[1] = g; p[2] = b; p[3] = s[0];
}

View File

@@ -27,7 +27,7 @@ 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(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", "HOLLOW" };
#define BOOL(x) ((x) ? Py_True : Py_False)
static PyObject *

View File

@@ -728,6 +728,7 @@ PyInit_fast_data_types(void) {
PyModule_AddIntMacro(m, CURSOR_BLOCK);
PyModule_AddIntMacro(m, CURSOR_BEAM);
PyModule_AddIntMacro(m, CURSOR_UNDERLINE);
PyModule_AddIntMacro(m, CURSOR_HOLLOW);
PyModule_AddIntMacro(m, NO_CURSOR_SHAPE);
PyModule_AddIntMacro(m, DECAWM);
PyModule_AddIntMacro(m, DECCOLM);

View File

@@ -68,7 +68,7 @@ typedef uint16_t glyph_index;
typedef uint32_t pixel;
typedef unsigned int index_type;
typedef uint16_t sprite_index;
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape;
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, CURSOR_HOLLOW, NUM_OF_CURSOR_SHAPES } CursorShape;
typedef enum { DISABLE_LIGATURES_NEVER, DISABLE_LIGATURES_CURSOR, DISABLE_LIGATURES_ALWAYS } DisableLigature;
#define ERROR_PREFIX "[PARSE ERROR]"

View File

@@ -256,6 +256,7 @@ GLFW_RELEASE: int
GLFW_REPEAT: int
CURSOR_BEAM: int
CURSOR_BLOCK: int
CURSOR_HOLLOW: int
NO_CURSOR_SHAPE: int
CURSOR_UNDERLINE: int
DECAWM: int

View File

@@ -325,8 +325,8 @@ read_fvar_font_table(const uint8_t *table, size_t table_len, PyObject *name_look
const double minimum = next32, def = next32, maximum = next32;
p = (uint16_t*)(pos + 16);
int32_t flags = next, strid = next;
PyObject *axis = Py_BuildValue("{sd sd sd ss# sO sN}",
"minimum", minimum, "maximum", maximum, "default", def, "tag", pos, 4,
PyObject *axis = Py_BuildValue("{sd sd sd sN sO sN}",
"minimum", minimum, "maximum", maximum, "default", def, "tag", PyUnicode_FromStringAndSize((const char*)pos, 4),
"hidden", (flags & 1) ? Py_True : Py_False, "strid", get_best_name(name_lookup_table, strid)
); if (!axis) return NULL;
PyTuple_SET_ITEM(axes, i, axis);

View File

@@ -195,7 +195,7 @@ def find_best_match(
# Let CoreText choose the font if the family exists, otherwise
# fallback to Menlo
if q not in font_map['family_map']:
if family != "monospace":
if family.lower() not in ('monospace', 'symbols nerd font mono'):
log_error(f'The font {family} was not found, falling back to Menlo')
q = 'menlo'
candidates = scorer.sorted_candidates(font_map['family_map'][q])

View File

@@ -1013,7 +1013,8 @@ render_sample_text(Face *self, PyObject *args) {
place_bitmap_in_canvas(canvas, &pbm, canvas_width, canvas_height, x, 0, baseline, 99999, fg, 0, y);
}
for (uint8_t *p = (uint8_t*)PyBytes_AS_STRING(pbuf); p < (uint8_t*)PyBytes_AS_STRING(pbuf) + sizeof(pixel) * canvas_width * canvas_height; p += 4) {
const uint8_t *last_pixel = (uint8_t*)PyBytes_AS_STRING(pbuf) + PyBytes_GET_SIZE(pbuf) - sizeof(pixel);
for (uint8_t *p = (uint8_t*)PyBytes_AS_STRING(pbuf); p <= last_pixel; p += sizeof(pixel)) {
uint8_t a = p[0], b = p[1], g = p[2], r = p[3];
p[0] = r; p[1] = g; p[2] = b; p[3] = a;
}

View File

@@ -86,6 +86,7 @@ bool
init_logging(PyObject *module) {
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
#ifdef __APPLE__
// This env var can be either 1 or 2
if (getenv("KITTY_LAUNCHED_BY_LAUNCH_SERVICES") != NULL) use_os_log = true;
#endif
return true;

View File

@@ -320,6 +320,11 @@ def macos_cmdline(argv_args: list[str]) -> list[str]:
ans = list(shlex_split(raw))
if ans and ans[0] == 'kitty':
del ans[0]
if '-1' in ans or '--single-instance' in ans:
# Re-exec with new argv so that the C code that handles single instance
# can pick up the modified argv
os.environ['KITTY_LAUNCHED_BY_LAUNCH_SERVICES'] = '2' # so that use_os_log is set in the re-execed process
os.execl(kitty_exe(), 'kitty', *(ans + argv_args))
return ans + argv_args
@@ -446,7 +451,6 @@ def _main() -> None:
if is_macos and os.environ.pop('KITTY_LAUNCHED_BY_LAUNCH_SERVICES', None) == '1':
os.chdir(os.path.expanduser('~'))
args = macos_cmdline(args)
getattr(sys, 'kitty_run_data')['launched_by_launch_services'] = True
try:
cwd_ok = os.path.isdir(os.getcwd())
except Exception:

View File

@@ -189,7 +189,12 @@ class EncodedDataStore:
def add_base64_data(self, data: Union[str, bytes]) -> None:
if isinstance(data, str):
data = data.encode('ascii')
self.data_store(self.decoder.decode(data))
try:
decoded = self.decoder.decode(data)
except ValueError:
log_error('Ignoring invalid base64 encoded data in notification request')
else:
self.data_store(decoded)
def flush_encoded_data(self) -> None:
self.decoder.reset()

View File

@@ -315,7 +315,7 @@ cursor shape to :code:`beam` at shell prompts. You can avoid this by setting
opt('cursor_shape_unfocused', 'hollow', option_type='to_cursor_unfocused_shape', ctype='int', long_text='''
Defines the text cursor shape when the OS window is not focused. The unfocused
cursor shape can be one of :code:`block`, :code:`beam`, :code:`underline`,
:code:`hollow`.
:code:`hollow` and :code:`unchanged` (leave the cursor shape as it is).
''')
opt('cursor_beam_thickness', '1.5',
@@ -1529,7 +1529,7 @@ opt('background_image_linear', 'no',
opt('second_transparent_bg', 'none', option_type='to_color_or_none', long_text='''
When the background color matches this color, :opt:`background_opacity` is applied to it
to render it as semi-transparent, just as for colors matching the background color.
to render it as semi-transparent, just as for colors matching the main :opt:`background` color.
Useful in more complex UIs like editors where you could want more than a single background color
to be rendered as transparent, for instance, for a cursor highlight line background.
Terminal applications can set this color using :ref:`The kitty color control <color_control>`

View File

@@ -507,7 +507,7 @@ class Options:
cursor_beam_thickness: float = 1.5
cursor_blink_interval: typing.Tuple[float, kitty.options.utils.EasingFunction, kitty.options.utils.EasingFunction] = (-1.0, kitty.options.utils.EasingFunction(), kitty.options.utils.EasingFunction())
cursor_shape: int = 1
cursor_shape_unfocused: int = 0
cursor_shape_unfocused: int = 4
cursor_stop_blinking_after: float = 15.0
cursor_text_color: typing.Optional[kitty.fast_data_types.Color] = Color(17, 17, 17)
cursor_underline_thickness: float = 2.0

View File

@@ -46,7 +46,7 @@ from kitty.conf.utils import (
unit_float,
)
from kitty.constants import is_macos
from kitty.fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, NO_CURSOR_SHAPE, Color, Shlex, SingleKey
from kitty.fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_HOLLOW, CURSOR_UNDERLINE, NO_CURSOR_SHAPE, Color, Shlex, SingleKey
from kitty.fonts import FontModification, FontSpec, ModificationType, ModificationUnit, ModificationValue
from kitty.key_names import character_key_name_aliases, functional_key_name_aliases, get_key_name_lookup
from kitty.rgb import color_as_int
@@ -530,7 +530,8 @@ cshapes_unfocused = {
'block': CURSOR_BLOCK,
'beam': CURSOR_BEAM,
'underline': CURSOR_UNDERLINE,
'hollow': NO_CURSOR_SHAPE
'hollow': CURSOR_HOLLOW,
'unchanged': NO_CURSOR_SHAPE,
}

View File

@@ -2442,8 +2442,7 @@ screen_request_capabilities(Screen *self, char c, const char *query) {
if (strcmp(" q", query) == 0) {
// cursor shape DECSCUSR
switch(self->cursor->shape) {
case NO_CURSOR_SHAPE:
case NUM_OF_CURSOR_SHAPES:
case NO_CURSOR_SHAPE: case CURSOR_HOLLOW: case NUM_OF_CURSOR_SHAPES:
shape = 1; break;
case CURSOR_BLOCK:
shape = self->cursor->non_blinking ? 2 : 0; break;

View File

@@ -327,27 +327,17 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
if (cursor->opacity > 0) {
rd->cursor_x = cursor->x, rd->cursor_y = cursor->y;
rd->cursor_opacity = cursor->opacity;
if (cursor->is_focused) {
switch(cursor->shape) {
default:
rd->cursor_fg_sprite_idx = BLOCK_IDX; break;
case CURSOR_BEAM:
rd->cursor_fg_sprite_idx = BEAM_IDX; break;
case CURSOR_UNDERLINE:
rd->cursor_fg_sprite_idx = UNDERLINE_IDX; break;
}
} else {
switch(OPT(cursor_shape_unfocused)) {
default:
rd->cursor_fg_sprite_idx = UNFOCUSED_IDX; break;
case CURSOR_BEAM:
rd->cursor_fg_sprite_idx = BEAM_IDX; break;
case CURSOR_UNDERLINE:
rd->cursor_fg_sprite_idx = UNDERLINE_IDX; break;
case CURSOR_BLOCK:
rd->cursor_fg_sprite_idx = BLOCK_IDX; break;
}
}
CursorShape cs = (cursor->is_focused || OPT(cursor_shape_unfocused) == NO_CURSOR_SHAPE) ? cursor->shape : OPT(cursor_shape_unfocused);
switch(cs) {
case CURSOR_BEAM:
rd->cursor_fg_sprite_idx = BEAM_IDX; break;
case CURSOR_UNDERLINE:
rd->cursor_fg_sprite_idx = UNDERLINE_IDX; break;
case CURSOR_BLOCK: case NUM_OF_CURSOR_SHAPES: case NO_CURSOR_SHAPE:
rd->cursor_fg_sprite_idx = BLOCK_IDX; break;
case CURSOR_HOLLOW:
rd->cursor_fg_sprite_idx = UNFOCUSED_IDX; break;
};
color_type cell_fg = rd->default_fg, cell_bg = rd->default_bg;
index_type cell_color_x = cursor->x;
bool reversed = false;

View File

@@ -92,11 +92,10 @@ write_control_ch(Shlex *self) {
static void
read_valid_digits(Shlex *self, int max, char *output, bool(*is_valid)(Py_UCS4 ch)) {
for (int i = 0; i < max && self->src_pos < self->src_sz; i++) {
Py_UCS4 ch = PyUnicode_READ(self->kind, self->src_data, self->src_pos);
if (!is_valid(ch)) break;
output[0] = ch;
self->src_pos++; output++;
for (int i = 0; i < max && self->src_pos < self->src_sz; i++, output++) {
Py_UCS4 ch = read_ch(self);
if (!is_valid(ch)) { self->src_pos--; break; }
*output = ch;
}
}

View File

@@ -124,6 +124,8 @@ def find_testable_go_packages() -> tuple[set[str], dict[str, list[str]]]:
base = os.getcwd()
pat = re.compile(r'^func Test([A-Z]\w+)', re.MULTILINE)
for (dirpath, dirnames, filenames) in os.walk(base):
if 'b' in dirnames and os.path.basename(dirpath) == 'bypy':
dirnames.remove('b')
for f in filenames:
if f.endswith('_test.go'):
q = os.path.relpath(dirpath, base)

View File

@@ -27,7 +27,11 @@ func is_stream_response(serialized_response []byte) bool {
func do_chunked_io(io_data *rc_io_data) (serialized_response []byte, err error) {
serialized_response = make([]byte, 0)
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors)
// we cant do inbandresize notification as in the --no-response case the
// command can cause a resize and the loop can quit before the notification
// arrives, leading to the notification being sent to whatever is executed
// after us.
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoInBandResizeNotifications)
if io_data.on_key_event != nil {
lp.FullKeyboardProtocol()
} else {

View File

@@ -10,6 +10,7 @@ import (
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
@@ -362,11 +363,22 @@ func ReloadConfigInKitty(in_parent_only bool) error {
}
return nil
}
if all, err := process.Processes(); err == nil {
for _, p := range all {
if exe, eerr := p.Exe(); eerr == nil {
if c, err := p.CmdlineSlice(); err == nil && is_kitty_gui_cmdline(exe, c...) {
_ = p.SendSignal(unix.SIGUSR1)
// process.Processes() followed by filtering by getting the process
// exe and cmdline is very slow on non-Linux systems as CGO is not allowed
// which means getting exe works by calling lsof on every process. So instead do
// initial filtering based on ps output.
if ps_out, err := exec.Command("ps", "-x", "-o", "pid=,comm=").Output(); err == nil {
for _, line := range utils.Splitlines(utils.UnsafeBytesToString(ps_out)) {
line = strings.TrimSpace(line)
if pid_string, argv0, found := strings.Cut(line, " "); found {
if pid, err := strconv.Atoi(strings.TrimSpace(pid_string)); err == nil && strings.Contains(argv0, "kitty") {
if p, err := process.NewProcess(int32(pid)); err == nil {
if cmdline, err := p.CmdlineSlice(); err == nil {
if exe, err := p.Exe(); err == nil && is_kitty_gui_cmdline(exe, cmdline...) {
_ = p.SendSignal(unix.SIGUSR1)
}
}
}
}
}
}

View File

@@ -196,6 +196,10 @@ func NoRestoreColors(self *Loop) {
self.terminal_options.restore_colors = false
}
func NoInBandResizeNotifications(self *Loop) {
self.terminal_options.in_band_resize_notification = false
}
func (self *Loop) DeathSignalName() string {
if self.death_signal != SIGNULL {
return self.death_signal.String()

View File

@@ -26,6 +26,7 @@ func new_loop() *Loop {
l := Loop{controlling_term: nil}
l.terminal_options.Alternate_screen = true
l.terminal_options.restore_colors = true
l.terminal_options.in_band_resize_notification = true
l.terminal_options.kitty_keyboard_mode = DISAMBIGUATE_KEYS | REPORT_ALTERNATE_KEYS | REPORT_ALL_KEYS_AS_ESCAPE_CODES | REPORT_TEXT_WITH_KEYS
l.escape_code_parser.HandleCSI = l.handle_csi
l.escape_code_parser.HandleOSC = l.handle_osc

View File

@@ -100,6 +100,7 @@ type TerminalStateOptions struct {
Alternate_screen, restore_colors bool
mouse_tracking MouseTracking
kitty_keyboard_mode KeyboardStateBits
in_band_resize_notification bool
}
func set_modes(sb *strings.Builder, modes ...Mode) {
@@ -128,7 +129,10 @@ func (self *TerminalStateOptions) SetStateEscapeCodes() string {
reset_modes(&sb,
IRM, DECKM, DECSCNM, BRACKETED_PASTE, FOCUS_TRACKING,
MOUSE_BUTTON_TRACKING, MOUSE_MOTION_TRACKING, MOUSE_MOVE_TRACKING, MOUSE_UTF8_MODE, MOUSE_SGR_MODE)
set_modes(&sb, DECARM, DECAWM, DECTCEM, INBAND_RESIZE_NOTIFICATION)
set_modes(&sb, DECARM, DECAWM, DECTCEM)
if self.in_band_resize_notification {
set_modes(&sb, INBAND_RESIZE_NOTIFICATION)
}
if self.Alternate_screen {
set_modes(&sb, ALTERNATE_SCREEN)
sb.WriteString(CLEAR_SCREEN)

View File

@@ -49,13 +49,15 @@ with open(__file__, 'rb') as f:
script = f.read().decode('utf-8')
script = script[:script.find('# EOF_REMOTE')].replace('if False:', 'if True:', 1)
with tempfile.NamedTemporaryFile(prefix='install-dmg-', suffix='.py') as f:
cmd = 'python ../bypy macos program --dont-strip'
cmd = 'python ../bypy macos program'
if 'dont_sign' not in sys.argv:
cmd += ' --sign-installers'
if 'notarize' in sys.argv:
cmd += ' --sign-installers --notarize'
if 'strip' not in sys.argv:
cmd += ' --dont-strip'
if 'tests' not in sys.argv:
cmd += ' --skip-tests'
if 'notarize' in sys.argv:
cmd += ' --sign-installers --notarize'
run(cmd)
f.write(script.encode('utf-8'))
f.flush()