Compare commits

...

1546 Commits

Author SHA1 Message Date
129186761c Update patches from https://github.com/KittyPatch/kitty to work on current kitty 2023-05-12 21:06:00 -07:00
Kovid Goyal
491297ea1d
When asking for permission to exec a shebang script also add options to view or edit the script 2023-05-12 16:02:47 +05:30
Kovid Goyal
c101a6acb0
Implement a dedicated function for word matching rather than relying on a regex and being at the mercy of the vagaries of regex implementations 2023-05-12 15:43:56 +05:30
Kovid Goyal
65f8bb7397
hints kitten: Switch to using a regex engine that supports lookaround
Note that we loose unicode char matching for --type=word because of
https://github.com/dlclark/regexp2/issues/65 and of course user regexps
cant use \p{N} escapes any more. Hopefully regexp2 will add support for
these soon-ish. IMO lookaround is more important than \p.

Fixes #6265
2023-05-12 12:24:59 +05:30
Kovid Goyal
5b8b91b6a3
Add support for OSC 1337 SetUserVar
See https://github.com/kovidgoyal/kitty/discussions/6229
2023-05-11 17:57:45 +05:30
Kovid Goyal
6a2edfa847
Merge branch 'pr-fix-shade' of https://github.com/MithicSpirit/kitty 2023-05-10 09:56:59 +05:30
MithicSpirit
28b84a2d5b
Add support for 0x1fb90
Allocation in box_glyph_id is larger than necessary to account for the
addition of 0x1fb8c ... 0x1fb94 eventually, which are quite similar but
will require more work to add. Note that 0x1fb93 is not present in the
standard yet, but it is easy to guess what it will likely be from
context, so it should be kept in the allocation imo.
2023-05-09 22:19:03 -04:00
MithicSpirit
c247fe2336
Revert "Improve shade character appearance"
This reverts commit c883a024ba2a58533fb5bea021fe6b3d2dfb11a2.

To maximize compatibility with the appearance in the standard.
2023-05-09 22:06:05 -04:00
MithicSpirit
c883a024ba
Improve shade character appearance
I was really unhappy with the previous checkerboard appearance, so I
changed it to supersampled diagonal lines. The fill ratios are still the
same, so it should still be compliant with the standard if I understood
it correctly.

Feel free to revert (or tell me to revert) this commit if you want the
previous look.
2023-05-09 16:08:02 -04:00
Kovid Goyal
0cc38e1086
... 2023-05-09 09:50:11 +05:30
Kovid Goyal
1777b87c45
Improve docs for reset the terminal 2023-05-09 09:44:05 +05:30
Kovid Goyal
e72975cc98
A new escape code that moves the current contents of the screen into the scrollback before clearing it 2023-05-09 09:32:39 +05:30
Kovid Goyal
8f15654985
Ensure kitty is rebuilt after publishing the nightly 2023-05-09 08:54:29 +05:30
Kovid Goyal
2408ccb635
... 2023-05-09 08:48:37 +05:30
Kovid Goyal
a0cf4214df
... 2023-05-09 08:44:51 +05:30
Kovid Goyal
07203c67ca
Add a note about why kitty terminfo does not have E3
See #6255
2023-05-09 08:28:54 +05:30
MithicSpirit
a36fe45181
Fix shade characters to follow unicode standard
- Light shade: 25% fill
- Medium shade: 50% fill
- Dark shade: 75% fill (implemented as inverse of light shade)
2023-05-08 18:46:24 -04:00
Kovid Goyal
061c444f20
... 2023-05-08 16:36:47 +05:30
Kovid Goyal
a1d791083b
ssh_kitten: Proper exit code for termination by SIGINT 2023-05-08 16:27:07 +05:30
Kovid Goyal
454acd4f5c
ssh kitten: Fix a regression in 0.28.0 that caused interrupt during setup to not be handled gracefully
Fixes #6254
2023-05-08 16:18:05 +05:30
Kovid Goyal
71189aee9f
Correct the type signature for callback 2023-05-08 16:03:27 +05:30
Kovid Goyal
23d7494e3a
Fix #6251 2023-05-08 08:04:20 +05:30
Kovid Goyal
404f83a277
Add a link to awrit in the integrations page 2023-05-07 10:06:37 +05:30
Kovid Goyal
474244268c
edit-in-kitty: Fix running edit-in-kitty with elevated privileges to edit a restricted file not working 2023-05-07 09:36:16 +05:30
Kovid Goyal
79cd6f38fe
... 2023-05-07 09:24:30 +05:30
Kovid Goyal
b7c3946f8f
... 2023-05-07 08:13:57 +05:30
Kovid Goyal
537cabca71
kitty +open: Ask for permission before executing script files that are not marked as executable
This prevents accidental execution of script files via MIME type
association from programs that unconditionally "open"
attachments/downloaded files via MIME type associations.
2023-05-07 08:11:39 +05:30
Kovid Goyal
79c19562b5
When publishing stash untracked files as well 2023-05-07 07:42:25 +05:30
Kovid Goyal
52afc79476
Fix re-using an image id for an animated image for a still image causing a crash
Fixes #6244
2023-05-06 09:37:55 +05:30
Kovid Goyal
877d8d7008
... 2023-05-04 10:36:02 +05:30
Kovid Goyal
ce70320a62
... 2023-05-04 10:26:18 +05:30
Kovid Goyal
3eb18a416a
Entry point for parsing theme metadata 2023-05-04 10:14:58 +05:30
Kovid Goyal
8ba7258db9
Merge branch 'fix-bash-intergration-var-leak' of https://github.com/syyyr/kitty 2023-05-04 08:05:33 +05:30
Václav Kubernát
a502e94950 bash_integration: Do not leak variable i
With shell-integration, the user would see the last value of this
variable (as set by the shell-integration script.

Fix this by making it local.
2023-05-03 18:35:30 +02:00
Kovid Goyal
ea5634b3fd
When parsing theme metadata ignore the name if it is the placeholder value from the template 2023-05-03 21:55:33 +05:30
Kovid Goyal
87943079fb
Fix #6238 2023-05-03 21:40:42 +05:30
Kovid Goyal
a77b2b20c2
Fix #6230 2023-05-03 18:25:07 +05:30
Kovid Goyal
8f96395f74
diff kitten: Fix a regression in 0.28.0 that broke using relative paths as arguments to the kitten
Fixes #6235
2023-05-03 08:34:46 +05:30
Kovid Goyal
1fc4e53bea
hints kitten: Fix a regression in 0.28.0 that broke using sub-groups in regexp captures
Fixes #6228
2023-04-30 21:16:24 +05:30
Kovid Goyal
f6ccd2ad2c
Dont apply linear2srgb in borders with bg image as the cell shader doesnt apply it then either 2023-04-30 10:19:35 +05:30
Kovid Goyal
bc2af4acf9
Update changelog 2023-04-30 09:09:09 +05:30
Kovid Goyal
07dbfaa297
Fix #6224 2023-04-30 08:28:02 +05:30
Kovid Goyal
8020d5823b
Fix #6225 2023-04-30 07:15:56 +05:30
Kovid Goyal
73f10aaf43
clipboard kitten: Fix a bug causing the last MIME type available on the clipboard not being recognized when pasting with arbitrary MIME types 2023-04-30 06:48:09 +05:30
Kovid Goyal
59c4d4a4bd
DRYer 2023-04-28 20:30:15 +05:30
Kovid Goyal
ef999c9024
Also show stderr from tmux on failure 2023-04-28 20:16:37 +05:30
Kovid Goyal
514888a274
Use FindExe to find the tmux executable and return a nicer error message when running tmux fails 2023-04-28 20:11:15 +05:30
Kovid Goyal
09ebdcd809
Allow using set_tab_title without a pre-filled title. Fixes #6217 2023-04-28 10:14:25 +05:30
Kovid Goyal
8ebe4084cc
Merge branch 'fix/6209-background_opacity_fringing' of https://github.com/m4rw3r/kitty 2023-04-28 09:28:09 +05:30
Martin Wernstål
9f41183628 fix: account for incorrect gamma-blending performed by compositor on transparent windows
Fixes #6209
2023-04-27 18:35:06 +02:00
Martin Wernstål
289957ef1c style: use ifdef to be consistent with the other cases 2023-04-27 18:34:00 +02:00
Martin Wernstål
920b350ac9 feat: more exact sRGB approximation 2023-04-27 18:27:46 +02:00
Kovid Goyal
d14655f644
Merge pull request #6216 from jaseg/master
docs/basic.rst: Add resize window shortcut
2023-04-27 16:25:03 +05:30
jaseg
29583411e6
docs/basic.rst: Add resize window shortcut 2023-04-27 12:48:05 +02:00
Kovid Goyal
019359b219
show_key kitten: In kitty mode show the actual bytes sent by the terminal rather than a re-encoding of the parsed key event
Also port the kitten to Go
2023-04-26 21:48:53 +05:30
Kovid Goyal
7b6d11fd1e
Fix rendering of :doc: links with explicit titles in help text in the terminal 2023-04-26 16:46:20 +05:30
Kovid Goyal
bb33c66570
Fix #6213 2023-04-26 16:38:25 +05:30
Kovid Goyal
c2fc4eadc8
unicode_input: Only serialize favorites if no user config exists 2023-04-26 16:02:18 +05:30
Kovid Goyal
a7b4d07601
unicode_input kitten: Fix a regression in 0.28.0 that caused the order of recent and favorites entries to not be respected
Fixes #6214
2023-04-26 15:55:56 +05:30
Kovid Goyal
6a07435bb0
hints kitten: Fix regression causing editing of favorites to sometimes hang 2023-04-26 15:23:38 +05:30
Kovid Goyal
93a5107e79
Fix #6202 2023-04-21 21:35:59 +05:30
Kovid Goyal
6cc8e67580
Add example code to get screen size in Bash 2023-04-21 15:18:30 +05:30
Kovid Goyal
ccdb951716
Website: Fix optimization of social preview images 2023-04-21 14:19:36 +05:30
Kovid Goyal
07bcc5ba61
version 0.28.1 2023-04-21 13:10:01 +05:30
Kovid Goyal
6e90bc1996
... 2023-04-20 21:48:07 +05:30
Kovid Goyal
6269f78ed2
Make it clearer that exclude operates only on directories 2023-04-18 09:22:34 +05:30
Kovid Goyal
dd0e1cce9e
Bump versions of various go deps 2023-04-18 09:13:08 +05:30
Kovid Goyal
92e68a6e0c
Fix #6193 2023-04-18 09:05:28 +05:30
Kovid Goyal
e4baca6d97
Emphasize that names of custom theme conf files must actual builtin theme names to override them 2023-04-17 08:47:26 +05:30
Kovid Goyal
a09464dee9
Fix a regression in the previous release that broke usage of custom themes
Fixes #6191
2023-04-17 08:45:46 +05:30
Kovid Goyal
b966013a2b
Make Samefile interface a bit nicer for working with paths 2023-04-17 08:35:50 +05:30
Kovid Goyal
046fbb860b
themes kitten: ignore custom theme files if they are stdout 2023-04-17 08:02:41 +05:30
Kovid Goyal
91700b3e42
Fix a bug in the Go code of the CSI key event parser
Fixes #6189
2023-04-16 15:31:56 +05:30
Kovid Goyal
b314303787
pep8 2023-04-16 15:31:03 +05:30
Kovid Goyal
176cfe771c
Merge branch 'void_functions' of https://github.com/derekschrock/kitty 2023-04-16 11:06:35 +05:30
Derek Schrock
3b57acf03c More cases of #5477 functions with empty argument lists
Building on macOS 13.3.1 (22E261) clang 14.0.3 (clang-1403.0.22.14.1)
running to errors like #5477 where functions without argument lists at
least need void.

Looking for possible suspect functions via:

  git grep -E "^([A-Za-z_]+ )?[A-Za-z_]+\()" \*.c \*.m
2023-04-16 01:09:36 -04:00
Kovid Goyal
77e2572c5a
Optimize social preview images before publishing website 2023-04-15 21:49:32 +05:30
Kovid Goyal
39eff0fe8c
Fix a regression in the previous release that broke the remote file kitten
Fixes #6186
2023-04-15 21:04:30 +05:30
Kovid Goyal
12efff6d08
Fix #6185 2023-04-15 20:43:58 +05:30
Kovid Goyal
b81f457e9b
version 0.28.0 2023-04-15 11:17:36 +05:30
Kovid Goyal
35ebd32f4c
Merge branch 'fix-iplot-heredoc' of https://github.com/zaidhaan/kitty 2023-04-15 08:26:06 +05:30
Zaidhaan Hussain
63fff29621 Docs: fix heredoc issue in iplot snippet 2023-04-15 06:44:11 +08:00
Kovid Goyal
2f63f24e7d
log system color scheme changes 2023-04-13 13:29:03 +05:30
Kovid Goyal
66801b6b28
GLFW API to track system color scheme dark/light
Implemented only on macOS and Wayland.
2023-04-13 13:16:33 +05:30
Kovid Goyal
1392d8cdb7
Merge branch 'master' of https://github.com/Nogesma/kitty 2023-04-11 19:36:15 +05:30
Mano Ségransan
0d2a27968b
Add twitch-tui to the list of program that use the kitty graphics protocol 2023-04-11 15:25:32 +02:00
Kovid Goyal
912dcc0a6e
Nicer error message when the version of go on the system is too old 2023-04-10 11:31:53 +05:30
Kovid Goyal
d4c5b8c899
Keyboard input: Fix text not being reported as unicode codepoints for multi-byte characters in the kitty keyboard protocol
Fixes #6167
2023-04-09 22:57:40 +05:30
Kovid Goyal
6aa2a7f99d
... 2023-04-09 09:08:34 +05:30
Kovid Goyal
f250a93715
Fix #6165 2023-04-09 08:48:56 +05:30
Kovid Goyal
373c05943f
Allow specifying full layout specifications with options for goto_layout
Fixes #6163
2023-04-08 13:35:38 +05:30
Kovid Goyal
d9d2e31318
Another place where [:max_length] is used without checking 2023-04-07 18:08:38 +05:30
Kovid Goyal
3f943998c6
Note that the kitty keyboard protocol can be used in emacs 2023-04-07 08:22:33 +05:30
Kovid Goyal
1dd3490611
Fix #6160 2023-04-06 15:14:21 +05:30
Kovid Goyal
7803b07e7f
Ignore leading and trailing space around values when parsing config lines 2023-04-06 10:45:34 +05:30
Kovid Goyal
feb5da70a8
Clean up changelog a bit 2023-04-05 21:12:06 +05:30
Kovid Goyal
c3246051d4
... 2023-04-05 18:08:58 +05:30
Kovid Goyal
912aa17594
... 2023-04-05 08:08:54 +05:30
Kovid Goyal
708267d229
Fix parsing of actions in map directives in Go 2023-04-05 07:55:18 +05:30
Kovid Goyal
3ee77a3a57
Fix #6154 2023-04-04 21:18:27 +05:30
Kovid Goyal
6dcc7ad0c7
Add a HOWTO for adjusting text_composition_strategy 2023-04-03 17:40:15 +05:30
Kovid Goyal
e07f2df8d0
Fix rendering of file added/removed lines 2023-04-03 11:07:51 +05:30
Kovid Goyal
bca67cde6f
Fix default for syntax_aliases not being respected 2023-04-02 15:07:41 +05:30
Kovid Goyal
dfa41f01fd
Fix panic caused by incorrectly constructed empty line
Also be more defensive in draw_screen() about rendering lines.
2023-04-02 10:18:23 +05:30
Kovid Goyal
dae49d788e
... 2023-04-01 10:51:32 +05:30
Kovid Goyal
1b67fd2ec0
Merge branch 'patch-1' of https://github.com/carlmjohnson/kitty 2023-04-01 07:29:48 +05:30
Carl Johnson
0afcf5a26b
keyboard-protocol.rst: Add Helix 2023-03-31 14:07:09 -04:00
Kovid Goyal
e0cdc26e68
Fix placement of images in diff broken by new render layout 2023-03-30 11:21:28 +05:30
Kovid Goyal
e73282ceb0
Only send graphics protocol commands if there are actual images to diff 2023-03-30 11:06:44 +05:30
Kovid Goyal
9919767aef
Remove unused code 2023-03-30 10:26:39 +05:30
Kovid Goyal
57ef0e29c0
Wait for keypress on panic in alternate screen kittens 2023-03-30 08:26:45 +05:30
Kovid Goyal
c767f7b57f
... 2023-03-30 07:58:00 +05:30
Kovid Goyal
fa094b2697
Update changelog 2023-03-30 07:24:12 +05:30
Kovid Goyal
3da2a3f60f
Fix table alignment in docs 2023-03-29 21:36:31 +05:30
Kovid Goyal
266746c96e
Implement the trim_whitespace option
Needed for help text formatting
2023-03-29 21:28:47 +05:30
Kovid Goyal
34526517de
Allow passing multiple options to control how wrapping is done 2023-03-29 20:56:24 +05:30
Kovid Goyal
cb99fbd83c
Dont remove leading and trailing spaces when wrapping
Without this we lose some spaces and also there was a case where the
line could end up longer than the specified width.
2023-03-29 20:47:31 +05:30
Kovid Goyal
7169a89591
Add shortcuts for copying to clipboard 2023-03-29 19:56:08 +05:30
Kovid Goyal
37edc728a9
Implement drag scrolling for the diff kitten 2023-03-29 17:14:13 +05:30
Kovid Goyal
05e10d8066
Also parse negative numbers in CSI 2023-03-29 15:12:22 +05:30
Kovid Goyal
aebfdaa69a
Refactor diff mouse selection to use new render layout 2023-03-29 14:32:36 +05:30
Kovid Goyal
468168b9de
Refactor diff search to use new render layout 2023-03-29 13:22:34 +05:30
Kovid Goyal
3dbb830a0e
Refactor diff rendering
Dont store full rendered lines, instead fill them up at actual draw
time. Makes implementing mouse selection and searching more robust.
2023-03-29 11:55:03 +05:30
Kovid Goyal
e095a2ab43
Fix #6142 2023-03-28 21:06:39 +05:30
Kovid Goyal
7ed7e82637
Use a filler char other than space 2023-03-28 18:01:04 +05:30
Kovid Goyal
67a9def013
Get copy to primary selection working 2023-03-28 17:15:28 +05:30
Kovid Goyal
676f576ace
Adjust the bounds of the mouse selection taking starting half cell into account 2023-03-28 15:12:41 +05:30
Kovid Goyal
8867818dfe
DRYer 2023-03-28 11:55:08 +05:30
Kovid Goyal
00d4841304
Make the mouse selection code re-useable 2023-03-28 11:48:22 +05:30
Kovid Goyal
277dea647e
More work on mouse selection 2023-03-28 10:29:45 +05:30
Kovid Goyal
45c1e36de9
More work on mouse selection 2023-03-28 08:10:29 +05:30
Kovid Goyal
40ca46d8d8
Fix default generation for nullable colors 2023-03-28 08:09:37 +05:30
Kovid Goyal
0f59a2d543
Fix DECCARA in non-rectangular mode for a single line 2023-03-28 08:02:44 +05:30
Kovid Goyal
d19f28f2b4
More work on mouse selection in the diff kitten 2023-03-27 21:23:31 +05:30
Kovid Goyal
94db6053d5
Turn off atomic update during direct transmission 2023-03-27 20:54:03 +05:30
Kovid Goyal
80204c6056
Use join_half_lines in a few more places 2023-03-27 18:01:53 +05:30
Kovid Goyal
d33b83e6ea
More work on mouse selections 2023-03-27 17:56:00 +05:30
Kovid Goyal
a22933afbc
DRYer 2023-03-27 17:19:13 +05:30
Kovid Goyal
840caf5fd5
Start work on mouse handling in diff kitten 2023-03-27 17:06:56 +05:30
Kovid Goyal
6dfe823dfb
... 2023-03-27 17:05:57 +05:30
Kovid Goyal
71580a2a93
Fix wheel event detection 2023-03-27 16:35:29 +05:30
Kovid Goyal
e85473cee6
Linux Wayland: Fix animated images not being animated continuously
Fixes #6126
2023-03-27 13:43:37 +05:30
Kovid Goyal
6504dd15c1
Update folder README 2023-03-27 13:20:10 +05:30
Kovid Goyal
ff55121094
Move the kittens Go code into the kittens folder 2023-03-27 13:06:02 +05:30
Kovid Goyal
3f9579d61d
Port the removed walk test to Go 2023-03-27 12:34:31 +05:30
Kovid Goyal
a2aadd4756
Remove python diff tests as no longer needed 2023-03-27 11:54:34 +05:30
Kovid Goyal
70fd89caac
... 2023-03-27 11:49:11 +05:30
Kovid Goyal
d30091034a
Remove the python diff kitten 2023-03-27 11:46:22 +05:30
Kovid Goyal
fb9d95038d
Free images in kitty when quitting diff kitten 2023-03-27 11:13:04 +05:30
Kovid Goyal
a3f1d3e132
Get image display working 2023-03-27 11:00:21 +05:30
Kovid Goyal
9cc54978e6
Fix margin formatting for binary lines 2023-03-27 08:23:10 +05:30
Kovid Goyal
d66da811db
More work on getting images to display in diff 2023-03-27 07:53:57 +05:30
Kovid Goyal
cece795b16
More work on image support for diff 2023-03-27 07:53:57 +05:30
Kovid Goyal
9eedcc1d2a
Better struct name 2023-03-27 07:53:57 +05:30
Kovid Goyal
508a61bd1c
More work on diffing images 2023-03-27 07:53:57 +05:30
Kovid Goyal
c745961f47
Nicer error messages for failure to load with Magick 2023-03-27 07:53:57 +05:30
Kovid Goyal
be886f9bf9
Make code for loading images with ImageMagick re-useable 2023-03-27 07:53:57 +05:30
Kovid Goyal
404a775f4b
Start work on image support for new diff kitten 2023-03-27 07:53:57 +05:30
Kovid Goyal
18445e20ff
... 2023-03-27 07:53:57 +05:30
Kovid Goyal
7b16132b75
Fix searching in full title lines 2023-03-27 07:53:57 +05:30
Kovid Goyal
0a8fc3f17c
... 2023-03-27 07:53:57 +05:30
Kovid Goyal
d57e47349b
Make searches case insensitive 2023-03-27 07:53:57 +05:30
Kovid Goyal
ccf1dfabbc
Fix highlighting of center changes 2023-03-27 07:53:56 +05:30
Kovid Goyal
de9edb6ff5
Manually specify the closing SGR for a span 2023-03-27 07:53:56 +05:30
Kovid Goyal
6590be84a2
... 2023-03-27 07:53:56 +05:30
Kovid Goyal
ccfae228b9
Avoid panics while rendering 2023-03-27 07:53:56 +05:30
Kovid Goyal
3236a42cb7
... 2023-03-27 07:53:56 +05:30
Kovid Goyal
e774deaef1
Fix tabs and carriage returns being incorrectly sanitized 2023-03-27 07:53:56 +05:30
Kovid Goyal
b5c2d85837
Fix diffing dirs 2023-03-27 07:53:56 +05:30
Kovid Goyal
2d18529d05
Show a message for identical files 2023-03-27 07:53:56 +05:30
Kovid Goyal
2ac170c1b1
Allowing using the anchored diff from the Go stdlib as the diff implementation 2023-03-27 07:53:56 +05:30
Kovid Goyal
9c188096d0
Prevent panics incase highlighting leads to different number of lines 2023-03-27 07:53:56 +05:30
Kovid Goyal
09c6a68804
Fix syntax highlighting of multiline tokens 2023-03-27 07:53:56 +05:30
Kovid Goyal
4c9efb6ff2
Fix bold/dim handling when wrapping 2023-03-27 07:53:56 +05:30
Kovid Goyal
4bc9cf84a3
Micro-optimization 2023-03-27 07:53:56 +05:30
Kovid Goyal
14b58ba015
Fix overrides not being parsed correctly 2023-03-27 07:53:56 +05:30
Kovid Goyal
29a896f9d8
... 2023-03-27 07:53:56 +05:30
Kovid Goyal
f8c83519fe
Reset styles after half lines 2023-03-27 07:53:56 +05:30
Kovid Goyal
91eaa89b3e
Fix various off-by-ones in the search code 2023-03-27 07:53:55 +05:30
Kovid Goyal
1926db8ee8
Correct cursor shape when inputting search query 2023-03-27 07:53:55 +05:30
Kovid Goyal
c19c614d9e
DRYer 2023-03-27 07:53:55 +05:30
Kovid Goyal
f7f6df675f
Implement searching the diff 2023-03-27 07:53:55 +05:30
Kovid Goyal
88bd3ee9ca
New SGR codes to turn off bold/dim independently
Allows for robust patching of formatting into already formatted
text. Without this it is not possible to turn off bold without
affecting existing dim and vice versa.
2023-03-27 07:53:55 +05:30
Kovid Goyal
e46a7c39c3
Fix failing test 2023-03-27 07:53:55 +05:30
Kovid Goyal
5086c62a81
Implement changing of context lines 2023-03-27 07:53:55 +05:30
Kovid Goyal
15b0dbb71c
Code to insert SGR formatting into already formatted strings 2023-03-27 07:53:55 +05:30
Kovid Goyal
2a185575b2
Implement drawing of status bar 2023-03-27 07:53:55 +05:30
Kovid Goyal
cf5ea96126
Ensure scroll position is correct after resize 2023-03-27 07:53:55 +05:30
Kovid Goyal
e2edacb629
DRYer 2023-03-27 07:53:55 +05:30
Kovid Goyal
c2e549b79c
Implement syntax highlighting 2023-03-27 07:53:55 +05:30
Kovid Goyal
4d61ad87b3
Implement jumping to fixed locations 2023-03-27 07:53:55 +05:30
Kovid Goyal
2905744dad
Implement scrolling by lines 2023-03-27 07:53:55 +05:30
Kovid Goyal
ebcf85428c
More work on porting diff kitten 2023-03-27 07:53:55 +05:30
Kovid Goyal
425ab4f6d8
Start implementing shortcut handling 2023-03-27 07:53:55 +05:30
Kovid Goyal
924cd4cadd
Do not add a trailing newline when wrapping 2023-03-27 07:53:55 +05:30
Kovid Goyal
e42b4fd9a6
Decrease allocs when wrapping 2023-03-27 07:53:54 +05:30
Kovid Goyal
18b58c5cf9
Ensure wrapping never results in lines longer than the specified word 2023-03-27 07:53:54 +05:30
Kovid Goyal
6c503985ce
Dont run gen-config for diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
648925e83a
More work on porting diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
1c7d1094d4
More work on porting diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
4f5fc1000d
Allow multiple specifications of kwds,ext,mime in completion specs 2023-03-27 07:53:54 +05:30
Kovid Goyal
41ea5f0c63
Ensure unique image id in single session 2023-03-27 07:53:54 +05:30
Kovid Goyal
ef7f13d893
title lines are now displayed 2023-03-27 07:53:54 +05:30
Kovid Goyal
5d8b5ab720
More work on porting diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
ee82cb5a52
More work on porting diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
e4d936b5ed
More work on porting the diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
293c0ab845
More work on porting the diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
bf1f0c00f4
Port full MIME type guessing to Go 2023-03-27 07:53:54 +05:30
Kovid Goyal
3c550bcd28
More work on porting diff kitten 2023-03-27 07:53:54 +05:30
Kovid Goyal
d208670172
Abstract typical config file loading with path and cli overrides 2023-03-27 07:53:54 +05:30
Kovid Goyal
5329546f21
Implement parsing of map 2023-03-27 07:53:54 +05:30
Kovid Goyal
e4fbcb707f
Add lua mime type as a known text mime type 2023-03-27 07:53:54 +05:30
Kovid Goyal
44ff6bd1dd
Start work on porting diff kitten 2023-03-27 07:53:53 +05:30
Kovid Goyal
cb03168957
Merge branch 'patch-1' of https://github.com/piorrro33/kitty 2023-03-27 07:51:56 +05:30
Pierre GRASSER
ce7741c9a8
bootstrap-utils.sh: make grep silent
Prevents a print of "no-rc".
2023-03-26 20:31:37 +02:00
Kovid Goyal
5ff1dadf0d
Allow using --session=none to override startup_session
Fixes #6131
2023-03-25 10:44:34 +05:30
Kovid Goyal
f046884f23
Allow stopping of URL detection at newlines via url_excluded_characters
Fixes #6122
2023-03-21 08:04:42 +05:30
Kovid Goyal
856fddec3c
Tall/fat layout: When changing the number of full size windows, reset the main axis biases. Fixes #6123 2023-03-20 22:36:18 +05:30
Kovid Goyal
f61ddd62d1
Allow specifying an optional integer argument for next_layout. Fixes #6121 2023-03-20 19:49:37 +05:30
Kovid Goyal
1bed92bed1
Cleanup previous PR 2023-03-20 07:42:10 +05:30
Kovid Goyal
122ba17df6
Merge branch 'patch/getpwuid' of https://github.com/usertam/kitty 2023-03-20 07:37:27 +05:30
usertam
08fa7f19f7
kitty_tests, shell-integration: rework getpwuid() exceptions suppression 2023-03-20 03:31:23 +08:00
Kovid Goyal
5f9b520ca0
Bash integration: Dont fail if the user enabled failglob in their bashrc
BASH is by *far* the most buggy and least featureful of the three shells.
Fix #6119
2023-03-19 21:05:29 +05:30
Kovid Goyal
47d7e812a3
Cleanup previous PR 2023-03-19 17:20:09 +05:30
Kovid Goyal
9a8e92fade
Merge branch 'patch/getpwuid' of https://github.com/usertam/kitty 2023-03-19 17:18:29 +05:30
Samuel Tam
8a7491722f
shell-integration/ssh/bootstrap.py: suppress getpwuid() exceptions
Reference: 89e5ae28bb60d5bf3aaadf25d62ea0864e5136bb
2023-03-19 19:28:24 +08:00
Samuel Tam
31319f0b65
kitty_tests/ssh.py: skip login shell detection if getpwuid() fails 2023-03-19 18:45:47 +08:00
Kovid Goyal
fda2646dd3
Cleanup previous PR 2023-03-19 10:37:37 +05:30
Kovid Goyal
14dcf38e51
Merge branch 'xdg-sound-theme-option' of https://github.com/serebit/kitty 2023-03-19 10:20:06 +05:30
Kovid Goyal
e633677749
Run make debug before building static binaries
Ensures all deps are built in case make clean was run.
2023-03-19 09:51:57 +05:30
Campbell Jones
55fd885491
Add option to set XDG sound theme on Linux 2023-03-18 16:38:29 -04:00
Kovid Goyal
073b47a236
Revert #6114
Frozen kitty builds dont have python files (they are loaded from a
single mmmaped archive), so the test will prevent any
kittens from being found.

Have make clean remove leftover kittens directories
2023-03-18 15:26:33 +05:30
Kovid Goyal
bf773351ed
DRYer 2023-03-17 11:00:00 +05:30
Kovid Goyal
509a45b579
Dont request release events for most kittens
They are not needed and there is always a small risk that a release
event could be delivered after the kitten has stopped reading from the
tty, thereby leaking into the environment.
2023-03-17 10:50:10 +05:30
Kovid Goyal
de74b93b16
Update icon link 2023-03-17 09:19:11 +05:30
Kovid Goyal
e4611d0c81
... 2023-03-17 09:02:58 +05:30
Kovid Goyal
b0a4b932ad
... 2023-03-17 08:59:45 +05:30
Kovid Goyal
f7b735d5ab
ssh kitten: Fix failure when remote system has no base64 but does have openssl 2023-03-17 08:36:52 +05:30
Kovid Goyal
c8fe0712e6
Merge branch 'ccm/fix-uname-arch-freebsd' of https://github.com/chazmcgarvey/kitty 2023-03-16 07:53:40 +05:30
Charles McGarvey
4b818244be Add "amd64" as a potential value for "uname -m"
This accommodates FreeBSD and perhaps others.
2023-03-15 19:05:30 -06:00
Kovid Goyal
99463ef492
Merge branch 'fix-build' of https://github.com/page-down/kitty 2023-03-16 06:12:30 +05:30
pagedown
97ef09b633
Fix empty folders being considered as kitten
When pulling a git commit that contains delete folder actions, the local
folders will not be deleted.
2023-03-16 08:20:05 +08:00
Kovid Goyal
e2fda5d1c4
... 2023-03-15 15:32:04 +05:30
Kovid Goyal
da38cb3254
Add support for more option types to Go conf file parsing 2023-03-15 15:17:38 +05:30
Kovid Goyal
3803d7e3c2
Use maps package for generic keys/values functions 2023-03-14 22:49:40 +05:30
Kovid Goyal
7ce83e7fd0
Use the generic contains/index from slices instead of our custom one 2023-03-14 22:40:20 +05:30
Kovid Goyal
5520a75bba
Dont rely on filesystem mtimes for test as they can be flaky 2023-03-14 21:13:14 +05:30
Kovid Goyal
e539035639
more useful test failure messages 2023-03-14 21:06:57 +05:30
Kovid Goyal
290b868193
forgot to close zip file 2023-03-14 20:42:36 +05:30
Kovid Goyal
c19ac531cf
Fix some failing tests 2023-03-14 20:40:12 +05:30
Kovid Goyal
f6d66b2336
... 2023-03-14 20:35:31 +05:30
Kovid Goyal
9443b0e361
Remove themes python code 2023-03-14 20:28:45 +05:30
Kovid Goyal
0805330b77
Finish port of themes kitten to Go 2023-03-14 20:24:21 +05:30
Kovid Goyal
0c20a4d980
Fix sort with key implementations 2023-03-14 12:54:35 +05:30
Kovid Goyal
21954937fb
More work on porting themes 2023-03-14 12:29:44 +05:30
Kovid Goyal
c4731771ac
Make style cache thread safe 2023-03-14 12:29:44 +05:30
Kovid Goyal
ffb3b073d7
Convenient loop API to print styled strings 2023-03-14 12:29:44 +05:30
Kovid Goyal
6794ec1de7
Wire up the new subseq match code 2023-03-14 12:29:44 +05:30
Kovid Goyal
29dd2438c9
Port the subseq matcher to Go 2023-03-14 12:29:44 +05:30
Kovid Goyal
b088ab91cf
Make code to convert rune offsets to byte offsets re-useable 2023-03-14 12:29:44 +05:30
Kovid Goyal
dd783c842f
More work on porting themes UI to Go 2023-03-14 12:29:44 +05:30
Kovid Goyal
f9b0b54ee5
Start work on porting themes kitten to Go 2023-03-14 12:29:44 +05:30
Kovid Goyal
3741d3d1be
hints: fix select by word broken while porting to Go 2023-03-14 12:27:33 +05:30
Kovid Goyal
c0c0fd8ac1
Merge branch 'fix-typo' of https://github.com/page-down/kitty 2023-03-14 12:20:35 +05:30
pagedown
2416122647
... 2023-03-14 14:30:11 +08:00
Kovid Goyal
626637c2ba
Merge branch 'icons' of https://github.com/eccentric-j/kitty 2023-03-12 12:09:00 +05:30
Jay
5d90544c9d Updated faq with optimized alt icon preview urls 2023-03-12 01:27:34 -05:00
Kovid Goyal
dad9cfdf38
Merge branch 'icons' of https://github.com/eccentric-j/kitty 2023-03-12 11:03:31 +05:30
Jay
bea6fdc72e
Added new icons 2023-03-11 19:06:01 -05:00
Kovid Goyal
74c5692b78
Default permission for atomicupdate should be 0644 2023-03-11 10:04:43 +05:30
Kovid Goyal
83f25cd361
Fix #6105 2023-03-11 07:21:43 +05:30
Kovid Goyal
7acc6bdeb8
Move splitlines_like_git to a more appropriate home 2023-03-10 17:26:06 +05:30
Kovid Goyal
ffa8c1c498
Add debug print for focus change events 2023-03-10 17:09:11 +05:30
Kovid Goyal
34cbf5ceac
Get rid of prewarming
Don't need it anymore since all major UI kittens are ported to Go
and so don't have startup latency.
2023-03-10 13:22:10 +05:30
Kovid Goyal
48e7ebb838
make gofmt happy 2023-03-10 13:03:51 +05:30
Kovid Goyal
7f6ed72684
Nicer error message when custom processor produces invalid marks 2023-03-10 12:51:32 +05:30
Kovid Goyal
e78c398243
Fix offsets incorrect for non-ASCII chars when using custom processing
python gives us offsets in unicode characters. Go uses offsets in utf8
bytes. Translate.
2023-03-10 12:41:56 +05:30
Kovid Goyal
b76b0c61ed
Port custom processor for hints 2023-03-10 10:45:37 +05:30
Kovid Goyal
69916ca4e8
Remove python implementation of hints 2023-03-10 07:16:25 +05:30
Kovid Goyal
2e1eebd998
More work on porting hints 2023-03-10 06:58:10 +05:30
Kovid Goyal
5b3f5dd02d
Port all remaining hints matching tests 2023-03-09 20:53:46 +05:30
Kovid Goyal
0e5ed29d83
Fix generation of url regex for Go 2023-03-09 19:00:56 +05:30
Kovid Goyal
2aa9187428
More work on porting hints 2023-03-09 19:00:56 +05:30
Kovid Goyal
09ceb3c0be
Start work on porting hints kitten to Go 2023-03-09 19:00:56 +05:30
Kovid Goyal
bcd3802d3e
Merge branch 'refactor' of https://github.com/page-down/kitty 2023-03-09 19:00:29 +05:30
pagedown
6c182a00a8
fish integration: Remove newlines from the data in __ksi_transmit_data
Moving the operation of removing whitespace characters to the function
that transmits the data. This matches the implementation in zsh and bash
integration scripts.
2023-03-09 21:10:08 +08:00
Kovid Goyal
88443ef8a5
icat: allow specifying image ids 2023-03-09 10:17:53 +05:30
Kovid Goyal
a56f111f98
Add a comment explaining why we rescan even when the line is not dirty 2023-03-09 10:09:08 +05:30
Kovid Goyal
5058960a0e
Merge branch 'pr-redraw-on-upload' of https://github.com/sergei-grechanik/kitty 2023-03-09 10:08:16 +05:30
Sergei Grechanik
87ef5e4084 Always rerender unicode placeholders in the scrollback 2023-03-08 19:23:54 -08:00
Kovid Goyal
31d8a98a45
Fix kitty icat broken during the port to Go 2023-03-08 20:47:17 +05:30
Kovid Goyal
f42090766a
Use the new string scanner everywhere 2023-03-08 13:31:27 +05:30
Kovid Goyal
b8ce441453
A new string scanner thats faster than bufio.Scanner and has zero-allocation 2023-03-08 13:24:20 +05:30
Kovid Goyal
ebc1a0f0aa
Don't need to save/restore private mode values in icat when output unicode paceholder
Was originally there in case we turned off line wrapping. But didnt end
up doing that.
2023-03-08 10:33:43 +05:30
Sergei Grechanik
0be83c1bb6 Redraw old unicode placeholders when a virtual placement is added 2023-03-07 20:11:56 -08:00
Kovid Goyal
d6a073945d
Count LoC in tests and docs as well 2023-03-07 18:00:46 +05:30
Kovid Goyal
cd332eb2d5
DRYer 2023-03-07 17:15:21 +05:30
Kovid Goyal
f157882856
Finish porting of ask kitten to Go 2023-03-07 17:06:00 +05:30
Kovid Goyal
018bf46ddb
kitty @ shell: Integrate completions from history 2023-03-07 17:01:21 +05:30
Kovid Goyal
ef6693a239
Dont insert empty spaces when no completions are found 2023-03-07 17:00:40 +05:30
Kovid Goyal
d7b0aa48c9
Dont display empty match groups 2023-03-07 16:53:52 +05:30
Kovid Goyal
ea1842407d
Auto accept completion when only a single candidate is present 2023-03-07 16:48:53 +05:30
Kovid Goyal
0e73c01093
readline: Automatically do word completion based on history 2023-03-07 16:44:02 +05:30
Kovid Goyal
4cef83ffd0
show message even for password asks 2023-03-07 14:03:39 +05:30
Kovid Goyal
f4b0fbc61e
Fix invocation of wrapped UI kittens 2023-03-07 13:55:45 +05:30
Kovid Goyal
0da998ac53
Implement reading of password 2023-03-07 13:55:45 +05:30
Kovid Goyal
bb22990af9
... 2023-03-07 13:55:45 +05:30
Kovid Goyal
7ad5dc6a6f
Fix mouse CSI parsing 2023-03-07 13:55:44 +05:30
Kovid Goyal
0aa55fb755
Start work on porting the ask kitten 2023-03-07 13:55:44 +05:30
Kovid Goyal
672ecde68b
X11: Fix a crash if the X server requests clipboard data after we have relinquished the clipboard
Fixes #5650
2023-03-07 13:53:07 +05:30
Kovid Goyal
ecfebcd6af
... 2023-03-07 12:42:25 +05:30
Kovid Goyal
cd4b19918c
make the latest mypy happy 2023-03-07 12:02:08 +05:30
Kovid Goyal
2bbf9a4e9b
Wayland KDE: Fix selecting in un-focused OS window not working correctly
Every day, in every way, I fall deeper and deeper in love with Yayland!

Fixes #6095
2023-03-07 11:29:57 +05:30
Kovid Goyal
e043fef257
Synthesize click events in the loop 2023-03-07 07:57:14 +05:30
Kovid Goyal
5c87d7f84f
Cleanup ring buffer implementation 2023-03-07 07:43:53 +05:30
Kovid Goyal
37cebbc817
Implement decoding of mouse events in Go 2023-03-07 07:20:46 +05:30
Kovid Goyal
16c7681c7c
diff kitten: Speedup patch parsing by working with bytes rather than unicode
Also change the line split algorithm to only split on \n, \r and \r\n.
This is hopefully closer to what git/diff generate in their patch files.
I cant find any documentation specifying this however.

Fixes #6052
Fixes #6092
2023-03-06 09:55:55 +05:30
Kovid Goyal
99b23c5c66
... 2023-03-05 14:25:19 +05:30
Kovid Goyal
db972f3442
Cleanup parsing of single char options 2023-03-05 14:22:53 +05:30
Kovid Goyal
23d2293296
More tests for rg arg parsing 2023-03-05 14:09:04 +05:30
Kovid Goyal
716a048e6c
... 2023-03-05 14:02:19 +05:30
Kovid Goyal
a252ff1c7b
Merge branch 'hold-kp-enter' of https://github.com/page-down/kitty 2023-03-05 14:00:39 +05:30
pagedown
2ee30302fe
hold: Allow pressing the numeric keypad enter key to exit 2023-03-05 16:18:29 +08:00
Kovid Goyal
6660071d3a
Port the hyperlinked_grep kitten to Go 2023-03-05 13:41:57 +05:30
Kovid Goyal
a0d30f4dd8
DRYer 2023-03-05 13:41:36 +05:30
Kovid Goyal
c88a171b28
Map should use same order of arguments as pythons map 2023-03-05 12:19:03 +05:30
Kovid Goyal
e6d53a1921
Merge branch 'nerd-fonts' of https://github.com/page-down/kitty 2023-03-05 08:42:26 +05:30
Kovid Goyal
0e4b374b7b
Merge branch 'fix-which' of https://github.com/page-down/kitty 2023-03-05 08:41:04 +05:30
pagedown
0147ef467b
Import the missing which 2023-03-05 08:51:29 +08:00
pagedown
e9f5806dcd
Update to Nerd Fonts 2.3.3 2023-03-04 23:23:52 +08:00
Kovid Goyal
3cfb5441fc
Merge branch 'ime' of https://github.com/page-down/kitty 2023-03-04 13:48:32 +05:30
pagedown
823db08712
IME: Right align overlay when typing at the edge of the screen
When the cursor is at the right edge of the screen, push the overlay to
the left to display the pre-edit text just entered.
2023-03-04 16:11:29 +08:00
Kovid Goyal
a2887bb9e0
get rid of utils.Cut since we can now rely on strings.Cut instead 2023-03-04 13:37:55 +05:30
Kovid Goyal
defac0c061
Implement automatic tmux passthrough for icat 2023-03-04 13:01:23 +05:30
Kovid Goyal
8bd814444c
Fix active TMUX session detection 2023-03-04 12:50:07 +05:30
Kovid Goyal
1218a152bf
Implement unicode placeholders in icat 2023-03-04 11:54:22 +05:30
Kovid Goyal
ed8a88e009
Add new unicode placeholder and tmux passthrough options to icat 2023-03-03 22:06:35 +05:30
Kovid Goyal
5b160ea599
Use Once for CachedHostname 2023-03-03 15:20:35 +05:30
Kovid Goyal
e6662e11c3
Dont change the tmux allow-passthrough mode if it is already set 2023-03-03 15:06:49 +05:30
Kovid Goyal
1bf911a81b
Generate the rowcol diacrticis for Go as well 2023-03-03 14:39:38 +05:30
Kovid Goyal
a7ed47575e
Improve documentation for Unicode placeholders 2023-03-03 12:45:52 +05:30
Kovid Goyal
8add28de96
Merge branch 'pr-unicode-placeholders' of https://github.com/sergei-grechanik/kitty 2023-03-03 10:55:02 +05:30
Kovid Goyal
900111572e
Linux binary installer: Proceed via a staged tmpdir
Now installation on Linux and macOS is similar. installer is first
downloaded, then extracted, then copied to installation location.
2023-03-02 14:13:34 +05:30
Kovid Goyal
3f293db632
... 2023-03-02 13:34:42 +05:30
Kovid Goyal
eab3b2a689
Reduce the number of spurious focus events
1) When performing operations known to cause lots of focus changes such
   as creating new sessions/windows or moving windows, forcibly ignore focus events

2) Track window focus state and dont report focus events when the state
   is unchanged by a focus_changed() call

This allows focus specific code to be restricted to just 2-3 places
instead of having to track every possible function that could change
focus.

Fixes #6083
2023-03-02 13:30:26 +05:30
Kovid Goyal
719fe9ea04
Fix deletion of assets from nightly release on GitHub
The derived asset URL was wrong. Instead use the URL supplied in the
JSON asset description.
2023-03-02 11:28:05 +05:30
Kovid Goyal
294d36f2d3
Merge branch 'hints-kitten' of https://github.com/page-down/kitty 2023-03-02 08:04:06 +05:30
pagedown
4c9d90efbb
hints kitten: Perform copy action with --program when matching linenum 2023-03-02 10:30:17 +08:00
Kovid Goyal
fccd776732
Fix overlay windows not inheriting the per-window padding and margin settings of their parents
Fixes #6063
2023-03-01 21:45:17 +05:30
Kovid Goyal
66804dafe8
Fix a regression that broke drawing of images below non-default cell backgrounds
Fixes #6061
2023-03-01 21:13:48 +05:30
Kovid Goyal
6d73306198
Fix for GitHub releases API not returning all assets when querying the assets URL due to pagination
Use the assets list from the release result when available as it is
not paginated. Otherwise request 64 items per page which is more than
enough for our 30 odd assets
2023-03-01 21:02:25 +05:30
Kovid Goyal
eb6d777790
... 2023-03-01 20:34:09 +05:30
Kovid Goyal
81f8ed6b45
Use @ rather than # for named buffers prefix char
Matches existing use of @ for clipboard. Also @ doesnt need to be quoted
in most shells.
2023-03-01 19:54:03 +05:30
Kovid Goyal
8ad39332c9
Merge branch 'hints-kitten-copy-to-buffer' of https://github.com/page-down/kitty 2023-03-01 19:49:52 +05:30
Kovid Goyal
c94401729a
Add protocol docs for async and streaming requests 2023-03-01 19:46:29 +05:30
pagedown
854529c443
hints kitten: Allow copying matches to named buffers 2023-03-01 22:10:24 +08:00
Kovid Goyal
bd32019b91
Fix error display when remote control mapping fails 2023-03-01 17:45:57 +05:30
Kovid Goyal
004aaf3291
Fix setting background image and logo via remote control key mapping not working 2023-03-01 17:42:55 +05:30
Kovid Goyal
22f6728fed
Do not buffer PNG data to disk when setting window background or logo images 2023-03-01 17:34:38 +05:30
Kovid Goyal
f0aacbd437
Remove unused code 2023-03-01 16:54:06 +05:30
Kovid Goyal
1bf180f354
Allow loading window background images from memory 2023-03-01 16:11:38 +05:30
Kovid Goyal
bf79940a13
When reloading config also reload all GPU data
Fixes some config options such as text_composition_strategy not being
reloaded.
2023-03-01 11:14:03 +05:30
Kovid Goyal
0616f9e077
Fix background image not changing when reloading config 2023-03-01 10:50:33 +05:30
Kovid Goyal
cbf3b5860b
Merge branch 'png' of https://github.com/page-down/kitty 2023-03-01 10:21:52 +05:30
pagedown
3d50c1ea5a
Fix cursor misalignment after displaying detailed traceback 2023-03-01 12:04:04 +08:00
pagedown
08c0321fc4
Don't use the deprecated imghdr module 2023-03-01 12:03:56 +08:00
Kovid Goyal
cd8bb462c3
Add KITTY_VCS_REV for release builds as well 2023-02-28 19:41:28 +05:30
Kovid Goyal
5b46d990a2
Add Read/Write to the MMap interface 2023-02-28 19:01:15 +05:30
Kovid Goyal
944e036611
DRYer 2023-02-28 15:48:04 +05:30
Kovid Goyal
1b2fe90ed1
Fix askpass.go on shm_syscall based systems 2023-02-28 14:11:27 +05:30
Kovid Goyal
ba1ce996bb
Fix WriteWithSize() on shm_syscall 2023-02-28 13:50:06 +05:30
Kovid Goyal
327cefbfda
Make test more robust 2023-02-28 13:44:29 +05:30
Kovid Goyal
ce12fd3515
Fix ReadWithSizeAndUnlink on systems that have syscall based mmap 2023-02-28 13:44:09 +05:30
Kovid Goyal
4d3ce47813
... 2023-02-28 13:19:51 +05:30
Kovid Goyal
8729717229
Dont create SHM files in the bootstrap limit and related tests 2023-02-28 13:16:00 +05:30
Kovid Goyal
935a36f5a8
Allow specifying VCS revision on the build command line 2023-02-28 13:05:43 +05:30
Kovid Goyal
1ddb1dc5e1
... 2023-02-28 13:00:19 +05:30
Kovid Goyal
9135ba138e
Merge branch 'ssh' 2023-02-28 12:45:51 +05:30
Kovid Goyal
00b3437a05
Remove python implementation of SSH kitten 2023-02-28 12:42:30 +05:30
Kovid Goyal
3558d1c274
Finish porting support for color schemes to SSH kitten 2023-02-28 12:08:55 +05:30
Kovid Goyal
8302e5d74b
Merge branch 'james/typo' of https://github.com/jamesbvaughan/kitty 2023-02-28 08:13:23 +05:30
James Vaughan
a5a0d5acb9
Fix typo in overview doc 2023-02-27 16:53:44 -08:00
Kovid Goyal
c877b2a5cb
Code to dump basic colors from a theme as escape codes 2023-02-27 08:02:22 +05:30
Kovid Goyal
c1791c8d2b
Function to load theme code 2023-02-26 22:09:07 +05:30
Kovid Goyal
22150e13fd
Add tests for cache file downloading 2023-02-26 21:56:03 +05:30
Kovid Goyal
7ce64fcde0
Support include when loading themes from dirs 2023-02-26 21:16:29 +05:30
Kovid Goyal
0b09d18b36
Port theme loading code to Go 2023-02-26 20:40:59 +05:30
Kovid Goyal
4eea2fd4fc
Port code to download themeball to Go 2023-02-26 15:21:49 +05:30
Kovid Goyal
c113ad6f56
Code to parse ISO8601 timestamps at least semi-robustly 2023-02-26 13:32:35 +05:30
Kovid Goyal
64cb9c9542
More work on porting ssh kitten 2023-02-26 11:26:28 +05:30
Kovid Goyal
4a5c6ad47f
Functions to punch DCS escapes through tmux 2023-02-26 11:11:42 +05:30
Kovid Goyal
6de77ce987
Clean up exclude pattern handling 2023-02-26 09:12:12 +05:30
Kovid Goyal
5cc3d3cbfe
Fix remaining failing tests 2023-02-26 08:01:04 +05:30
Kovid Goyal
dc938cf3dd
More test fixes 2023-02-26 08:01:04 +05:30
Kovid Goyal
22ea33182a
Fix various test failures 2023-02-26 08:01:04 +05:30
Kovid Goyal
3f417b26b2
Wire up the new ssh kitten into the python ssh kitten tests 2023-02-26 08:01:04 +05:30
Kovid Goyal
e4002b5691
Switch to a more capable glob implementation that supports ** 2023-02-26 08:01:04 +05:30
Kovid Goyal
77c04107f3
Add test for tarfile exclusion 2023-02-26 08:01:03 +05:30
Kovid Goyal
a5cf66b334
Stable constants generation 2023-02-26 08:01:03 +05:30
Kovid Goyal
525caff938
Move get_connection_data to utils module as it is not needed for the actual kitten 2023-02-26 08:01:03 +05:30
Kovid Goyal
e02ba7f389
Port bootstrap script length limit 2023-02-26 08:01:03 +05:30
Kovid Goyal
9870c94007
More work on porting the SSH kitten 2023-02-26 08:01:03 +05:30
Kovid Goyal
6b71b58997
Add write API to shm objects 2023-02-26 08:01:03 +05:30
Kovid Goyal
43bcb41a2a
Nicer Set constructor 2023-02-26 08:01:03 +05:30
Kovid Goyal
1df3ef648c
Clean up getting runtime dir on darwin 2023-02-26 08:01:03 +05:30
Kovid Goyal
4d8ccd8e94
... 2023-02-26 08:01:03 +05:30
Kovid Goyal
f40380b05a
More useful Set methods 2023-02-26 08:01:03 +05:30
Kovid Goyal
3703b4dbef
API to conveniently generate secure tokens 2023-02-26 08:01:03 +05:30
Kovid Goyal
907a51c99c
Code to read needed options from kitty.conf in a kitten 2023-02-26 08:01:03 +05:30
Kovid Goyal
0614c63966
Handle XDG_CONFIG_DIRS in Go as well 2023-02-26 08:01:03 +05:30
Kovid Goyal
a84b688038
Embed the data files needed for the ssh kitten into the Go binary 2023-02-26 08:01:03 +05:30
Kovid Goyal
b4b8943e64
Replace some more uses of sync.Once 2023-02-26 08:01:03 +05:30
Kovid Goyal
587d06b295
Replace use of sync.Once 2023-02-26 08:01:03 +05:30
Kovid Goyal
fa0773d9d2
Use a struct to store connection related data 2023-02-26 08:01:03 +05:30
Kovid Goyal
d656017f27
Move SSH askpass implementation into kitten 2023-02-26 08:01:02 +05:30
Kovid Goyal
6f4d89045a
A nicer implementation of sync.Once
Doesnt require storing the result of the function in a dedicated global
variable with a dedicated getter function
2023-02-26 08:01:02 +05:30
Kovid Goyal
fbaaca1be9
Function to create symlinks atomically 2023-02-26 08:01:02 +05:30
Kovid Goyal
fa45324d39
Port code to read cloned env 2023-02-26 08:01:02 +05:30
Kovid Goyal
88077fdbcd
Allow Stat() for MMap objects 2023-02-26 08:01:02 +05:30
Kovid Goyal
5a8d903a4d
Go SHM API to read simple data with size from SHM name 2023-02-26 08:01:02 +05:30
Kovid Goyal
3f829ccdde
Handle invalid args and passthrough 2023-02-26 08:01:02 +05:30
Kovid Goyal
06bfa671d9
Allow specifying the paths to search in Which() 2023-02-26 08:01:02 +05:30
Kovid Goyal
97b9572bec
Port parsing of ssh args 2023-02-26 08:01:02 +05:30
Kovid Goyal
12c8af60dc
String repr for Set 2023-02-26 08:01:02 +05:30
Kovid Goyal
57839b4e03
Port function to get ssh cli options by running ssh binary 2023-02-26 08:01:02 +05:30
Kovid Goyal
407555c6c8
Get completion working for kitten ssh 2023-02-26 08:01:02 +05:30
Kovid Goyal
590c1bd7ad
dont parse args for the ssh kitten as it will do so itself 2023-02-26 08:01:02 +05:30
Kovid Goyal
46367bceed
... 2023-02-26 08:01:02 +05:30
Kovid Goyal
041c646d46
Fix parsing of copy args 2023-02-26 08:01:02 +05:30
Kovid Goyal
d98504e1a6
Finish porting SSH config file parsing 2023-02-26 08:01:02 +05:30
Kovid Goyal
07f4adbab5
Also add tests for bad lines 2023-02-26 08:01:02 +05:30
Kovid Goyal
7b4738125b
Move config code into its own package 2023-02-26 08:01:02 +05:30
Kovid Goyal
2b7d6d45df
Finish up config parser port 2023-02-26 08:01:01 +05:30
Kovid Goyal
747411be00
Finish implementation of config file parsing
Still needs tests
2023-02-26 08:01:01 +05:30
Kovid Goyal
70086451e7
Port parsing of env instructions 2023-02-26 08:01:01 +05:30
Kovid Goyal
32aa580984
Store parsed multi option values on the config object 2023-02-26 08:01:01 +05:30
Kovid Goyal
1470b11024
Dont parse default values 2023-02-26 08:01:01 +05:30
Kovid Goyal
5822bb23f0
Work on porting config file parsing to Go 2023-02-26 08:01:01 +05:30
Kovid Goyal
6f63d9c5d4
Start work on porting the SSH kitten to Go 2023-02-26 08:01:01 +05:30
Kovid Goyal
3d3bfe6c75
... 2023-02-26 08:00:50 +05:30
Kovid Goyal
d550aef792
Fix #6056 2023-02-25 08:49:49 +05:30
Kovid Goyal
0d0f74a131
Note that we use tabs for indent in *.go files in editorconfig 2023-02-25 08:33:51 +05:30
Kovid Goyal
ed64899b83
Merge branch 'indent_style_space' of https://github.com/ornicar/kitty 2023-02-25 08:24:40 +05:30
Thibault Duplessis
098530ad38 fix typo in .editorconfig
According to https://editorconfig.org/#file-format-details:

> indent_style: set to tab or space to use hard tabs or soft tabs respectively.

Apologies if this is known and the previous `spaces` syntax is preferred.
In that case of course just close the PR.

Thanks for kitty 🐱
2023-02-24 19:03:47 +01:00
Kovid Goyal
b0f552c332
Fix upload to github not aborting for uploads that fail with protocol errors rather than failure responses 2023-02-24 20:34:46 +05:30
Kovid Goyal
f7f4384876
Also log start of upload 2023-02-24 20:29:51 +05:30
Kovid Goyal
7dd20d4c79
Dont output empty brackets for release versions which dont have KITTY_VCS_REV 2023-02-24 20:11:09 +05:30
Kovid Goyal
7ab0c3013e
Merge branch 'fix-macos' of https://github.com/page-down/kitty 2023-02-24 17:31:37 +05:30
pagedown
4f44945c07
macOS: Restore pre-edit text after inserting text from the service
Add comments to explain how to get the methods to be called.
2023-02-24 19:57:09 +08:00
pagedown
f8b53df5c2
macOS: Fix resize_in_steps being applied when double-clicking on the
title bar to maximize the window
2023-02-24 19:56:51 +08:00
Kovid Goyal
c5149dec24
... 2023-02-23 22:19:45 +05:30
Kovid Goyal
e41897f93f
Also clean *_generated.bin files 2023-02-23 21:24:59 +05:30
Kovid Goyal
5ce85292b7
Cleanup previous PR
1) Fix a text_len leaking
2) No need to re-decode overlay_text
3) get_ime_cursor_position should not change the current global callback OS window
2023-02-23 21:19:30 +05:30
Kovid Goyal
dba8d278cb
Merge branch 'ime' of https://github.com/page-down/kitty 2023-02-23 20:50:25 +05:30
Kovid Goyal
79e99f7e3a
Dont pass PWD to go build
Fixes #6051
2023-02-23 14:31:30 +05:30
pagedown
9a598237c6
macOS: Allow IME to actively get the cursor position in real time
IME will automatically get the display position when needed, which keeps
it consistent with the overlay as much as possible.

Fix the issue that when IME is activated after mouse click, it is
displayed at the wrong position.
2023-02-22 22:36:20 +08:00
pagedown
126aaddccb
IME: Render overlay at the last visible cursor position with a separate cursor
Fix the problem caused by wrong cursor coordinates. No more messing with
the main cursor, instead the cursor is saved when receiving a pre-edit
text update and used for drawing later.

Update the overlay to the last visible cursor position before rendering
to ensure it always moves with the cursor. Finally, draw the overlay
after line rendering is complete, and restore the line buffer after
updating the rendered data to ensure that the line text being read is
correct at all times.

This also improves performance by only rendering once when changes are
made, eliminating the need to repeatedly disable and draw after various
commands and not even comprehensively.
2023-02-22 22:36:06 +08:00
Kovid Goyal
de188faf55
Fix #6048 2023-02-22 19:51:33 +05:30
Sergei Grechanik
d63eeada73 Image placement using Unicode placeholders
This commit introduces the Unicode placeholder image placement method.
In particular:
- Virtual placements can be created by passing `U=1` in a put command.
- Images with virtual placements can be displayed using the placeholder
  character `U+10EEEE` with diacritics indicating rows and columns.
- The image ID is indicated by the foreground color of the placeholder.
  Additionally, the most significant byte of the ID can be specified via
  the third diacritic.
- Underline color can be optionally used to specify the placement ID.
- A bug was fixed, which caused incomplete image removal when it was
  overwritten by another image with the same ID.
2023-02-21 18:23:16 -08:00
Kovid Goyal
1f84e2d4e5
Merge branch 'pr-fix-screen-switching' of https://github.com/sergei-grechanik/kitty 2023-02-21 10:20:32 +05:30
Sergei Grechanik
6edf145b73 Fix image distortion when switching between screens 2023-02-20 19:46:25 -08:00
Kovid Goyal
fbfb779a19
Clarify what pygments style does 2023-02-20 16:38:22 +05:30
Kovid Goyal
71b07090c2
End APC and PM escape code on BEL as well as ST 2023-02-19 15:24:23 +05:30
Kovid Goyal
6619804df0
... 2023-02-18 17:23:50 +05:30
Kovid Goyal
24b2802619
Merge branch 'fix-os-window-state' of https://github.com/page-down/kitty 2023-02-18 17:22:43 +05:30
pagedown
b0c28148b1
macOS: Fix window not taking up full height when the title bar is hidden
When the remembered window size is the full screen height, the window
height decreases after hiding the title bar.
2023-02-18 19:35:01 +08:00
pagedown
75a4f45a23
... 2023-02-18 17:43:45 +08:00
pagedown
ba83ce7b10
macOS: Display the newly created OS window in specified state
Fix the maximized window can't occupy full screen space when window
decoration or title bar is hidden.
Fix resize_in_steps being applied even when window is maximized.
Allows to specify `os_window_state` in startup session file.
2023-02-18 14:02:19 +08:00
Kovid Goyal
1b76cee9b4
Merge branch 'dependabot/go_modules/golang.org/x/image-0.5.0' of https://github.com/kovidgoyal/kitty 2023-02-17 20:18:02 +05:30
dependabot[bot]
aad3704803
Bump golang.org/x/image from 0.3.0 to 0.5.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.3.0 to 0.5.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.3.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-17 14:44:32 +00:00
Kovid Goyal
00e2c66ea3
Add a link to the pets nvim plugin 2023-02-17 10:41:03 +05:30
Kovid Goyal
72b2ba51df
launch: Allow specifying the state (fullscreen/maximized/minimized) for newly created OS Windows
Fixes #6026
2023-02-16 16:24:46 +05:30
Kovid Goyal
c73c165be1
Cleanup change_os_window_state 2023-02-16 16:10:19 +05:30
Kovid Goyal
e6e25c4ece
Merge branch 'patch-1' of https://github.com/jle64/kitty 2023-02-15 22:01:17 +05:30
Jonathan Lestrelin
9ce11499de
Add x-scheme-handler/ssh to mimetypes
Add x-scheme-handler/ssh to mimetypes so that kitty open can be used to open ssh links by default.
2023-02-15 16:24:47 +00:00
Kovid Goyal
ac5298ce76
Finish porting unicode input 2023-02-15 17:42:31 +05:30
Kovid Goyal
1321a96ae7
More work on porting unicode input 2023-02-15 17:14:09 +05:30
Kovid Goyal
2b87a601a0
More work on porting unicode input 2023-02-15 10:48:54 +05:30
Kovid Goyal
73a3366d53
Fix atomic write not working when file does not exist 2023-02-15 10:46:47 +05:30
Kovid Goyal
7223fdaa38
API to set the text at the prompt 2023-02-15 10:16:25 +05:30
Kovid Goyal
67436a48cd
New API to suspend a loop 2023-02-14 22:27:41 +05:30
Kovid Goyal
9aaca33f15
... 2023-02-14 22:27:10 +05:30
Kovid Goyal
a5eac42d92
More work on unicode input 2023-02-14 21:33:21 +05:30
Kovid Goyal
fb66cbc792
Forgot to exclude some control chars from unicode name based searching 2023-02-14 21:33:21 +05:30
Kovid Goyal
311a0cbfe9
More work on porting unicode input 2023-02-14 21:33:21 +05:30
Kovid Goyal
53e33a80ba
Start work on porting unicode input kitten to Go 2023-02-14 21:33:21 +05:30
Kovid Goyal
a2e4efbb14
API to save/restore cursor position 2023-02-14 21:33:21 +05:30
Kovid Goyal
1aa9f1e62d
Allow faint as an alias for dim 2023-02-14 21:33:21 +05:30
Kovid Goyal
32e0a56a94
Some more useful generic slice utilities 2023-02-14 21:33:21 +05:30
Kovid Goyal
601a333b0e
Atomically update cached values file 2023-02-14 21:33:21 +05:30
Kovid Goyal
cc5107d0db
Convenient way to load/save JSON data 2023-02-14 21:33:20 +05:30
Kovid Goyal
bee853cc6a
ignore *.bin files in version control 2023-02-14 21:33:09 +05:30
Kovid Goyal
ec375ad3c6
Dont strip title for tabs to allow for leading and trailing whitespace. Fixes #6013 2023-02-14 21:31:23 +05:30
Kovid Goyal
5a7abd6214
CodeQL does not work for Go code 2023-02-14 11:15:44 +05:30
Kovid Goyal
3399f40de5
Merge branch 'go-version' of https://github.com/page-down/kitty 2023-02-14 11:15:02 +05:30
Kovid Goyal
31b804d8fb
Merge branch 'add-python-typing-for-send_mouse_event' of https://github.com/trygveaa/kitty 2023-02-14 10:00:16 +05:30
Kovid Goyal
5219044519
Merge branch 'reload-mime-types' of https://github.com/page-down/kitty 2023-02-14 09:55:22 +05:30
Kovid Goyal
d6aecf172d
Merge branch 'fix-macos-fullscreen' of https://github.com/page-down/kitty 2023-02-14 09:49:19 +05:30
Trygve Aaberge
8a3376261e Add send_mouse_event to fast_data_types.pyi 2023-02-13 21:52:41 +01:00
pagedown
cc18a4c192
transfer kitten: Use guess_type with custom MIME 2023-02-12 17:34:09 +08:00
pagedown
4141872290
When reloading configuration, also reload mime.types 2023-02-12 17:28:42 +08:00
pagedown
c41b65af97
macOS: Update window button visibility after toggling full screen 2023-02-12 13:45:27 +08:00
pagedown
dcddaf33e0
... 2023-02-11 20:43:42 +08:00
pagedown
e388326929
... 2023-02-11 20:36:25 +08:00
pagedown
d1e54a1d3b
CI: Bump versions of the deprecated github actions to the latest 2023-02-11 20:33:29 +08:00
pagedown
3c7df680cf
Get go version from go.mod
No need to update multiple places when bumping the go version.
2023-02-11 20:33:08 +08:00
Kovid Goyal
64fe9f82ed
Add chr and ord to safe_builtins 2023-02-11 05:51:24 +05:30
Kovid Goyal
74a5b26967
... 2023-02-11 05:48:01 +05:30
Kovid Goyal
2307892b50
Cleanup previous PR getting kitty working on macOS
Do not reduce the required OpenGL version on macOS. There is no point
anyway.

Fixes #2790
2023-02-10 11:03:25 +05:30
Kovid Goyal
a09dda27dc
Merge branch 'master' of https://github.com/marcan/kitty 2023-02-10 10:55:41 +05:30
Kovid Goyal
ca1a5dcf5e
Update design philosophy to mention Go code 2023-02-10 10:51:16 +05:30
Kovid Goyal
1d21b54d23
Merge branch 'docs' of https://github.com/page-down/kitty 2023-02-10 10:46:46 +05:30
pagedown
0d51adaa2c
gitignore: Remove duplicate ignore rules and add ruff cache directory 2023-02-10 12:47:05 +08:00
pagedown
81a221460a
Docs: Remind users to remove macos_thicken_font in changelog 2023-02-10 12:46:50 +08:00
pagedown
f8644682f9
... 2023-02-10 12:46:40 +08:00
pagedown
c172e0158c
Docs: Minor configuration docs improvements
Add some text roles.
Revise the cases of some words.
Manually wrap lines to make the generated commented config file and
source code a bit neater.
2023-02-10 12:46:31 +08:00
pagedown
c41a0c0290
Docs: Generate commented default configuration files
Provides the same sample config files as the locally generated ones.
2023-02-10 12:44:10 +08:00
Kovid Goyal
1b580e8323
Update Changelog for last PR 2023-02-10 09:28:33 +05:30
Kovid Goyal
94ab58343a
Merge branch 'fix-ime' of https://github.com/page-down/kitty 2023-02-10 09:27:19 +05:30
pagedown
947dc2ff75
IME: Fix IME commit text and update pre-edit at the same time
Correctly update the overlay position when cursor visibility changes.
Restore the overlay line only when the cursor is visible.
Clear the saved overlay when drawing new pre-edit text.
Also update the cursor position when screen size changes.
Use four spaces to indent instead of two.
2023-02-10 10:50:32 +08:00
Kovid Goyal
439a997e5d
Add a note to macos_thicken_font pointing to the new text_composition_strategy 2023-02-09 19:59:09 +05:30
Kovid Goyal
befd5a65c3
A generic Set implementation 2023-02-09 18:00:04 +05:30
Kovid Goyal
8d0452d375
Allow specifying initial capacity when splitting lines 2023-02-09 12:59:40 +05:30
Kovid Goyal
44f46afb2a
Merge branch 'patch_function_prototype' of https://github.com/hellobbn/kitty 2023-02-09 11:42:22 +05:30
Luofan Chen
130315ce8d Use strict function prototypes
Fixes clang error:
error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
2023-02-09 13:16:00 +08:00
Kovid Goyal
07bab5253e
Update Unicode data 2023-02-09 09:45:42 +05:30
Kovid Goyal
3b861d5f79
Better fix for OGP social cards build failure 2023-02-09 09:45:10 +05:30
Kovid Goyal
679862aa94
When changing the cursor text color via escape codes or remote control to a fixed color, do not ignore cursor_text_color
Fixes #5994
2023-02-08 21:01:00 +05:30
Kovid Goyal
1d2a8288ee
... 2023-02-08 20:45:41 +05:30
Kovid Goyal
7c8c7fe3a2
launch: When using --cwd=current for a remote system support running non shell commands as well 2023-02-08 17:52:28 +05:30
Kovid Goyal
244507336b
Function to change the remote command in an ssh kitten cmdline 2023-02-08 16:34:33 +05:30
Kovid Goyal
237a5d17c0
Fix a regression in 0.27.0 that broke kitty @ set-font-size 0
Fixes #5992
2023-02-08 14:21:56 +05:30
Kovid Goyal
4dfd4d4972
sRGB glyph composition: Use default values that give "close to native" rendering. Also use only a single option to control it. 2023-02-08 13:49:53 +05:30
Kovid Goyal
8433f1d731
Update changelog for last PR 2023-02-08 13:03:25 +05:30
Kovid Goyal
2849eadd47
Minor cleanups 2023-02-08 12:51:18 +05:30
Kovid Goyal
28af786209
DRYer 2023-02-08 12:09:14 +05:30
Kovid Goyal
d53cb97aa1
Mark SRGB LUT table as generated 2023-02-08 11:29:18 +05:30
Kovid Goyal
e0e7917eaa
Use builtin clamp() rather than min() + max() 2023-02-08 11:29:04 +05:30
Kovid Goyal
b5b070aade
Merge branch 'linear-gamma-blending' of https://github.com/m4rw3r/kitty 2023-02-08 11:22:35 +05:30
Kovid Goyal
45d8a2a630
... 2023-02-07 18:27:16 +05:30
Kovid Goyal
dd07a8c4a4
Changes to make updated mypy happy 2023-02-07 18:10:43 +05:30
Kovid Goyal
9e35d26188
Disable OGP social cards as building them breaks 2023-02-07 17:21:07 +05:30
Kovid Goyal
17e4995e93
version 0.27.1 2023-02-07 16:10:29 +05:30
Kovid Goyal
e161b5a4de
Merge branch 'completion' of https://github.com/page-down/kitty 2023-02-04 13:35:58 +05:30
pagedown
52b643b6c6
Completion: Handle kitty +complete setup fish2
Provide the currently supported fish completion script when requesting
version 2.
2023-02-04 15:55:22 +08:00
Kovid Goyal
9bdb647454
kitty @ shell: Fix global options being ignored
Also no need to exec a separate process for every command
2023-02-04 12:54:49 +05:30
Kovid Goyal
0cabc3e109
Indicate when caps lock is on while reading password 2023-02-04 11:06:24 +05:30
Kovid Goyal
d06d6d7646
Add the command that can be used to get the default config file 2023-02-03 19:29:45 +05:30
Kovid Goyal
f1dc072045
Clean up previous PR 2023-02-03 16:14:24 +05:30
Kovid Goyal
9adc474e3c
Merge branch 'completion' of https://github.com/page-down/kitty 2023-02-03 16:03:03 +05:30
pagedown
370aa3aaa6
Completion: Delegate kitty +complete to kitten
Implement `kitten __complete__ setup` in Go.
Fix zsh completion script to check `kitten`.
2023-02-03 18:16:04 +08:00
Kovid Goyal
bed4f33be8
Remove unused code 2023-02-03 09:51:54 +05:30
Kovid Goyal
8ce80d8962
Switch to using Go stdlib for ECDH crypto 2023-02-03 09:50:42 +05:30
Kovid Goyal
27ae9104ac
Bump required Go version to 1.20
This allows us to use the stdlib for ECDH crypto used by remote control.
Fixes #5976
2023-02-03 09:32:56 +05:30
Kovid Goyal
331f1b7f2b
Merge branch 'ksi' of https://github.com/page-down/kitty 2023-02-03 09:30:14 +05:30
pagedown
df1a99a974
Shell integration: More builtin commands 2023-02-03 10:56:19 +08:00
Kovid Goyal
7ea4270c88
... 2023-02-03 08:02:28 +05:30
Kovid Goyal
a8480a4ca6
Update changelog for previous PR 2023-02-02 17:51:25 +05:30
Kovid Goyal
783bfb2823
Merge branch 'master' of https://github.com/shimt/kitty 2023-02-02 17:50:02 +05:30
Shinichi MOTOKI
a88164e3a2 Fix function key definitions in terminfo/termcap 2023-02-02 20:01:56 +09:00
Martin Wernstål
3676e6651d feat: additional contrast on text as a function of luminance difference 2023-02-02 10:18:15 +01:00
Martin Wernstål
e64affe3f7 feat: simulate gamma-incorrect blending 2023-02-02 09:53:39 +01:00
Martin Wernstål
9a1155721c refactor: cell_fragment blending functions 2023-02-02 09:53:39 +01:00
Martin Wernstål
8ece895774 feat: Use sRGB LUT for cells 2023-02-02 09:53:39 +01:00
Martin Wernstål
b10c18b8fe feat: Use sRGB LUT for borders 2023-02-02 09:53:39 +01:00
Martin Wernstål
2bc03852a1 feat: sRGB colors to shaders 2023-02-02 09:53:39 +01:00
Martin Wernstål
be61b4e95e feat: sRGB lookup table 2023-02-02 09:53:39 +01:00
Martin Wernstål
02d1a3c1c3 feat(srgb): swap textures and framebuffers to SRGB 2023-02-02 09:53:39 +01:00
Kovid Goyal
a7cbe3776d
Wayland GNOME: Fix for ibus not working when using XWayland
See 8ce25208c3

I dont know what it is with GNOME. Every single release they break
backward compatibility somewhere, somehow. They must have special
talents.

Fixes #5967
2023-02-02 10:25:33 +05:30
Kovid Goyal
78d0cc40a3
Fix readSelectionFromPasteboard not actually inserting the text 2023-02-02 06:14:34 +05:30
Kovid Goyal
01720a8d4f
Fix typo seems to have no actual effect, but... 2023-02-02 06:07:30 +05:30
Kovid Goyal
1d45cf4f91
Use crypto/rand rather than math/rand
Who knows how random math/rand actually is
2023-02-02 06:04:17 +05:30
Kovid Goyal
a9da57d9b3
Forgot to use builtin for alias 2023-02-01 19:27:39 +05:30
Kovid Goyal
a280328731
kitty->kitten typo 2023-02-01 19:11:39 +05:30
Kovid Goyal
17d2315d0c
Merge branch 'docs' of https://github.com/page-down/kitty 2023-02-01 19:11:13 +05:30
pagedown
e27920527c
Docs: Remove the text role target that is no longer needed 2023-02-01 19:26:38 +08:00
Kovid Goyal
960f5ff065
Merge branch 'docs' of https://github.com/page-down/kitty 2023-02-01 15:46:51 +05:30
pagedown
8fe936882d
Docs: Improve usage and help documents for kitten 2023-02-01 17:14:54 +08:00
Kovid Goyal
682428fb54
Optimize the services implementation
Dont construct the selection string when we are merely checking if a
selection exists.
2023-02-01 12:46:19 +05:30
Kovid Goyal
1c6bae636b
Only accept service requests when we actually have a selection 2023-02-01 12:17:59 +05:30
Kovid Goyal
c201bac900
... 2023-02-01 12:17:15 +05:30
Kovid Goyal
5eaa935ede
icat: Dont try to further compress PNG images when using stream based transmission 2023-02-01 11:45:01 +05:30
Kovid Goyal
a73f09cf89
Clarify that a=f is needed for chunked transmission of animation frame data 2023-02-01 11:43:15 +05:30
Kovid Goyal
092dc3d01f
... 2023-02-01 11:28:52 +05:30
Kovid Goyal
5c0d477a18
icat kitten: Fix transmission of frame data in direct mode
Sometimes frame data is > 2048 but does not compress smaller, which
broke the if statement checking for first loop.

Fixes #5958
2023-02-01 10:51:59 +05:30
Kovid Goyal
414ca86e3f
Remaining fixes from #5962
Fixes #5962
2023-02-01 10:26:53 +05:30
Kovid Goyal
fbbfb25702
Better fix for kitten not being in PATH
Add it to PATH just as we add the kitty dir to PATH. Ensures the correct
kitten is in PATH, corresponding to the correct kitty.
2023-02-01 10:16:50 +05:30
Kovid Goyal
6ea812679f
Fix modify_font not working for strikethrough position
Fixes #5946
2023-02-01 08:14:54 +05:30
Kovid Goyal
5a997a5f7a
grammar 2023-01-31 21:02:58 +05:30
Kovid Goyal
47641456da
Ensure edit-in-kitty works even if kitten is not in PATH
Still needs to be implemented for fish shell
2023-01-31 20:41:39 +05:30
Kovid Goyal
077f71cad5
Another place to update that talks about symlinking to PATH 2023-01-31 20:31:33 +05:30
Kovid Goyal
8f71f6112a
Update installation instructions to note that kitty and kitten both need to be added to PATH 2023-01-31 20:29:41 +05:30
Kovid Goyal
8bdd4d0596
ssh kitten: Install kitty bootstrap on systems other than linux/darwin as now we have kitten which works on more types of systems 2023-01-31 20:16:20 +05:30
Kovid Goyal
df45a4e759
Add a note that --detach is not available on macOS 2023-01-31 17:52:36 +05:30
Kovid Goyal
70111d130e
version 0.27.0 2023-01-31 10:48:56 +05:30
Kovid Goyal
ce6dacd0d4
Also build 32-bit kitten for Linux 2023-01-31 10:48:56 +05:30
Kovid Goyal
f3c434b7c1
Now that we are releasing 0.27.0 dont need to fetch release version to download latest kitten 2023-01-31 10:48:56 +05:30
Kovid Goyal
54b6344985
Add a note that --spacing is ignored for overlay windows 2023-01-30 12:00:41 +05:30
Kovid Goyal
18fc8dad37
Instead of calling insertText duplicate some of its code so we arent limited in the size of text we can insert 2023-01-29 19:56:53 +05:30
Kovid Goyal
9b5034f904
macOS: Integrate with system services 2023-01-29 19:47:50 +05:30
Kovid Goyal
f2c8819d25
Add an example for displaying a PNG with bash 2023-01-29 10:27:03 +05:30
Kovid Goyal
53482f4c84
Show bad length in base64 decode error message 2023-01-29 10:17:00 +05:30
Kovid Goyal
e1c50cf124
Merge branch 'revert' of https://github.com/page-down/kitty 2023-01-27 21:12:53 +05:30
pagedown
aacb4db2dc
Remote control: Improve create-marker error messages
No more missing color errors when text/regex are missing.
Use `mark group` in error messages instead of `color`.
2023-01-27 23:31:06 +08:00
pagedown
8638e42135
Revert "Fix #5937"
This reverts commit 4b322560c398e704d402a0b46a19afad24e50bdd.
Only two arguments are required to create a marker.
2023-01-27 23:15:13 +08:00
Kovid Goyal
4b322560c3
Fix #5937 2023-01-27 15:15:47 +05:30
Kovid Goyal
0a4ad1fe12
Merge branch 'indent' of https://github.com/page-down/kitty 2023-01-27 11:19:54 +05:30
pagedown
907f658fcc
... 2023-01-27 13:40:31 +08:00
pagedown
1e7e10f96f
Docs: Fix mixed tab and space indentation in the example code 2023-01-27 13:39:27 +08:00
Kovid Goyal
5338fcdc1e
Add a note about why we play with file descriptors 2023-01-26 21:50:10 +05:30
Kovid Goyal
f8991ce3c8
ask kitten: Get readline to work even when stdout is redirected 2023-01-26 21:47:43 +05:30
Kovid Goyal
b408abe304
Move compile_commands.json to build directory 2023-01-26 14:25:22 +05:30
Kovid Goyal
084671b26e
Also preread STDIN when using /dev/stdin as the source 2023-01-26 12:57:12 +05:30
Kovid Goyal
1cc69b3edd
Move pre-read code into a separate function for clarity 2023-01-26 12:49:21 +05:30
Kovid Goyal
d88105319d
clipboard kitten: Allow STDIN to be connected to a program that itself uses the tty directly
Read in STDIN first, and only then start terminal IO, hopefully allowing
the other program to finish its terminal IO before we start.

Fixes #5934
2023-01-26 12:40:08 +05:30
Kovid Goyal
eb50fac8de
Add a test for creation of anonymous tempfiles 2023-01-26 11:51:02 +05:30
Kovid Goyal
4185e30d73
Code to more securely create anonymous temp files on Linux 2023-01-26 11:41:01 +05:30
Kovid Goyal
3a126ffa9d
Restore permissions check on pwfile
just use RW instead of R as the expected mode
2023-01-26 08:48:35 +05:30
Kovid Goyal
4f5e3f6cf1
Fix ruff invocation in ALE 2023-01-26 08:44:16 +05:30
Kovid Goyal
dd6e206f9b
Remove unused import 2023-01-26 08:29:37 +05:30
Kovid Goyal
ea920ffdf9
Merge branch 'master' of https://github.com/schlomie/kitty 2023-01-26 08:21:16 +05:30
Loren Schlomer
366d65f592
Fixes the ssh kitten
kovidgoyal@5e645a7 fixes the password file creation, allowing it to be
unlinked, but read_data_from_shared_memory/1 rejects the shared object
if it is not read only, and will break the ssh kitten for all
platforms.

This change removes the read only check, relying only on the file
ownership check.

This fully fixes #5928

Signed-off-by: Loren Schlomer <me@schlomie.com>
2023-01-25 11:14:12 -08:00
Kovid Goyal
5e645a7be7
Fix ssh kitten not working on FreeBSD
Apparently on FreeBSD one cannot unlink shared mem if it is not created
with write permissions.

Adding IWRITE to the permissions when creating the shared memory is
harmless. It means any process running as the user can either write to
the file or delete it. Deleting was already possible except on FreeBSD.
As for writing, it's needed on FreeBSD for shared memory to be useable
at all, and since processes running as the user can already completely
access all their data, kitty config files, tty pipes, etc. allowing them
to write to the SHM used here doesnt grant any significant new
capability, since they could just write to ssh.conf in the kitty config
folder to get the ssh kitten to do whatever they like.

Fixes #5928
2023-01-25 23:34:31 +05:30
Kovid Goyal
e3040a9c91
Make the various path finding functions thread safe and cache their results 2023-01-25 16:24:27 +05:30
Kovid Goyal
a01d68ed85
... 2023-01-25 16:12:47 +05:30
Kovid Goyal
f070b17fee
Also load ~/.config/kitty/mime.types in Go code 2023-01-25 16:08:12 +05:30
Kovid Goyal
22d562ca41
DRYer 2023-01-25 15:38:23 +05:30
Kovid Goyal
102197fabe
Merge branch 'mime-types' of https://github.com/page-down/kitty 2023-01-25 15:28:40 +05:30
pagedown
83f505e209
Update known textual mimes to Python
Also add default aliases for JavaScript and XML in Go.
2023-01-25 16:42:15 +08:00
Kovid Goyal
5a86bc2411
Add default aliases for YAML and TOML 2023-01-25 11:54:09 +05:30
Kovid Goyal
b9c324586e
Also recognize a few well known MIME types as being textual 2023-01-24 18:30:46 +05:30
Kovid Goyal
41fb3c79c5
DRYer 2023-01-24 18:26:01 +05:30
Kovid Goyal
5066623089
better fix for file completion in Go
When neither extensions for mime are specified assume we want to match
all files.
2023-01-23 18:01:17 +05:30
Kovid Goyal
8e98b4123e
Fix completion for --password-file not completing file names 2023-01-23 17:58:31 +05:30
Kovid Goyal
8f88aab9d2
remove unused code 2023-01-23 17:51:10 +05:30
Kovid Goyal
d8bbb16d5e
Make the single instance data type checked 2023-01-23 17:45:11 +05:30
Kovid Goyal
60791bb57b
Session files: Expand environment variables 2023-01-23 17:34:53 +05:30
Kovid Goyal
11f98592f7
We still need full keyboard protocol for @ send-text 2023-01-23 16:33:08 +05:30
Kovid Goyal
97467acb1f
kitten @ cmd: Dont generate key release events
We dont need them and they sometimes can spill over into the prompt if
the command is very fast.
2023-01-23 16:18:46 +05:30
Kovid Goyal
cc1f0bc3fe
Function to drain controlling tty 2023-01-23 16:07:00 +05:30
Kovid Goyal
a009d6b258
kitty shell: Add completion for help and exit commands 2023-01-23 15:34:45 +05:30
Kovid Goyal
0903ae7b4d
Do not use prewarming for wrapped kittens 2023-01-23 15:21:04 +05:30
Kovid Goyal
35c1ebd3f9
Merge branch 'fix-open-actions-shell' of https://github.com/page-down/kitty 2023-01-23 14:03:54 +05:30
pagedown
352f940010
Fix SHELL env var in open-actions.conf and launch-actions.conf
Only the executable path is used when expanding `$SHELL`.
Also fix the non-working example `{SHELL}` in the documentation.
2023-01-23 14:15:27 +08:00
Kovid Goyal
1f00c27097
Also create an automatic text/plain alias when reading from clipboard 2023-01-22 22:04:53 +05:30
Kovid Goyal
6b2d37366f
Add trailing newline when printing available MIME types 2023-01-22 21:57:17 +05:30
Kovid Goyal
a4075ff041
X11: Fix a crash when listing clipboard MIME types and the clipboard is owned by self
Fixes #5920
2023-01-22 21:19:03 +05:30
Kovid Goyal
7a526d9588
clipboard kitten: When copying, automatically add a text/plain alias if there is at least one text/* MIME and no actual text/plain MIME 2023-01-22 20:41:37 +05:30
Kovid Goyal
5b4e4f032d
ask kitten: Output JSON when used standalone 2023-01-22 11:48:51 +05:30
Kovid Goyal
0a1b399447
... 2023-01-22 08:58:14 +05:30
Kovid Goyal
6a64df1afb
Abort show_error kitten if stdin is a tty 2023-01-22 08:48:55 +05:30
Kovid Goyal
dc1851acdb
Add some messages to kitten help for kittens that are not meant to be run by end users. 2023-01-22 08:46:29 +05:30
Kovid Goyal
096c1e328e
Improve progress printout 2023-01-22 08:41:38 +05:30
Kovid Goyal
1a44c2117b
GitHub requires a User-Agent 2023-01-22 08:00:29 +05:30
Kovid Goyal
bd13238d9b
Should only return ENOTSUPP if SHM_DIR doesnt exist, not the fil we are trying to open 2023-01-21 17:46:37 +05:30
Kovid Goyal
b1c27d4c2f
... 2023-01-21 17:42:50 +05:30
Kovid Goyal
dc0093cb51
SHM FS: Return a not supported error if SHM_DIR does not exist 2023-01-21 17:40:59 +05:30
Kovid Goyal
b1934ce267
kitten: When guessing MIME types use a builtin list as a fallback, generated from the MIME type definitions available on the build system 2023-01-21 17:35:41 +05:30
Kovid Goyal
16f767de7e
Remove unneeded code 2023-01-21 13:20:29 +05:30
Kovid Goyal
93e9332474
Use separate connections for every request to github
GitHub has been flaking out a lot of late with SSL errors when re-using
connections. Also allows us to get rid of the dependency on requests.
2023-01-21 12:56:00 +05:30
Kovid Goyal
81cc09aa61
Increase number of retries when uploading to github as it is getting flakier than ever 2023-01-20 07:11:52 +05:30
Kovid Goyal
e5bc7255b2
... 2023-01-20 07:07:28 +05:30
Kovid Goyal
75048d56bc
... 2023-01-19 07:54:03 +05:30
Kovid Goyal
19f853c29f
Add a note about all the things wrong with modifyOtherKeys 2023-01-18 22:57:56 +05:30
Kovid Goyal
26ca3f9bad
Simplify code 2023-01-18 16:16:11 +05:30
Kovid Goyal
bf7d27691c
Also add the EINTR fix from previous commit to writing to loop 2023-01-18 16:09:19 +05:30
Kovid Goyal
22532b4805
kitten @: Fix occasional hang until key is pressed while waiting for response from terminal
Fixes #5890
2023-01-18 16:07:42 +05:30
Kovid Goyal
68a006444e
Ensure that marking a child for removal works even when the child is still in the queue to be added
Fixes #5895
2023-01-18 15:43:41 +05:30
Kovid Goyal
2d846f53a1
... 2023-01-18 14:44:40 +05:30
Kovid Goyal
63077e5432
Dont do extremely small reads 2023-01-18 10:13:07 +05:30
Kovid Goyal
5edb1e2d6b
micro-optimization 2023-01-18 09:58:29 +05:30
Kovid Goyal
0c7b4df6fc
Ensure we are not using iterators when closing 2023-01-18 09:40:31 +05:30
Kovid Goyal
03abbb315a
Fix using cursor=none not working on text that has reverse video
Fixes #5897
2023-01-18 09:23:49 +05:30
Kovid Goyal
dc03c14af2
Fix #5896 2023-01-18 08:51:17 +05:30
Kovid Goyal
821f52a748
... 2023-01-17 12:39:41 +05:30
Kovid Goyal
750f2fa4d0
Use go 1.20 facilities for unsafe string <-> bytes 2023-01-17 12:38:54 +05:30
Kovid Goyal
009fd6418c
Fix #5894 2023-01-17 12:05:23 +05:30
Kovid Goyal
ce161e610f
... 2023-01-17 11:52:06 +05:30
Kovid Goyal
b1b9c3704b
Merge branch 'patch-2' of https://github.com/eltociear/kitty 2023-01-17 08:38:57 +05:30
Ikko Eltociear Ashimine
fd245e894b
Fix typo in overview.rst
specifed -> specified
2023-01-17 12:05:46 +09:00
Kovid Goyal
59170a3627
Add a note to CONTRIBUTING.md about bug management 2023-01-16 17:16:58 +05:30
Kovid Goyal
61143557a9
Re-organize the terminfo FAQ entries into a single one 2023-01-16 16:32:35 +05:30
Kovid Goyal
9a77fdcd04
A new option undercurl_style to control the rendering of undercurls
Fixes #5883
2023-01-16 14:23:10 +05:30
Kovid Goyal
0c8ec3c57b
Cleanup previous PR 2023-01-15 13:01:43 +05:30
Jake(Jaehak Song)
b799eba81e
Save the overlay when DECTCEM is turned off and restore it when turned on. 2023-01-15 13:01:43 +05:30
Jake(Jaehak Song)
9d1de50bf9
shell.nix: add a missing dependency 'UniformTypeIdentifiers' for macOS 2023-01-15 13:01:43 +05:30
Kovid Goyal
d55a9b582b
Use ruff for import sorting 2023-01-15 11:07:10 +05:30
Kovid Goyal
865fc24975
When reporting unused activity in a window, ignore activity that occurs soon after a window resize
Fixes #5881
2023-01-15 09:09:07 +05:30
Kovid Goyal
45b0788f28
Dont rely on existence of sh to report exec failure 2023-01-14 16:03:34 +05:30
Kovid Goyal
bc73273cb3
... 2023-01-14 15:58:26 +05:30
Kovid Goyal
dd5cfe38b7
Update README 2023-01-14 15:56:03 +05:30
Kovid Goyal
6b8e5ea225
Rename kitty-tool to kitten
It's easier to type, and cuter.

Also, most, if not all of the TUI parts of
kitty's kittens will eventually be re-written into kitten.

The only downside I can see is that we cant tab complete kitty
anymore, but hopefully there will be less reason to run kitty
from the shell as command line tools migrate to kitten.

Meowrrrr!!!
2023-01-14 15:44:52 +05:30
Kovid Goyal
60310ced05
Also build 32-bit ARM kitty-tool for Linux 2023-01-14 11:20:31 +05:30
Kovid Goyal
f61b007645
... 2023-01-11 11:53:43 +05:30
Kovid Goyal
d4e34a4c31
themes kitten: Nicer error message when no internet connection is present
Fixes #5877
2023-01-11 09:00:58 +05:30
Kovid Goyal
15524ee0fb
... 2023-01-10 19:41:46 +05:30
Kovid Goyal
58a4b4218e
... 2023-01-10 17:35:15 +05:30
Kovid Goyal
ac67d9c72d
Allow dumping bytes sent to child for debugging 2023-01-10 15:39:56 +05:30
Kovid Goyal
b9692d480a
Allow passing memoryview to paste() 2023-01-10 10:56:03 +05:30
Kovid Goyal
3a2da22509
DRYer 2023-01-10 09:35:15 +05:30
Kovid Goyal
bf8d0c9732
Fix a bug when copying large amounts of text with OSC 52 introduced by the new multi-format clipboard support 2023-01-10 09:29:54 +05:30
Kovid Goyal
836b652f4d
Enable checks for unused noqa 2023-01-09 17:28:35 +05:30
Kovid Goyal
69255f7525
broadcast kitten: Allow pressing a key to stop echoing of input into the broadcast window itself 2023-01-09 17:19:35 +05:30
Kovid Goyal
6e41409a3f
Dont run isort on generated conf files 2023-01-09 16:51:59 +05:30
Kovid Goyal
7fe5d7b58f
Replace isort with ruff 2023-01-09 16:47:42 +05:30
Kovid Goyal
f15d27bb62
Use ruff on CI 2023-01-09 15:55:45 +05:30
Kovid Goyal
a068e3e655
Fix issues reported by ruff 2023-01-09 15:54:41 +05:30
Kovid Goyal
d248d5ad75
Move to pyproject.toml and ruff 2023-01-09 15:49:49 +05:30
Kovid Goyal
44866a6e79
Add sample Go code to get screen size 2023-01-07 15:00:51 +05:30
Kovid Goyal
1fe84f6057
Update icat kitten docs 2023-01-07 14:37:32 +05:30
Kovid Goyal
41207aa830
kitty @ get-colors: Report the current tab bar colors for the active OS window rather than configured values. Fixes #5865 2023-01-07 13:56:36 +05:30
Kovid Goyal
66a2e6f80d
... 2023-01-06 22:06:58 +05:30
Kovid Goyal
397ac36011
Also mention terminal multiplxers can cause graphics to fail 2023-01-06 16:36:39 +05:30
Kovid Goyal
02063a5a6a
Make some variables local no need for them to be global 2023-01-06 16:35:17 +05:30
Kovid Goyal
b3926ae9e7
Remove unused code 2023-01-06 16:32:04 +05:30
Kovid Goyal
3743ae50e7
Simplify icat code and write to STDOUT rather than the terminal device
The terminal device is now used only for detection.
2023-01-06 16:16:15 +05:30
Kovid Goyal
2205bf4426
add a comment 2023-01-06 14:42:14 +05:30
Kovid Goyal
def35078d1
... 2023-01-06 14:26:15 +05:30
Kovid Goyal
1b5fac3189
Cleanup previous PR 2023-01-06 14:25:21 +05:30
Kovid Goyal
dab7f71d2f
Merge branch 'master' of https://github.com/TrellixVulnTeam/kitty_864P 2023-01-06 14:17:38 +05:30
TrellixVulnTeam
1223130ef7 Adding tarfile member sanitization to extractall() 2023-01-06 08:07:51 +00:00
Kovid Goyal
4e90ae68a4
... 2023-01-06 11:33:47 +05:30
Kovid Goyal
e16e3c1582
Clarify the common use case for --config-file-name 2023-01-06 10:42:46 +05:30
Kovid Goyal
ddf36383b4
Dont need to fetch the current version since GitHub provides a redirecting constant download URL 2023-01-05 20:09:32 +05:30
Kovid Goyal
77a3916f6f
We need go >= 1.19 2023-01-05 19:41:42 +05:30
Kovid Goyal
5d42d1f955
Remove the old python icat implementation
Keep the python backend code as it is used by the diff kitten to display
image diffs.
2023-01-05 19:34:12 +05:30
Kovid Goyal
a2c68a927e
icat: When using --place ensure screen doesnt scroll by leaving cursor at top-left corner of image. 2023-01-05 19:15:13 +05:30
Kovid Goyal
cab7856495
Finish resize handling for the magick engine 2023-01-05 19:15:13 +05:30
Kovid Goyal
c317c934f3
More work on ImageMagick 2023-01-05 19:15:13 +05:30
Kovid Goyal
4d21be9eb5
Port python's shutil.which() 2023-01-05 19:15:13 +05:30
Kovid Goyal
fd71d2035d
Start work on rendering with ImageMagick 2023-01-05 19:15:13 +05:30
Kovid Goyal
7ebb281855
Allow controlling num of CPUs for images operations 2023-01-05 19:15:13 +05:30
Kovid Goyal
2d3da1db6d
Dont scan all pixels of JPEG images when EXIF rotated to check for opacity 2023-01-05 19:15:13 +05:30
Kovid Goyal
458adf967a
Dont use extra memory for mirror operations 2023-01-05 19:15:13 +05:30
Kovid Goyal
eec4c6b802
Dont transmit animation control commands for non-animated images 2023-01-05 19:15:13 +05:30
Kovid Goyal
0b9b207513
Implement scaling for GIF as well 2023-01-05 19:15:13 +05:30
Kovid Goyal
7e8017604e
Copy comment explaining min gap and set it to the correct value 2023-01-05 19:15:13 +05:30
Kovid Goyal
520b935cd3
... 2023-01-05 19:15:12 +05:30
Kovid Goyal
9cb83a6ec2
... 2023-01-05 19:15:12 +05:30
Kovid Goyal
7c2317d301
Fix divide by zero 2023-01-05 19:15:12 +05:30
Kovid Goyal
7237e5cf9c
Get GIF basically working 2023-01-05 19:15:12 +05:30
Kovid Goyal
cd5dab581b
DRYer 2023-01-05 19:15:12 +05:30
Kovid Goyal
481cebbd29
Transmission format should be per frame 2023-01-05 19:15:12 +05:30
Kovid Goyal
4623f580b9
Get 24 bit RGB transmission working 2023-01-05 19:15:12 +05:30
Kovid Goyal
6291d0d400
Code to check if an image is Opaque 2023-01-05 19:15:12 +05:30
Kovid Goyal
36d82267bb
... 2023-01-05 19:15:12 +05:30
Kovid Goyal
f9feb4954a
Wire up pasting to RGB 2023-01-05 19:15:12 +05:30
Kovid Goyal
d192dcb0d7
Code to convert images to NRGB 2023-01-05 19:15:12 +05:30
Kovid Goyal
143fd6e4dd
Start work on transmitting RGB images 2023-01-05 19:15:12 +05:30
Kovid Goyal
df06578c2d
Implement --scale-up and --place 2023-01-05 19:15:12 +05:30
Kovid Goyal
73a055fe12
Fix failing test 2023-01-05 19:15:12 +05:30
Kovid Goyal
1fa1a478d9
Get --background working 2023-01-05 19:15:12 +05:30
Kovid Goyal
5a3a547c65
Work on adding support for rendering transforms 2023-01-05 19:15:12 +05:30
Kovid Goyal
373ab95f14
Basic go based rendering 2023-01-05 19:15:11 +05:30
Kovid Goyal
7f866b2b1f
Start work on rendering images with Go 2023-01-05 19:15:11 +05:30
Kovid Goyal
24db38ba7e
Set data size for SHM transmission as on some platforms the actual SHM size is not equal to the requested size 2023-01-05 19:15:11 +05:30
Kovid Goyal
efdfaaec30
... 2023-01-05 19:15:11 +05:30
Kovid Goyal
d694f48c91
Get the other two transmission modes working as well 2023-01-05 19:15:11 +05:30
Kovid Goyal
5562a4d52f
Get file mode transmission working for unmodified PNG 2023-01-05 19:15:11 +05:30
Kovid Goyal
ce4c71c465
Start work on the transmit backend 2023-01-05 19:15:11 +05:30
Kovid Goyal
31df90a64e
Dont allow abort while waiting for query response 2023-01-05 19:15:11 +05:30
Kovid Goyal
22d69d24d0
Fix panic when no timers are left after dispatch 2023-01-05 19:15:11 +05:30
Kovid Goyal
d76e0850ae
More work on porting icat 2023-01-05 19:15:11 +05:30
Kovid Goyal
b520882b62
... 2023-01-05 19:15:11 +05:30
Kovid Goyal
79acab1547
More work on porting icat 2023-01-05 19:15:11 +05:30
Kovid Goyal
4690f3c7c0
... 2023-01-05 19:15:11 +05:30
Kovid Goyal
cf1d9eb303
Parse more icat cli flags 2023-01-05 19:15:11 +05:30
Kovid Goyal
ba2a3f228d
Implement --detect-timeout 2023-01-05 19:15:11 +05:30
Kovid Goyal
a757587ea2
Fix SHM on OpenBSD 2023-01-05 19:15:10 +05:30
Kovid Goyal
ea756db544
Get transmission medium detection working 2023-01-05 19:15:10 +05:30
Kovid Goyal
2d1a2c30bf
MMap.Name() should return the SHM name not the full filesystem path 2023-01-05 19:15:10 +05:30
Kovid Goyal
6ace082bc2
Add openbsd and dragonfly support to shm 2023-01-05 19:15:10 +05:30
Kovid Goyal
7e161ea94b
Get syscall based SHM working 2023-01-05 19:15:10 +05:30
Kovid Goyal
d01d5297b8
Start work on a SHM implementation in Go 2023-01-05 19:15:10 +05:30
Kovid Goyal
7a1140cd03
Start work on porting icat to Go 2023-01-05 19:15:10 +05:30
Kovid Goyal
aab81c2d32
Turn off hyperlink target display by default
I find it too intrusive for limited benefit. Most the hyperlinks I
click come from trusted programs anyway.
2023-01-05 15:30:43 +05:30
Kovid Goyal
49418c2f53
Show the hyperlink target bar on the top more often than the bottom. This is because the text cursor is usually closer to the bottom. 2023-01-05 15:28:02 +05:30
Kovid Goyal
a548e3eb4d
Fix some animations pausing before starting 2023-01-04 11:18:17 +05:30
Kovid Goyal
779a7b7deb
... 2023-01-04 11:15:47 +05:30
Kovid Goyal
c83a8b0773
zsh completion; Fix leading ~ in filenames being quoted on insertion into commandline 2023-01-04 11:07:56 +05:30
Kovid Goyal
035c3de4bb
Add completion for file args to clipboard kitten 2023-01-04 10:39:24 +05:30
Kovid Goyal
e2543e8968
Fix #5852 2023-01-04 08:20:04 +05:30
Kovid Goyal
bc2492c212
dont show URL targetbar when mouse is hidden 2023-01-01 12:11:19 +05:30
Kovid Goyal
c03310b5e5
Cleanup previous PR 2022-12-31 14:03:16 +05:30
Kovid Goyal
bd33cef092
Merge branch 'sequence' of https://github.com/ppwwyyxx/kitty 2022-12-31 13:38:37 +05:30
Yuxin Wu
832506d785 move is_modifier_key to glfw.c and expose in Python 2022-12-30 23:32:46 -08:00
Yuxin Wu
13b09346b9 reset current window after processing sequence 2022-12-30 23:07:50 -08:00
Yuxin Wu
1c10c5fcc4 replay modifier key as well 2022-12-30 23:07:50 -08:00
Yuxin Wu
510c5bd73b handle release 2022-12-30 23:07:49 -08:00
Yuxin Wu
774fdd7e94 Send sequence events to child if they don't match kitty. 2022-12-30 23:07:36 -08:00
Kovid Goyal
58497161c0
X11: When pasting text/plain try UTF8_STRING first then text/plain/charset=utf-8
Fixes #5842
Also fixes pasting from GTK+2 applications like leafpad.
2022-12-30 22:20:43 +05:30
Kovid Goyal
f831c34813
Update the FAQ on vim with a comprehensive set of settings needed to get it to work with modern terminals 2022-12-30 13:52:08 +05:30
Kovid Goyal
456af90ad2
Remote control: Allow matching for self window even over sockets when run inside a kitty window
Have kitty-tool send the value of KITTY_WINDOW_ID if present.
2022-12-30 12:17:31 +05:30
Kovid Goyal
c18bff7821
Remote control: Allow matching the parent of an overlay window 2022-12-30 11:29:05 +05:30
Kovid Goyal
080d1bf935
Fox object lifetime management 2022-12-30 10:08:49 +05:30
Kovid Goyal
4f9ed6546a
Pass key events mapped to scroll actions to the program running in the terminal when the terminal is in alternate screen mode
Fixes #5839
2022-12-30 08:54:31 +05:30
Kovid Goyal
c76bbeabd6
... 2022-12-30 08:34:58 +05:30
Kovid Goyal
0f24ce60f8
Fix @ send-text --stdin always assuming STDIN is a tty 2022-12-30 08:29:30 +05:30
Kovid Goyal
6a06769931
... 2022-12-29 17:27:57 +05:30
Kovid Goyal
468b6fab02
Also use sanitized URL for allow_hyperlinks=ask 2022-12-29 17:05:18 +05:30
Kovid Goyal
306f9e5735
Prettify URLs before displaying them to the user 2022-12-29 17:04:02 +05:30
Kovid Goyal
f4ac03b791
Show the target of terminal hyperlinks when hovering over them with the mouse
Fixes #5830
2022-12-29 16:43:45 +05:30
Kovid Goyal
b8abdd2b50
Retry failed deletes from github 2022-12-29 12:50:16 +05:30
Kovid Goyal
e673747ef4
readline: add alt+arrow to move by word default binding. Common on macOS 2022-12-27 10:59:13 +05:30
Kovid Goyal
6e4376e44e
A few more wrapping serialization tests 2022-12-27 09:11:15 +05:30
Kovid Goyal
f6801d48d1
Add a test to ensure \n does not change wrapping status 2022-12-27 08:48:26 +05:30
Kovid Goyal
ca57198927
Merge branch 'patch-1' of https://github.com/eltociear/kitty 2022-12-26 21:00:33 +05:30
Ikko Ashimine
e78000c879
Fix typo in iqsort.h
comparision -> comparison
2022-12-27 00:27:16 +09:00
Kovid Goyal
68cf9f7514
Switch to tracking linewrap on the last cell in a line
This allows us to have newline not affect the wrap status of a line.

Now a lines wrapping status is changed only when the last cell
in the line is changed. This actually matches the behavior of many other
terminal emulators so is probably a good thing from a ecosystem
compatibility perspective.

The fish shell expects this weird behavior of newline not changing
wrapping status, for unknown reasons, which is the actual motivation for
doing all this work.

Fixes #5766
2022-12-26 20:26:21 +05:30
Kovid Goyal
4556f5b8f1
Merge branch 'pr-fix-image-scrolling' of https://github.com/sergei-grechanik/kitty 2022-12-26 09:51:22 +05:30
Sergei Grechanik
32d8aac808 Fix scrolling images within margins
This commit fixes an off-by-one error in image scrolling that caused
images to not be scrolled or to be cropped at the wrong line.
2022-12-25 15:34:54 -08:00
Kovid Goyal
2e81d00c92
make go fmt happy 2022-12-24 10:53:17 +05:30
Kovid Goyal
cd92d50a0d
Keyboard protocol: Remove CSI R from the allowed encodings of the F3 key as it conflicts with the *Cursor Position Report* escape code 2022-12-24 10:32:28 +05:30
Kovid Goyal
155dd426c5
Merge branch 'ssh-kitten' of https://github.com/page-down/kitty 2022-12-24 10:04:58 +05:30
pagedown
a8f2816ac2
ssh kitten: Compile terminfo with tic coming from pkgsrc under NetBSD 2022-12-24 11:53:52 +08:00
pagedown
0ddc5d030c
ssh kitten: Fall back to using openssl when base64 does not exist 2022-12-24 11:53:45 +08:00
Kovid Goyal
a2c2d81373
Cleanup readline prompt rendering 2022-12-23 15:23:42 +05:30
Kovid Goyal
307ce1cf87
Remove not needed wrapper function since now we use a struct to set attrs 2022-12-23 13:50:55 +05:30
Kovid Goyal
61ceb12e07
Merge branch 'singlekey-endian' of https://github.com/jamessan/kitty
Fixes #5802
2022-12-23 08:12:23 +05:30
James McCoy
b45dc20693
Define SingleKey bitfields according to endianness
Closes #5802
2022-12-22 15:07:54 -05:00
Kovid Goyal
bcedbe5ec1
Revert "Change the terminfo entry for cud1 to not alter text to comply with the terminfo man page"
This reverts commit d8284befd3dc3005568b28a1247553e22548c4eb.
See https://github.com/kovidgoyal/kitty/issues/5766#issuecomment-1363025173
2022-12-22 21:49:32 +05:30
Kovid Goyal
038639e2d3
Bump bundled zlib 2022-12-22 19:26:34 +05:30
Kovid Goyal
c857492f37
Merge pull request #5803 from jamessan/runtime-dir
tests: Use tempdir for XDG_RUNTIME_DIR
2022-12-22 11:07:44 +05:30
Kovid Goyal
42923ab673
... 2022-12-22 10:19:34 +05:30
James McCoy
9afd0309fc
tests: Use tempdir for XDG_RUNTIME_DIR 2022-12-21 22:21:48 -05:00
Kovid Goyal
b9d098de2d
Update mpv support link to point to the actual merged commit 2022-12-22 07:16:53 +05:30
Kovid Goyal
09e6f740de
Merge branch 'macos-shortcuts' of https://github.com/page-down/kitty 2022-12-21 16:41:43 +05:30
pagedown
1023084eb9
macOS: Allow to customize Hide, Minimize, and Quit global menu shortcuts
All previously hard-coded shortcuts under macOS can be configured now.
2022-12-20 21:08:26 +08:00
Kovid Goyal
aa9679e56b
Fix typo in key definition 2022-12-20 15:01:40 +05:30
Hector Martin
84aebae6a8 Downgrade OpenGL version requirement to 3.1
There are only a few features required from newer versions, and they
can be achieved via extensions. This significantly improves compatibility.
2022-12-20 16:22:05 +09:00
Kovid Goyal
d8284befd3
Change the terminfo entry for cud1 to not alter text to comply with the terminfo man page
Fixes #5766
2022-12-20 09:16:05 +05:30
Kovid Goyal
e4ee2cf995
Move the alt+left/right binding into zsh integration
It works OOTB in bash and fish already.
2022-12-19 11:25:12 +05:30
Kovid Goyal
e3f6f47f10
... 2022-12-19 05:35:18 +05:30
Kovid Goyal
e5941b1b44
Add a link for the vim t_ut issue 2022-12-18 22:32:20 +05:30
Kovid Goyal
65c64d8745
macOS: Bind :kbd:option+left and :kbd:option+right to :kbd:alt+b and :kbd:alt+f. This mimics the default bindings in Terminal.app
Fixes #5793
2022-12-18 20:34:42 +05:30
Kovid Goyal
40093a4702
Add tests for GraphicsCommand serialization 2022-12-18 11:56:30 +05:30
Kovid Goyal
3815cba8f3
Add stringer interface to GraphicsCommand 2022-12-17 15:34:43 +05:30
Kovid Goyal
7410cd62f9
remove unused code 2022-12-17 09:00:44 +05:30
Kovid Goyal
ae0a8e73d2
... 2022-12-17 08:59:56 +05:30
Kovid Goyal
8f3a8c828f
Add an APC to GraphicsCommand parser 2022-12-16 21:05:17 +05:30
Kovid Goyal
6efb5dc2c2
Auto-create an OS Window if none exists on new_tab 2022-12-16 19:34:37 +05:30
Kovid Goyal
bb33f6c0ac
Start work on graphics support in kitty-tool 2022-12-16 18:06:52 +05:30
Kovid Goyal
d34284ee1c
Merge branch 'docs' of https://github.com/page-down/kitty 2022-12-16 13:06:20 +05:30
pagedown
74cae7b787
... 2022-12-16 14:27:02 +08:00
Kovid Goyal
c6360537e5
Try to fix tests failing on Python 3.11 2022-12-16 10:05:05 +05:30
Kovid Goyal
7d28d7413f
Merge branch 'patch-1' of https://github.com/lodisy/kitty 2022-12-16 09:41:10 +05:30
Michael
d3f3e9ec38
docs: fix overview.rst
add missing `be`, L88
2022-12-16 12:06:25 +08:00
Kovid Goyal
928becece4
Fix #5773 2022-12-14 15:45:43 +05:30
Kovid Goyal
80db167abb
Add mpv to the list of things that speak the graphics protocol 2022-12-14 10:31:56 +05:30
Kovid Goyal
a5a6880a19
Respect enable_audio_bell when a layout action fails 2022-12-14 06:53:14 +05:30
Kovid Goyal
da13d03b98
Merge branch 'rc-launch' of https://github.com/page-down/kitty 2022-12-13 20:32:20 +05:30
pagedown
0a5c409a12
Remote control: Add the missing option value overlay-main 2022-12-13 22:48:46 +08:00
Kovid Goyal
eeb772ad07
@launch: When an overlay window is specified in a particular tab via --match use the active window of that tab as the base, not the current tab. Fixes #5768 2022-12-13 20:15:21 +05:30
Kovid Goyal
2b66775f45
explicitly ignore a few errors 2022-12-13 16:19:46 +05:30
Kovid Goyal
3f65ce0e71
Make sizes explicit in a few reallocs 2022-12-13 12:11:37 +05:30
Kovid Goyal
d235b673d1
also test \ is escaped 2022-12-13 10:21:19 +05:30
Kovid Goyal
0ab618c2dc
Fix #5767 2022-12-13 10:20:02 +05:30
Kovid Goyal
fefafda9a0
Fix #5764 2022-12-12 21:26:54 +05:30
Kovid Goyal
902373ed20
Also make lists and dicts of strings escape code safe 2022-12-12 19:24:44 +05:30
Kovid Goyal
aac57550c9
rc protocol: Encode strings values in an escape code safe way
Go emits UTF-8 encoded JSON not ascii encoded JSON. Still need to fix
lists and dicts of strings
2022-12-12 18:48:54 +05:30
Kovid Goyal
95e05ce9ec
Fix #5761 2022-12-12 16:49:18 +05:30
Kovid Goyal
b6c6316b7b
Merge branch 'rc-ls' of https://github.com/page-down/kitty 2022-12-12 10:32:51 +05:30
pagedown
91576cc42f
Remote control: Keep the same naming style for ls command output 2022-12-12 12:53:58 +08:00
Kovid Goyal
032e01ebf7
... 2022-12-11 20:55:06 +05:30
Kovid Goyal
bd70100e09
Fix typo in FAQ 2022-12-10 13:00:09 +05:30
Kovid Goyal
ff6d2e3c10
Merge branch 'kitten-hyperlink-grep' of https://github.com/page-down/kitty 2022-12-10 12:58:57 +05:30
pagedown
2f292bb5d2
DRYer 2022-12-10 15:13:19 +08:00
pagedown
52cf443daf
Docs: rg --no-heading has been handled 2022-12-10 15:12:32 +08:00
Kovid Goyal
f03a665e09
Remote control: When matching windows allow using negative id numbers to match recently created windows
Fixes #5753
2022-12-10 11:17:55 +05:30
Kovid Goyal
66e7919171
Add a FAQ entry about not being able to use a keybinding in a terminal program
I am tired of people asking this same question endlessly. At least now I
can just point them to this link.
2022-12-08 14:16:01 +05:30
Kovid Goyal
1289dd2ff0
Cleanup previous PR 2022-12-08 13:30:54 +05:30
Kovid Goyal
fa50e0d6cc
Merge branch 'kitten-hyperlinked-grep' of https://github.com/page-down/kitty 2022-12-08 13:26:28 +05:30
pagedown
8c7a5288ae
hyperlinked_grep kitten: Handle more rg command line options
Skip for unsupported options.
2022-12-08 14:51:13 +08:00
Kovid Goyal
7fe5c79d53
Also mask signals when SIGNALFD is not available
This makes behavior across platforms consistent.
Fixes #4636
2022-12-07 12:25:14 +05:30
Kovid Goyal
ea5ffa4304
... 2022-12-07 10:18:15 +05:30
Kovid Goyal
89b32e4545
Update changelog with clipboard kitten new features 2022-12-07 10:04:02 +05:30
Kovid Goyal
879b27a045
... 2022-12-07 06:48:19 +05:30
Kovid Goyal
9cb0e4d09d
Block handled signals early in startup before glfw is initialized to ensure that if the graphics libraries start a thread behind our backs, that threads defaults to haveing the signals blocked unless the library explicitly unblocks them. See #4636 2022-12-07 06:35:18 +05:30
Kovid Goyal
94410f2866
Handle EBUSY as well 2022-12-06 12:20:20 +05:30
Kovid Goyal
a3ba8647ba
Document the new OSC 5522 protocol 2022-12-06 12:18:55 +05:30
Kovid Goyal
f35ee1bb40
Fix using primary selection with the extended protocol 2022-12-06 11:15:52 +05:30
Kovid Goyal
23b3b171fa
Merge branch 'conf' of https://github.com/page-down/kitty 2022-12-05 17:54:10 +05:30
pagedown
30b25709d2
Fix the base path for envinclude 2022-12-05 14:53:26 +08:00
pagedown
9c488bb877
Docs: Remove extra backslashes from commented config
Update docs to use \e in the example.
2022-12-05 14:27:40 +08:00
Kovid Goyal
14a33dbd94
Put the non-boilerplate functions in their proper place 2022-12-05 08:07:50 +05:30
Kovid Goyal
e37ee422b6
... 2022-12-05 07:53:30 +05:30
Kovid Goyal
d7d96c2e7b
When using the include directive in kitty.conf make the environment variable KITTY_OS available for OS specific config 2022-12-04 21:03:24 +05:30
Kovid Goyal
fda4aa21a1
When drawing the tab bar have the default left and right margins drawn in a color matching the neighboring tab
Fixes #5719
2022-12-04 20:51:41 +05:30
Kovid Goyal
3cbca4955e
... 2022-12-04 20:48:15 +05:30
Kovid Goyal
8e0e70e2d6
Simplify passing colors to the borders shader 2022-12-04 16:08:32 +05:30
Kovid Goyal
7a348d6ef1
Store updated tab bar edge colors on every tab bar redraw 2022-12-04 14:38:56 +05:30
Kovid Goyal
cf8f904720
Function to guess the effective color at the edge of the current screen line 2022-12-04 14:23:21 +05:30
Kovid Goyal
fe53555dba
Document the additions to the clipboard kitten 2022-12-04 11:37:02 +05:30
Kovid Goyal
b644a42a48
Allow using wildcard mime types when copying from clipboard 2022-12-03 14:06:16 +05:30
Kovid Goyal
5c9c9a67bc
Fix make asan
Suppress leak detection when running gen-go-code.py otherwise it fails
since python always leaks
2022-12-03 12:34:32 +05:30
Kovid Goyal
76f6288e69
... 2022-12-03 12:25:23 +05:30
Kovid Goyal
6422b323c6
Implement MIME aliases for clipboard 2022-12-03 12:20:03 +05:30
Kovid Goyal
a622a149f6
Allow arbitrary bytes in the mime metadata key 2022-12-03 09:21:36 +05:30
Kovid Goyal
fa6527cdf3
add note about how MIME types are detected 2022-12-03 08:35:58 +05:30
Kovid Goyal
0b293428c4
X11: Fix reading list of available mime types 2022-12-03 08:16:59 +05:30
Kovid Goyal
26e8a5186a
Avoid extra roundtrip when only reading clipboard mime types 2022-12-03 08:06:48 +05:30
Kovid Goyal
bde737fa38
Finish implementation of clipboard writing 2022-12-03 08:02:27 +05:30
Kovid Goyal
71e09ba1fb
Fix show_key kitten showing incorrect CSI encoding for F3 2022-12-01 23:33:08 +05:30
Kovid Goyal
3e69cf81af
DRYer 2022-12-01 22:40:47 +05:30
Kovid Goyal
f5d2c35755
Move implementation of +hold to Go
No need to pay python interpreter startup cost for --hold
2022-12-01 22:34:56 +05:30
Kovid Goyal
38a7fa73e3
Simplify filter mode operation
Dont need channels and goroutines as writing in the loop is already
asnychronous
2022-12-01 19:54:57 +05:30
Kovid Goyal
fdd42d5f19
Implement kitty side write OSC 5522 2022-12-01 18:18:06 +05:30
Kovid Goyal
fe75493c37
Better error messages 2022-12-01 18:17:53 +05:30
Kovid Goyal
e187265d04
Dont truncate the output file just to get tis permission bits 2022-12-01 14:13:28 +05:30
Kovid Goyal
0a985134e2
Ensure permissions are correct when using atomic writes 2022-12-01 14:04:52 +05:30
Kovid Goyal
e555d963b1
DRYer 2022-12-01 13:58:06 +05:30
Kovid Goyal
3601488b26
Add a generic Values() 2022-12-01 13:47:06 +05:30
Kovid Goyal
f29ce19097
Reading arbitrary MIME from clipboard now works 2022-12-01 13:35:44 +05:30
Kovid Goyal
f6ab641b00
Clarify the action of CSI < u in Quickstart 2022-11-30 16:28:34 +05:30
Kovid Goyal
722a1020fa
Cleaner implementation of max_tab_title_length
Ensures that tab decorations are not affected
2022-11-29 23:20:39 +05:30
Kovid Goyal
fbd19f3bde
Merge branch 'docs' of https://github.com/page-down/kitty 2022-11-29 22:10:57 +05:30
Kovid Goyal
3cf874f6e9
Work on implementing read support in the clipboard kitten 2022-11-29 22:07:51 +05:30
pagedown
02b206eeb8
Docs: Slightly adjust the description of tab_title_max_length
Note the associated GitHub PR ID in the changelog.
2022-11-30 00:20:32 +08:00
Kovid Goyal
5c50e3869c
Change the new option to limit tab title lengths to apply to the length of the title, as documented, nit the full tab 2022-11-29 17:41:27 +05:30
Kovid Goyal
6f66bbd424
... 2022-11-29 15:15:01 +05:30
Kovid Goyal
2697ddaec3
Dont ask for permission when reading only the mime types available in the clipboard 2022-11-29 15:09:01 +05:30
Kovid Goyal
d6dcdf0751
Merge branch 'tab_max_length' of https://github.com/fratajczak/kitty 2022-11-29 14:59:18 +05:30
Kovid Goyal
11724c8a5f
Terminal end of OSC 5522 read requests 2022-11-29 14:55:40 +05:30
Ferdinand Ratajczak
b6792a6d71 Add option to limit length of tab titles 2022-11-29 09:50:32 +01:00
Kovid Goyal
f0d61c2de9
Add debug output for key encoding state modifications 2022-11-29 11:20:19 +05:30
Kovid Goyal
35ae689818
Improve debug encoded key output 2022-11-29 08:06:07 +05:30
Kovid Goyal
1305199bdf
Output the bytes sent to the child in --debug-input 2022-11-29 07:56:06 +05:30
Kovid Goyal
c62c31f776
More mypy bugs
It cant handle putting a ClipboardTyple fielf on ReadRequest. SO just
use a bool as we really only have two types anyway.
2022-11-28 22:03:04 +05:30
Kovid Goyal
defef3f88c
Make mypy happy 2022-11-28 21:05:10 +05:30
Kovid Goyal
3ee9f723f2
The legacy osc 52 protocol now works with the new clipboard requests manager class 2022-11-28 20:53:56 +05:30
Kovid Goyal
a8725d6307
Start work on a new clipboard protocol to allow terminal programs to access more than just text/plain content from the clipboard 2022-11-28 14:23:03 +05:30
Kovid Goyal
4c72f92939
Wayland GNOME: Workaround for latest mutter release breaking full screen for semi-transparent kitty windows
Destroy the CSD surfaces when window goes full screen.
Fixes #5677
2022-11-28 14:19:13 +05:30
Kovid Goyal
2150f261ee
Merge branch 'ksi-fish-cwd' of https://github.com/page-down/kitty 2022-11-27 11:46:42 +05:30
pagedown
f720bc9fab
Shell integration: Report cwd on the fish prompt event 2022-11-27 14:07:19 +08:00
Kovid Goyal
d92f89e47f
ZSH integration: Report cwd on every new prompt draw
Handles the case of a command reporting a different cwd to the terminal.
2022-11-27 10:09:25 +05:30
Kovid Goyal
c54a4021ef
Update docs to use \e instead of \x1b for esc since we now support it 2022-11-27 10:06:04 +05:30
Kovid Goyal
375fa73826
Delegate kitty +kitten clipboard to kitty-tool 2022-11-26 20:09:43 +05:30
Kovid Goyal
5eb2142d70
Use a define rather than a generated file for wrapped kittens 2022-11-26 16:16:45 +05:30
Kovid Goyal
00223c5bba
Merge branch 'hostname' of https://github.com/page-down/kitty 2022-11-26 15:43:46 +05:30
Kovid Goyal
aa9080d375
Add a note about using single quotes when passing arguments with backslash escapes to send-text
One could of course also use double quotes and escape the backslash or
just escape the backslash but I dont think we need to explain shell
quoting fully here.
2022-11-26 15:38:22 +05:30
Kovid Goyal
8d45f5011b
Add support for the 🔗 role to prettify 2022-11-26 15:34:20 +05:30
Kovid Goyal
b3f096b03b
kitty shell: Fix pressing enter while cursor is not at end of line causes line to be truncated visually 2022-11-26 15:30:49 +05:30
Kovid Goyal
a721ffeb7d
Finish porting clipboard kitten to Go 2022-11-26 15:15:30 +05:30
pagedown
6a1b456bac
DRYer: Get hostname 2022-11-26 16:08:40 +08:00
Kovid Goyal
63a08dc6cc
kitty-tool @: Fix extra newline being printed when a command returns no response 2022-11-26 05:02:32 +05:30
Kovid Goyal
4969611bdb
Handle backslash escapes in :code: blocks 2022-11-25 22:03:13 +05:30
Kovid Goyal
5d3a9f2628
Use base64 for args in old rc code as well 2022-11-25 21:12:59 +05:30
Kovid Goyal
15a7aeff4d
Fix kitty-tool @ send-text not processing ANSI escapes 2022-11-25 21:09:51 +05:30
Kovid Goyal
f9a22d0bc7
Port ANSI escape code parser to Go 2022-11-25 21:03:09 +05:30
Kovid Goyal
402c8b6803
Use ANSI C escapes rather than python string literals 2022-11-25 19:10:15 +05:30
Kovid Goyal
ac60715ee2
Merge branch 'docs' of https://github.com/page-down/kitty 2022-11-25 17:34:46 +05:30
Kovid Goyal
cfc6bd4da5
Native code implementation for expanding ANSI escape codes 2022-11-25 17:33:41 +05:30
Kovid Goyal
4d3f3b5e91
Start moving clipboard kitten to kitty-tool 2022-11-25 12:58:10 +05:30
pagedown
55b5a45e27
Docs: Fix missing backslashes 2022-11-25 12:03:34 +08:00
Kovid Goyal
fbce5e7524
Merge branch 'patch-1' of https://github.com/zeertzjq/kitty 2022-11-24 10:16:56 +05:30
zeertzjq
daeb1b6c50
Add note about Vim's support for kitty keyboard protocol 2022-11-24 11:30:40 +08:00
Kovid Goyal
8fb2c209a9
Query for existing assets and then delete 2022-11-23 07:53:14 +05:30
Kovid Goyal
2b676b63b1
sleep defaults to one second 2022-11-22 21:56:10 +05:30
Kovid Goyal
c0d06adcb5
New sleep action
useful in combine based mappings to make kitty sleep before executing the next action
2022-11-22 21:45:19 +05:30
Kovid Goyal
51bba9110e
Bash integration: Fix clone-in-kitty not working on bash >= 5.2 if environment variable values contain newlines or other special characters
Bash >= 5.2 changed the export command to output values using $' escaping when they contain special characters.
Fixes #5629
2022-11-22 16:38:24 +05:30
Kovid Goyal
4fc91dcc03
There should be no trailing space when completing directories for a file match based on patterns 2022-11-21 11:05:36 +05:30
Kovid Goyal
3c0667afd6
add some motivation for background_tint_gaps 2022-11-21 10:19:25 +05:30
Kovid Goyal
03dc24f913
Merge branch 'background-tint-gaps' of https://github.com/page-down/kitty 2022-11-21 10:17:36 +05:30
pagedown
73b5857916
Keep two blank lines between each version in the changelog 2022-11-21 12:21:13 +08:00
pagedown
08d74a6c56
Add an option to control background image tinting for window gaps 2022-11-21 12:21:06 +08:00
Kovid Goyal
4290a8f9ba
Change the Accept header to current github api recommedation 2022-11-20 07:22:00 +05:30
Kovid Goyal
c6dd6ccc68
Apparently github's deletion api is flakey, retry 2022-11-20 07:18:38 +05:30
Kovid Goyal
fd7cc66689
Increase wait timeout before retry 2022-11-20 07:15:31 +05:30
Kovid Goyal
1c19fc77f1
... 2022-11-20 06:55:22 +05:30
Kovid Goyal
4080a09748
More upload code cleanup 2022-11-19 11:31:43 +05:30
Kovid Goyal
b91eaa3b2a
Cleanup the asset upload code 2022-11-19 11:23:31 +05:30
Kovid Goyal
bdb25831a7
Merge branch 'refactor-cursor-shape' of https://github.com/page-down/kitty 2022-11-19 11:08:17 +05:30
pagedown
a131f9a82e
Refactor: Use a consistent name for beam cursor shape 2022-11-19 10:34:50 +08:00
Kovid Goyal
ffefd0f581
Cleanup previous PR 2022-11-18 10:42:06 +05:30
Kovid Goyal
43c0e0f586
Merge branch 'unicode' of https://github.com/page-down/kitty 2022-11-18 10:40:50 +05:30
pagedown
76669ad14d
Note the Unicode version in the generated files
Files generated from the same Unicode version will be consistent
regardless of the date they were built.
2022-11-18 13:01:32 +08:00
Kovid Goyal
a9bb341e43
Add an option to control max file size for edit-in-kitty 2022-11-18 10:24:38 +05:30
Kovid Goyal
0757fcc451
Dont fail on github responses without JSON payloads 2022-11-18 10:16:29 +05:30
Kovid Goyal
dd4051bfd5
Allow getting the exe name of the active foreground process in the tab title template 2022-11-17 22:06:06 +05:30
Kovid Goyal
a6dcbe9c1d
... 2022-11-17 20:51:01 +05:30
Kovid Goyal
efaf9faa38
Implement edit-in-kitty using kitty-tool
Fixes #5546
Fixes #5630
2022-11-17 20:48:20 +05:30
Kovid Goyal
36631ddc49
... 2022-11-17 20:25:35 +05:30
Kovid Goyal
e5e8cc72c6
Make the Unicode database version used available 2022-11-17 20:11:50 +05:30
Kovid Goyal
38547c9e7a
Documentation: distinguish between examples and default values for multi-valued options 2022-11-17 17:20:40 +05:30
Kovid Goyal
e00a5ce911
Merge branch 'master' of https://github.com/ppwwyyxx/kitty 2022-11-17 17:06:56 +05:30
Kovid Goyal
0af48a4d05
Start work on implementing edit-in-kitty in kitty-tool 2022-11-17 17:05:25 +05:30
Yuxin Wu
c0d80f9a47 [docs]: don't show config codeblocks that only has a name 2022-11-17 00:05:50 -08:00
Kovid Goyal
d2dabc7d57
... 2022-11-17 11:10:17 +05:30
Kovid Goyal
81db5eb82f
Use nightly to get kitty-tool until 0.27 is released 2022-11-17 11:05:46 +05:30
Kovid Goyal
1addfea261
Avoid an extra HTTP request to set the uploaded file description
Also delete partial asset when receiving 502 errors
2022-11-17 10:44:52 +05:30
Kovid Goyal
e5be31ee14
build in non-interactive mode while publishing 2022-11-17 10:27:53 +05:30
Kovid Goyal
9cef714078
Merge branch 'pr-end-iter' of https://github.com/sergei-grechanik/kitty 2022-11-17 10:03:01 +05:30
Kovid Goyal
a5a4a1bf8f
Increase timeout in test 2022-11-17 10:02:44 +05:30
Kovid Goyal
281ad13f6b
Retry uploading file to Github 2022-11-17 08:45:26 +05:30
Kovid Goyal
5ad2ac259b
When truncating descriptions for completion truncate at word boundaries 2022-11-17 08:29:01 +05:30
Kovid Goyal
a2f022d166
Add support for the repeat escape code to TruncatetoVisualLength() 2022-11-17 08:17:11 +05:30
Sergei Grechanik
4df6c172a3 Define END_ITER to prevent brace imbalance
Otherwise some editors/plugins get confused
2022-11-16 09:54:49 -08:00
Kovid Goyal
9db1d581f7
DRYer 2022-11-16 22:37:27 +05:30
Kovid Goyal
b3bc5a5565
... 2022-11-16 22:35:59 +05:30
Kovid Goyal
fc20e8d04b
Fix spurious EOF error when select for reading from the tty fails with a temporary error 2022-11-16 22:32:35 +05:30
Kovid Goyal
86af1d5c16
Wrap EOF errors when doing terminal I/O 2022-11-16 22:23:00 +05:30
Kovid Goyal
d8574f8f85
Fix another bug in readline cursor position tracking 2022-11-16 21:28:36 +05:30
Kovid Goyal
bdd04f37d6
Better error message for kitty shell when running unknown command 2022-11-16 20:53:08 +05:30
Kovid Goyal
a4e43b3925
Use a pager for the help interactive command as well 2022-11-16 20:44:13 +05:30
Kovid Goyal
5e880b92f5
Ensure active hyperlink is cleared when truncating output for completion descriptions 2022-11-16 20:32:42 +05:30
Kovid Goyal
d4c103e53e
zsh breaks when there are escape codes in completion descriptions 2022-11-16 19:32:16 +05:30
Kovid Goyal
3e4df7d812
... 2022-11-16 19:06:22 +05:30
Kovid Goyal
3b18f90319
Merge branch 'completion' of https://github.com/page-down/kitty 2022-11-16 19:05:58 +05:30
Kovid Goyal
e31587ec1e
Ensure auto-generated entries such as --help are present for completion by calling Validate() 2022-11-16 18:05:27 +05:30
pagedown
5dc97af4d5
Add completion for kitty +list-fonts 2022-11-16 20:23:58 +08:00
Kovid Goyal
81916d0f02
Finish implementation of update-self 2022-11-16 17:44:21 +05:30
Kovid Goyal
ae93d95bbe
Get progress bar rendering working 2022-11-16 16:35:15 +05:30
Kovid Goyal
dd1fcf6855
Support the repeat prev char escape code when calculating the width of a string 2022-11-16 16:25:16 +05:30
Kovid Goyal
4b05822474
Merge branch 'ksi-completion-fish' of https://github.com/page-down/kitty 2022-11-16 14:00:28 +05:30
Kovid Goyal
337f1fad3f
fix double signatures 2022-11-16 13:45:27 +05:30
Kovid Goyal
463c9debe7
More work on update-self 2022-11-16 13:41:58 +05:30
pagedown
9225919112
Fix completion for fish 2022-11-16 16:03:07 +08:00
Kovid Goyal
e70c021371
Some basic TUI widgets ported to Go 2022-11-16 12:48:47 +05:30
Kovid Goyal
f3b3d6c0ef
Workaround for mypy bug 2022-11-15 22:47:53 +05:30
Kovid Goyal
0c0b9e6b9c
Fix deadlock in update-self 2022-11-15 22:33:23 +05:30
Kovid Goyal
d9215feda5
Allow using the cwd of the original process for launch --cwd
Fixes #5672
2022-11-15 22:18:19 +05:30
Kovid Goyal
d54fe3c16a
Start work on a command to self update kitty-tool 2022-11-15 21:29:11 +05:30
Kovid Goyal
36dd5b2d00
More minor loop API additions 2022-11-15 21:00:19 +05:30
Kovid Goyal
87108a18ef
Add a callback for wakeups 2022-11-15 18:01:21 +05:30
Kovid Goyal
234274c1df
... 2022-11-15 16:54:14 +05:30
Kovid Goyal
b42677b343
Utility function to download a URL to a file path with progress reporting 2022-11-15 16:53:43 +05:30
Kovid Goyal
c03af4d294
Build static binaries on CI 2022-11-15 15:07:33 +05:30
Kovid Goyal
8d12e60f62
Set a flag available at runtime when cross compiling kitty-tool 2022-11-15 15:04:28 +05:30
Kovid Goyal
5a71b8c209
Merge branch 'macos-custom-icon' of https://github.com/page-down/kitty 2022-11-15 13:28:03 +05:30
Kovid Goyal
16775c5539
ssh kitten: Add a kitty-tool wrapper script to auto-download and use kitty-tool
Needs testing.
2022-11-15 13:26:48 +05:30
pagedown
8b8263d0ff
macOS: Failure to set custom app icon should not prevent launch
When running `kitty/launcher/kitty` and no bundle path is provided,
the icon of `kitty/launcher/kitty.app` should be changed instead of
the `launcher` folder.
2022-11-15 15:21:40 +08:00
Kovid Goyal
9ddd7d070e
Add a note to changelog about kitty @ speed improvements 2022-11-15 12:05:59 +05:30
Kovid Goyal
780d5400cb
Use full kitty-tool exe name in github description 2022-11-15 12:01:55 +05:30
Kovid Goyal
63d7b2a80b
Shutdown macOS build VM after building 2022-11-15 11:32:34 +05:30
Kovid Goyal
1958d67847
Sign kitty-tool on macOS 2022-11-15 11:32:12 +05:30
Kovid Goyal
737919505d
Update docs to mention kitty-tool 2022-11-14 20:58:24 +05:30
Kovid Goyal
d60ecfa8a6
Install go 1.18 for codeql build 2022-11-14 20:35:41 +05:30
Kovid Goyal
e3b22a87e4
Upload static kitty-tool builds when publishing 2022-11-14 17:07:32 +05:30
Kovid Goyal
c7d47a59f1
When running kitty-tool without arguments show usage 2022-11-14 16:36:05 +05:30
Kovid Goyal
7eae176b88
Code to build static versions of kitty-tool 2022-11-14 16:27:19 +05:30
Kovid Goyal
9361c62a1c
Linux: Use a separate thread to play the beep sound
This is because on misconfigured systems canberra hangs while queueing a
sound to play. And these misconfigured systems are quite common in
Linux-land. See for example #5646

Sigh. Even playing a simple sound is failure prone on Linux.
2022-11-14 15:42:09 +05:30
Kovid Goyal
018811c96c
Remove unused code
Completion and remote control have moved into kitty-tool
2022-11-14 15:42:09 +05:30
Kovid Goyal
129646c199
Use kitty-tool for all kitty @ incovations 2022-11-14 15:42:09 +05:30
Kovid Goyal
1881f4582e
... 2022-11-14 15:42:09 +05:30
Kovid Goyal
a5d05a2954
... 2022-11-14 15:42:09 +05:30
Kovid Goyal
59b43ee844
prettify :option:--xyz> better 2022-11-14 15:42:09 +05:30
Kovid Goyal
29bde6c72c
Improve formatting of completion entries with descriptions 2022-11-14 15:42:09 +05:30
Kovid Goyal
a7ce642a00
Fix rendering in cells 2022-11-14 15:42:08 +05:30
Kovid Goyal
723a9c91b5
Get completion basically working 2022-11-14 15:42:08 +05:30
Kovid Goyal
9e2c96653f
More work on readline completion 2022-11-14 15:42:08 +05:30
Kovid Goyal
4974219e0f
Add function to shlex for completion
Also remove the google header since we have diverged from
the original a fair bit. Add a link to the original for credit.
2022-11-14 15:42:08 +05:30
Kovid Goyal
a4de4b7c6f
Report stream start position for tokens 2022-11-14 15:42:08 +05:30
Kovid Goyal
eae4899df4
Use a string builder instead of appending to a slice 2022-11-14 15:42:08 +05:30
Kovid Goyal
87b4800fdf
Get rid of comment parsing from shlex
POSIX does not define comments
2022-11-14 15:42:08 +05:30
Kovid Goyal
64156fd6e6
Have the shlex tokenizer return space tokens as well 2022-11-14 15:42:08 +05:30
Kovid Goyal
1485981b11
Have the shlex tokenizer track position in stream and return defined error types 2022-11-14 15:42:08 +05:30
Kovid Goyal
8d76cf8d32
Import the google shlex package as we need more sophisticated parsing 2022-11-14 15:42:08 +05:30
Kovid Goyal
7c23536bfe
Start work on readline completions 2022-11-14 15:42:08 +05:30
Kovid Goyal
f919efcd42
Move basic multi key shortcut handling into its own package 2022-11-14 15:42:08 +05:30
Kovid Goyal
388e47a2df
DRYer 2022-11-14 15:42:08 +05:30
Kovid Goyal
dc787a6529
Allow pretty printing members of the Action enum 2022-11-14 15:42:08 +05:30
Kovid Goyal
cfb6d93dc0
Move cursor to end of input when traversing history list 2022-11-14 15:42:08 +05:30
Kovid Goyal
1523fef000
tests for history searching 2022-11-14 15:42:08 +05:30
Kovid Goyal
31dcb13836
cursor_y should be zero when resetting 2022-11-14 15:42:07 +05:30
Kovid Goyal
0c82832356
more work on history search 2022-11-14 15:42:07 +05:30
Kovid Goyal
ffea66357a
Start work on incremental history search 2022-11-14 15:42:07 +05:30
Kovid Goyal
6b48624b81
Reset keyboard state when resetting text 2022-11-14 15:42:07 +05:30
Kovid Goyal
5a425ccaad
Implement number args for repeats 2022-11-14 15:42:07 +05:30
Kovid Goyal
2f2dbfb45f
Cleanup prompt handling 2022-11-14 15:42:07 +05:30
Kovid Goyal
13a266aa42
Map ctrl+c to abort the current line 2022-11-14 15:42:07 +05:30
Kovid Goyal
67b12159f4
make clean should also clean go caches 2022-11-14 15:42:07 +05:30
Kovid Goyal
8ad55f7562
Add some tests for history 2022-11-14 15:42:07 +05:30
Kovid Goyal
e1ab2383b3
Add basic history operations 2022-11-14 15:42:07 +05:30
Kovid Goyal
f77d07259a
Fix mutable default value in dataclass 2022-11-14 15:42:07 +05:30
Kovid Goyal
2e07f90baf
... 2022-11-14 15:42:07 +05:30
Kovid Goyal
8574e136cd
Store cwd in history 2022-11-14 15:42:07 +05:30
Kovid Goyal
c8e8cb5ad5
Add some tests for yanking 2022-11-14 15:42:07 +05:30
Kovid Goyal
f127523ae9
Get rid of the unneccessary swap on first configure
Instead use the new flag to indicate the surface should not be committed
till the next swap.
2022-11-14 15:42:07 +05:30
Kovid Goyal
22f7145e34
Add yank actions 2022-11-14 15:42:07 +05:30
Kovid Goyal
1f115870bb
Need to install x11-xcb-dev explicitly in jammy 2022-11-14 15:42:06 +05:30
Kovid Goyal
3237db00fc
Implement word killing actions 2022-11-14 15:42:06 +05:30
Kovid Goyal
ea583f60b3
Start work on kill ring 2022-11-14 15:42:06 +05:30
Kovid Goyal
b7816d26be
Implement clear screen c-l binding 2022-11-14 15:42:06 +05:30
Kovid Goyal
19bf07abd9
Use the more efficient cell iterator api for single char horizontal cursor movement as well 2022-11-14 15:42:06 +05:30
Kovid Goyal
a008c627e3
Implement bindings for moving by simple word 2022-11-14 15:42:06 +05:30
Kovid Goyal
0068ae8f66
An easy to use iterator to iterate over the cells in a string 2022-11-14 15:42:06 +05:30
Kovid Goyal
5436408463
Fix the escape code parser not preserving complete utf-8 state between calls to ParseBytes()
Also allow it to be driven byte-by-byte
2022-11-14 15:42:06 +05:30
Kovid Goyal
d260d2f480
Add some test for vertical movement 2022-11-14 15:42:06 +05:30
Kovid Goyal
00ef9c1955
Implement vertical cursor movement 2022-11-14 15:42:06 +05:30
Kovid Goyal
5509673ff3
More tests 2022-11-14 15:42:06 +05:30
Kovid Goyal
3c4a411cad
Rewrite the readline redraw code to make the screen lines explicit 2022-11-14 15:42:06 +05:30
Kovid Goyal
f945ef8ee8
handle ctrl-c better when interrupting go test 2022-11-14 15:42:06 +05:30
Kovid Goyal
260249491d
Avoid Querying screen size on every resize 2022-11-14 15:42:05 +05:30
Kovid Goyal
595a78c956
DRYer 2022-11-14 15:42:05 +05:30
Kovid Goyal
cbbf8a2d34
Port output of active window and tab ids at shell startup 2022-11-14 15:42:05 +05:30
Kovid Goyal
88567f69b2
Start work on history support for readline 2022-11-14 15:42:05 +05:30
Kovid Goyal
fe91af5e09
Go stdlib doesnt even have a way to lock files 2022-11-14 15:42:05 +05:30
Kovid Goyal
5e2255591c
Dont send invalid kitty-cmd escape code over tty 2022-11-14 15:42:05 +05:30
Kovid Goyal
01969cae1a
More useful PARSE ERROR msg for unknown @ commands 2022-11-14 15:42:05 +05:30
Kovid Goyal
b89dfc6d1d
Actually run the remote control commands from the shell 2022-11-14 15:42:05 +05:30
Kovid Goyal
59edf1d349
Code to show help 2022-11-14 15:42:05 +05:30
Kovid Goyal
9419fbc77c
Fix rendering when line wraps 2022-11-14 15:42:05 +05:30
Kovid Goyal
d27cf045e5
... 2022-11-14 15:42:05 +05:30
Kovid Goyal
f7d44330a2
remove unused code 2022-11-14 15:42:05 +05:30
Kovid Goyal
834385baff
Improve performance when pasting large amounts of text into readline by not redrawing on every char 2022-11-14 15:42:05 +05:30
Kovid Goyal
c0f17c279e
Add a generic ring buffer
Go's stdlib is very anemic
2022-11-14 15:42:05 +05:30
Kovid Goyal
7264bea8c9
Fix selector incorrectly marking fd as ready on EINTR 2022-11-14 15:42:04 +05:30
Kovid Goyal
1058c999c8
... 2022-11-14 15:42:04 +05:30
Kovid Goyal
bf7dd1c369
Fix multiline prompts 2022-11-14 15:42:04 +05:30
Kovid Goyal
936a7a5f97
Dont write escape code for zero movement 2022-11-14 15:42:04 +05:30
Kovid Goyal
350060e0f6
... 2022-11-14 15:42:04 +05:30
Kovid Goyal
430bd23870
Fix decoding of letter trailer CSI key event 2022-11-14 15:42:04 +05:30
Kovid Goyal
9f2b2eac85
More work on shell 2022-11-14 15:42:04 +05:30
Kovid Goyal
fd36435262
Add some default readline bindings 2022-11-14 15:42:04 +05:30
Kovid Goyal
27418eed88
Beep when action could not be performed 2022-11-14 15:42:04 +05:30
Kovid Goyal
48f1690913
Wire up key event handling 2022-11-14 15:42:04 +05:30
Kovid Goyal
eff239a195
Code to erase character ranges 2022-11-14 15:42:04 +05:30
Kovid Goyal
5e5cae8391
Code to move cursor right 2022-11-14 15:42:04 +05:30
Kovid Goyal
57310a772a
Code to move cursor left 2022-11-14 15:42:04 +05:30
Kovid Goyal
066465bce7
Some tests for add_text 2022-11-14 15:42:04 +05:30
Kovid Goyal
1792c2268a
Start writing tests for readline internal functions 2022-11-14 15:42:04 +05:30
Kovid Goyal
32059dba7e
More work on readline 2022-11-14 15:42:03 +05:30
Kovid Goyal
c8296a44eb
More work on readline 2022-11-14 15:42:03 +05:30
Kovid Goyal
565526624f
Start work on porting kitty shell to Go 2022-11-14 15:42:03 +05:30
Kovid Goyal
f57832f501
Fix spurious rebuilds of generated go code 2022-11-14 15:42:03 +05:30
Kovid Goyal
e536ef7844
Suggestions for sub command names as well 2022-11-14 15:42:03 +05:30
Kovid Goyal
0dab006733
Allow un-ambiguous prefixes for command names 2022-11-14 15:42:03 +05:30
Kovid Goyal
75ead358a2
Show suggestions for options based on levenshtein distance 2022-11-14 15:42:03 +05:30
Kovid Goyal
654bd23109
DRYer 2022-11-14 15:42:03 +05:30
Kovid Goyal
6b04c42730
update wcswidth go version to match unicode 15 update in master 2022-11-14 15:42:03 +05:30
Kovid Goyal
8f5302a650
Hook up kitty-tool completions with shell integration 2022-11-14 15:42:03 +05:30
Kovid Goyal
74b1cac344
Allow using unabiguous long option prefixes 2022-11-14 15:42:03 +05:30
Kovid Goyal
7d5849cc17
... 2022-11-14 15:42:03 +05:30
Kovid Goyal
d2a2af9672
Add completion for kitty-tool 2022-11-14 15:42:02 +05:30
Kovid Goyal
2633356842
No need to use a map 2022-11-14 15:42:02 +05:30
Kovid Goyal
3bd4fd999a
All completion tests pass again 2022-11-14 15:42:02 +05:30
Kovid Goyal
262e2fb7a3
Various fixes from the completion merge 2022-11-14 15:42:02 +05:30
Kovid Goyal
97716fea8b
More work on merging completions with parse tree 2022-11-14 15:42:02 +05:30
Kovid Goyal
bf74413c1f
Work on merging completion tree with parse tree 2022-11-14 15:42:02 +05:30
Kovid Goyal
79ca0408e7
split up types.go 2022-11-14 15:42:02 +05:30
Kovid Goyal
97acb60981
Move completion package into cli 2022-11-14 15:42:02 +05:30
Kovid Goyal
3662efdf80
Nicer handling of python for typecheck 2022-11-14 15:42:02 +05:30
Kovid Goyal
e608a945de
Output version information at bottom of help 2022-11-14 15:42:02 +05:30
Kovid Goyal
5771bd0c01
Make adding subcommands a bit nicer 2022-11-14 15:42:02 +05:30
Kovid Goyal
4396dede85
Get rid of the cobra dependency 2022-11-14 15:42:02 +05:30
Kovid Goyal
cbc569af64
Remove no_response from json specs 2022-11-14 15:42:02 +05:30
Kovid Goyal
90c1745976
Fix parsing of list options 2022-11-14 15:42:02 +05:30
Kovid Goyal
c4ab964d09
Tests for CLI parsing 2022-11-14 15:42:02 +05:30
Kovid Goyal
04022ed363
Various fixes to CLI parsing 2022-11-14 15:42:02 +05:30
Kovid Goyal
79cfc1e70a
Move kitty-tool __complete__ to use the new CLI framework 2022-11-14 15:42:01 +05:30
Kovid Goyal
e7c14c78d0
Work on outputting help for commands 2022-11-14 15:42:01 +05:30
Kovid Goyal
cb2389efa5
Use the standard library deque
Drops a dependency
2022-11-14 15:42:01 +05:30
Kovid Goyal
49f5f25fb9
Run tests in the writeable src dir as the generated go files are present there 2022-11-14 15:42:01 +05:30
Kovid Goyal
ff4353b209
... 2022-11-14 15:42:01 +05:30
Kovid Goyal
c07dc220a8
Fix frozen builds 2022-11-14 15:42:01 +05:30
Kovid Goyal
4316018966
... 2022-11-14 15:42:01 +05:30
Kovid Goyal
a0bf6177e2
Use a LRUCache rather than an Unbounded one 2022-11-14 15:42:01 +05:30
Kovid Goyal
3078b9074a
Also report submatch positions 2022-11-14 15:42:01 +05:30
Kovid Goyal
dffb87ced9
Make the cache re-useable 2022-11-14 15:42:01 +05:30
Kovid Goyal
4adea5b7fe
Make ReplaceAll re-useable 2022-11-14 15:42:01 +05:30
Kovid Goyal
317b108497
Allow using :role:'payload' in addition to :role:payload as the former can be used in Go `` string literals 2022-11-14 15:42:01 +05:30
Kovid Goyal
7c41737370
Couple more errors found by linting 2022-11-14 15:42:01 +05:30
Kovid Goyal
4b6bae576d
configure staticcheck 2022-11-14 15:42:01 +05:30
Kovid Goyal
8221713995
Allow defining options using a struct 2022-11-14 15:42:01 +05:30
Kovid Goyal
ef49634353
Fix some issues reported by staticcheck 2022-11-14 15:42:01 +05:30
Kovid Goyal
d6f42a11d7
Run go vet on CI 2022-11-14 15:42:00 +05:30
Kovid Goyal
800dbf1f4d
extra message when tests have failed 2022-11-14 15:42:00 +05:30
Kovid Goyal
b1e08adbce
Utility function to sort with key 2022-11-14 15:42:00 +05:30
Kovid Goyal
e7f38929d9
DRYer 2022-11-14 15:42:00 +05:30
Kovid Goyal
d0e133885c
Install Go 1.18 on CI 2022-11-14 15:42:00 +05:30
Kovid Goyal
2cacd7a64a
get rid of interface{} since we now require Go 1.18 2022-11-14 15:42:00 +05:30
Kovid Goyal
a44c89504b
More convenient interface for sorting 2022-11-14 15:42:00 +05:30
Kovid Goyal
8807f6d539
Code to get exe name for usage message 2022-11-14 15:42:00 +05:30
Kovid Goyal
2f83bbdc85
command validation 2022-11-14 15:42:00 +05:30
Kovid Goyal
41a841c83d
Validate string slice fields 2022-11-14 15:42:00 +05:30
Kovid Goyal
0cf8876f8a
Validate count struct fields 2022-11-14 15:42:00 +05:30
Kovid Goyal
a3a89b3e21
More efficient multi line scanning 2022-11-14 15:42:00 +05:30
Kovid Goyal
2ddbe2a2bc
Automatically camel-case destination 2022-11-14 15:42:00 +05:30
Kovid Goyal
707963b694
Code to conveniently read option values into a struct 2022-11-14 15:42:00 +05:30
Kovid Goyal
1811949706
Implement cloning of commands 2022-11-14 15:42:00 +05:30
Kovid Goyal
bc38bd75fd
Start work on getting rid of the cobra dependency
Command line parsing is easy and I can do it better.
2022-11-14 15:42:00 +05:30
Kovid Goyal
54ec486d3a
Now completion for hyperlinked_grep is automatic thanks to delegation
Also fix delegation for zsh when the command being completed differs
from the current command.
2022-11-14 15:42:00 +05:30
Kovid Goyal
5666b1b0fd
Implement completion for fish 2022-11-14 15:41:59 +05:30
Kovid Goyal
ef9b765f81
Dont count bash's idiotic option equals as arguments 2022-11-14 15:41:59 +05:30
Kovid Goyal
a2bb360eec
Dont output escape strings in descriptions 2022-11-14 15:41:59 +05:30
Kovid Goyal
e3b8de1ac0
Update test for new exe search 2022-11-14 15:41:59 +05:30
Kovid Goyal
4cbd2a0ee0
... 2022-11-14 15:41:59 +05:30
Kovid Goyal
7cf9b21fc0
Show local executables for kityt command completion even without ./ 2022-11-14 15:41:59 +05:30
Kovid Goyal
454c2e32e7
... 2022-11-14 15:41:59 +05:30
Kovid Goyal
53dc079c10
Use compopt to manage files and spaces 2022-11-14 15:41:59 +05:30
Kovid Goyal
08c697e99a
Get delegate based completion working for bash 2022-11-14 15:41:59 +05:30
Kovid Goyal
1dce092ac0
Add trailing spaces for bash completion 2022-11-14 15:41:59 +05:30
Kovid Goyal
24c2d27eea
handle bash splitting completion cmdline on equals 2022-11-14 15:41:59 +05:30
Kovid Goyal
b04b483b3f
Remove common prefix for bash as well 2022-11-14 15:41:59 +05:30
Kovid Goyal
a7c997c6ef
Add a debug function to print to parent kitty stdout 2022-11-14 15:41:59 +05:30
Kovid Goyal
266e51310c
Basic BASH completion 2022-11-14 15:41:59 +05:30
Kovid Goyal
928a4db817
Implement delegate based completion fof the ssh and hyperlinked_grep kittens 2022-11-14 15:41:59 +05:30
Kovid Goyal
fd631bf402
Delegate based completion for @launch args 2022-11-14 15:41:59 +05:30
Kovid Goyal
dc403156a9
Delegate based completion for kitty cmd 2022-11-14 15:41:59 +05:30
Kovid Goyal
2cc359ccc8
Get zsh completion working apart from delegation 2022-11-14 15:41:58 +05:30
Kovid Goyal
cbbda23e01
Utility code to find longest common prefix/suffix and to quote strings for various shells 2022-11-14 15:41:58 +05:30
Kovid Goyal
1ff4f2df4f
Refactor the CLI markup code to make it re-useable 2022-11-14 15:41:58 +05:30
Kovid Goyal
8796168469
Port code to truncate strings to visual width to Go 2022-11-14 15:41:58 +05:30
Kovid Goyal
d16ad40bbf
avoid extra string copy in Stringwidth 2022-11-14 15:41:58 +05:30
Kovid Goyal
5c0858d6b7
Start work on zsh completion serialization 2022-11-14 15:41:58 +05:30
Kovid Goyal
a32a8d096d
Allow commands to customize argument parsing 2022-11-14 15:41:58 +05:30
Kovid Goyal
67f556bd7c
Add completion for the launch wrappers 2022-11-14 15:41:58 +05:30
Kovid Goyal
7737369fc9
Add completion for the kittens 2022-11-14 15:41:58 +05:30
Kovid Goyal
25a7ec9a07
Extra completion for some kitty options 2022-11-14 15:41:58 +05:30
Kovid Goyal
c2a2b4c087
Add various special purpose entry points 2022-11-14 15:41:58 +05:30
Kovid Goyal
3bf20594b7
Wire up completion for rc command options 2022-11-14 15:41:58 +05:30
Kovid Goyal
3a8bab90dc
Get rid of WordPrefix 2022-11-14 15:41:58 +05:30
Kovid Goyal
0ff2446a1a
More completion work 2022-11-14 15:41:58 +05:30
Kovid Goyal
946d44c43f
Implement completespec in go 2022-11-14 15:41:58 +05:30
Kovid Goyal
26d4f5bcc9
Use the new completionspec for rc cmds 2022-11-14 15:41:58 +05:30
Kovid Goyal
d84efe105c
... 2022-11-14 15:41:58 +05:30
Kovid Goyal
f657e6e916
Allow using a base directory other than the cwd when completing files 2022-11-14 15:41:57 +05:30
Kovid Goyal
c5afceb4cb
Basic completion for options 2022-11-14 15:41:57 +05:30
Kovid Goyal
18c3e46ac6
When completing on patterns exclude directories that only contain files that dont match 2022-11-14 15:41:57 +05:30
Kovid Goyal
3c29ce936b
Dont recurse for file completion
We could potentially end up recursing over the entire file system. And
for completion we only present the candidates in the immediate directory
anyway.
2022-11-14 15:41:57 +05:30
Kovid Goyal
c9d986f9a8
args completion for rc commands 2022-11-14 15:41:57 +05:30
Kovid Goyal
d4b67f3b6a
... 2022-11-14 15:41:57 +05:30
Kovid Goyal
6faa908733
And more corner cases 2022-11-14 15:41:57 +05:30
Kovid Goyal
ced741b247
More corner cases 2022-11-14 15:41:57 +05:30
Kovid Goyal
c47ccc8a59
... 2022-11-14 15:41:57 +05:30
Kovid Goyal
3326e9ef49
Move code to walk with symlinks to the utils module 2022-11-14 15:41:57 +05:30
Kovid Goyal
134fce8507
Allow completing paths with ~ prefix 2022-11-14 15:41:57 +05:30
Kovid Goyal
5d89a6c3c4
Work on completion of file args 2022-11-14 15:41:57 +05:30
Kovid Goyal
833e9625f9
Add a generated comment in *_generated.go in the style used by go generate 2022-11-14 15:41:57 +05:30
Kovid Goyal
21b572d69a
Allow building kitty-tool as a static binary 2022-11-14 15:41:57 +05:30
Kovid Goyal
12d9787d0e
update go deps 2022-11-14 15:41:57 +05:30
Kovid Goyal
8c6b391eda
... 2022-11-14 15:41:57 +05:30
Kovid Goyal
8c2e435793
Code to complete executables in PATH 2022-11-14 15:41:57 +05:30
Kovid Goyal
10cf7f06c6
Code to get file/dir completion candidates for a prefix 2022-11-14 15:41:56 +05:30
Kovid Goyal
4575a14873
work on framework for testing completion 2022-11-14 15:41:56 +05:30
Kovid Goyal
d679ea2cdf
Allow generating completions for multiple command lines for more efficient testing 2022-11-14 15:41:56 +05:30
Kovid Goyal
54378de52b
More work on command completion 2022-11-14 15:41:56 +05:30
Kovid Goyal
63287e4115
More work on completions 2022-11-14 15:41:56 +05:30
Kovid Goyal
d0efe00449
Use replace_if_needed() for at commands 2022-11-14 15:41:56 +05:30
Kovid Goyal
d703cb51cd
... 2022-11-14 15:41:56 +05:30
Kovid Goyal
005a9c7090
Add an entry point for the completion tool 2022-11-14 15:41:56 +05:30
Kovid Goyal
f4de6d2a10
More work on completions 2022-11-14 15:41:56 +05:30
Kovid Goyal
e60b331152
start work on porting completion to Go 2022-11-14 15:41:56 +05:30
Kovid Goyal
3d79eb5730
more tests for indent and wrap 2022-11-14 15:41:56 +05:30
Kovid Goyal
af7f4e97cf
More work on the new formatter 2022-11-14 15:41:56 +05:30
Kovid Goyal
aad8cb3d1e
Use the new formatter for CLI help output 2022-11-14 15:41:56 +05:30
Kovid Goyal
40a9ab8929
Allow ignoring lines containing a sentinel 2022-11-14 15:41:56 +05:30
Kovid Goyal
e433b90297
Dont drop trailing escape codes when stripping trailing whitespace 2022-11-14 15:41:56 +05:30
Kovid Goyal
1ac7d9c10d
Basic wrap is working 2022-11-14 15:41:56 +05:30
Kovid Goyal
ef5f0025e1
Start work on more sophisticated indent+wrap implementation 2022-11-14 15:41:56 +05:30
Kovid Goyal
32804f01b2
Allow parsing strings with escape code parser 2022-11-14 15:41:55 +05:30
Kovid Goyal
7ecc1b7950
Remove markup from ref_hyperlink text 2022-11-14 15:41:55 +05:30
Kovid Goyal
a7f6105393
Use Unsafe rather than Dangerous to be consistent 2022-11-14 15:41:55 +05:30
Kovid Goyal
081390b5a2
Utility functions to allow using string/[]byte interchangeably without copies 2022-11-14 15:41:55 +05:30
Kovid Goyal
61094c6bfb
Add strikethrough formatting 2022-11-14 15:41:55 +05:30
Kovid Goyal
6672904e64
Fix spurious error message when setting image to none 2022-11-14 15:41:55 +05:30
Kovid Goyal
905c4d641c
Allow using many image formats in RC commands 2022-11-14 15:41:55 +05:30
Kovid Goyal
fa7a6dfd4a
Implement stdin echo loop for socket i/o as well 2022-11-14 15:41:55 +05:30
Kovid Goyal
cb452ba9fc
Implement sen text from stdin for the tty backend 2022-11-14 15:41:55 +05:30
Kovid Goyal
85169c989f
... 2022-11-14 15:41:55 +05:30
Kovid Goyal
e8a321d097
Port code to serialize key events as CSI to Go 2022-11-14 15:41:55 +05:30
Kovid Goyal
3a198833da
Simplify escape code wrapping 2022-11-14 15:41:55 +05:30
Kovid Goyal
ea8fb10c05
Password input: Handle SIGTSTP 2022-11-14 15:41:55 +05:30
Kovid Goyal
67115530b4
Make the loop API a thin wrapper around internal methods 2022-11-14 15:41:55 +05:30
Kovid Goyal
7325921070
Allow cancel async commands without auth 2022-11-14 15:41:55 +05:30
Kovid Goyal
f86ce03d3b
Fix set-colors 2022-11-14 15:41:55 +05:30
Kovid Goyal
5cf10023c9
Nicer API for setting loop options 2022-11-14 15:41:55 +05:30
Kovid Goyal
93d08011f1
... 2022-11-14 15:41:54 +05:30
Kovid Goyal
7f77f7e408
Only send cancel async if there is an async id 2022-11-14 15:41:54 +05:30
Kovid Goyal
65c3630099
send_text other than from stdin works 2022-11-14 15:41:54 +05:30
Kovid Goyal
457aab7c41
Simplify timer removal 2022-11-14 15:41:54 +05:30
Kovid Goyal
dcec926590
Do not allow adding timers before loop is run 2022-11-14 15:41:54 +05:30
Kovid Goyal
0a2455c8be
Get scroll_window working 2022-11-14 15:41:54 +05:30
Kovid Goyal
bacca88213
Get set_font_size working 2022-11-14 15:41:54 +05:30
Kovid Goyal
bd1b3d9f6e
Implement streaming mode for socket IO 2022-11-14 15:41:54 +05:30
Kovid Goyal
364533b1ed
Work on supporting streaming remote commands with passwords 2022-11-14 15:41:54 +05:30
Kovid Goyal
d7985689c9
Allow debugprintln to controlling tty easily 2022-11-14 15:41:54 +05:30
Kovid Goyal
6d6bba4a4c
debugprintln should be in-band for the loop 2022-11-14 15:41:54 +05:30
Kovid Goyal
5cc5759f3e
flush_pending_writes must be non-blocking 2022-11-14 15:41:54 +05:30
Kovid Goyal
a388a658ce
Fix payload update code in multi send commands 2022-11-14 15:41:54 +05:30
Kovid Goyal
b5e2871aa0
Remove not needed chunking code 2022-11-14 15:41:54 +05:30
Kovid Goyal
192eccc6cc
More work on porting rc commands 2022-11-14 15:41:54 +05:30
Kovid Goyal
a4b2e2a196
more work on porting command parsing to Go 2022-11-14 15:41:54 +05:30
Kovid Goyal
6f4968305a
more work on porting rc command parsing to Go 2022-11-14 15:41:54 +05:30
Kovid Goyal
79c8862d4c
Work on conversion of args parsing to go code 2022-11-14 15:41:53 +05:30
Kovid Goyal
441e4edfb2
Also ensure kitty-tool bootstrap is executable 2022-11-14 15:41:53 +05:30
Kovid Goyal
ef71b071db
Automap a bunch of json fields from identically named options 2022-11-14 15:41:53 +05:30
Kovid Goyal
b33a684357
... 2022-11-14 15:41:53 +05:30
Kovid Goyal
43b35f6f4e
Move GoOption migration code to cli.py for re-use 2022-11-14 15:41:53 +05:30
Kovid Goyal
3b2c4561c2
Dont change the env for go tests
This prevents got test caching from working greatly increasing the time
for running a test
2022-11-14 15:41:53 +05:30
Kovid Goyal
e69b02ad46
... 2022-11-14 15:41:53 +05:30
Kovid Goyal
85b6053380
Run go tests in parallel 2022-11-14 15:41:53 +05:30
Kovid Goyal
249df69ac9
Use the new styling API for CLI infra 2022-11-14 15:41:53 +05:30
Kovid Goyal
4a4500d56b
Dont make urls part of styling, instead have a dedicated UrlFunc API
Since urls can potentially change a lot, caching them makes no sense
2022-11-14 15:41:53 +05:30
Kovid Goyal
be22f49012
Fix usage of numbered colors for underlines 2022-11-14 15:41:53 +05:30
Kovid Goyal
f9695a7947
Add url support to styling 2022-11-14 15:41:53 +05:30
Kovid Goyal
29d9b70f0c
More ansi styling tests 2022-11-14 15:41:53 +05:30
Kovid Goyal
42a8ca0842
Write some tests for the style wrapper 2022-11-14 15:41:53 +05:30
Kovid Goyal
91c61478dd
Start work on easily generating ANSI formatted strings 2022-11-14 15:41:53 +05:30
Kovid Goyal
fb482e28f6
... 2022-11-14 15:41:53 +05:30
Kovid Goyal
387333492b
Generate color names and table for Go
Also exclude generated files from gofmt checking
2022-11-14 15:41:53 +05:30
Kovid Goyal
9c58cb3f41
... 2022-11-14 15:41:52 +05:30
Kovid Goyal
b2e610f9b1
Implement socket I/O 2022-11-14 15:41:52 +05:30
Kovid Goyal
a960937095
Simplify serialization code and avoid extra copy 2022-11-14 15:41:52 +05:30
Kovid Goyal
0cda5d43a6
Fix final write detection 2022-11-14 15:41:52 +05:30
Kovid Goyal
a75d59643c
Use one less channel 2022-11-14 15:41:52 +05:30
Kovid Goyal
bf35817d73
No need to store most channels on self 2022-11-14 15:41:52 +05:30
Kovid Goyal
f103f8d5db
Create a in src symlink for kitty-tool as well 2022-11-14 15:41:52 +05:30
Kovid Goyal
b382587776
another attempt 2022-11-14 15:41:52 +05:30
Kovid Goyal
6fe0c8ba2f
dump tree 2022-11-14 15:41:52 +05:30
Kovid Goyal
7b2991de02
... 2022-11-14 15:41:52 +05:30
Kovid Goyal
1b90c03304
Refactor loop code into its own package 2022-11-14 15:41:52 +05:30
Kovid Goyal
0aa05b02e8
Cleanup 2022-11-14 15:41:52 +05:30
Kovid Goyal
5412a0126c
we generate more than just rc commands 2022-11-14 15:41:52 +05:30
Kovid Goyal
841b368021
DRYer 2022-11-14 15:41:52 +05:30
Kovid Goyal
b1f9139ca5
Use a fully random async_id rather than a uuid 2022-11-14 15:41:52 +05:30
Kovid Goyal
4a49c3940a
Switch to using goroutines rather than a select()
More complex code since now we have to synchronize between threads,
but a good way to teach myself more about goroutines.
2022-11-14 15:41:52 +05:30
Kovid Goyal
ee12349a50
Use Go's os.File this allows us to implement WriteString without using unsafe 2022-11-14 15:41:52 +05:30
Kovid Goyal
69c847a48f
Fix failing test 2022-11-14 15:41:51 +05:30
Kovid Goyal
03705cbec0
Fix transmission of async rc commands 2022-11-14 15:41:51 +05:30
Kovid Goyal
ff2ff9c04f
Port short uuid code to Go 2022-11-14 15:41:51 +05:30
Kovid Goyal
a22ba9f739
Fix failing test 2022-11-14 15:41:51 +05:30
Kovid Goyal
c86f8a698c
@ ls works phew 2022-11-14 15:41:51 +05:30
Kovid Goyal
fa4711bd04
Give the kill signal time to be delivered 2022-11-14 15:41:51 +05:30
Kovid Goyal
a939bbb3ec
... 2022-11-14 15:41:51 +05:30
Kovid Goyal
174bc25afb
Make timeout checking more efficient 2022-11-14 15:41:51 +05:30
Kovid Goyal
2ffba1c422
Work on implementing ttyio via TUI 2022-11-14 15:41:51 +05:30
Kovid Goyal
0913b64c6b
Dont vendor base85 2022-11-14 15:41:51 +05:30
Kovid Goyal
32e59257d2
Refactor io in preparation for using tui 2022-11-14 15:41:51 +05:30
Kovid Goyal
6f8c884bb5
Also handle SIGPIPE as the Go runtime does funky things with this signal 2022-11-14 15:41:51 +05:30
Kovid Goyal
80c5ac891d
Add license info to Go files 2022-11-14 15:41:51 +05:30
Kovid Goyal
ccb60687b6
Prefix names of cmd files 2022-11-14 15:41:51 +05:30
Kovid Goyal
6a2393299b
Add a write completed callback 2022-11-14 15:41:51 +05:30
Kovid Goyal
ab66b3f4c0
Add timer infra to the loop 2022-11-14 15:41:51 +05:30
Kovid Goyal
c8292d77f1
Re-use the escape code parser for wcswidth calculation 2022-11-14 15:41:51 +05:30
Kovid Goyal
7280c712d6
Move escape code parser into wcswidth package 2022-11-14 15:41:50 +05:30
Kovid Goyal
9be2247081
Dont use the syscall package 2022-11-14 15:41:50 +05:30
Kovid Goyal
e68b5fa504
Add callback for screen resize handling 2022-11-14 15:41:50 +05:30
Kovid Goyal
c2ef6c986b
Password input now works 2022-11-14 15:41:50 +05:30
Kovid Goyal
619fcb0681
Allow debug printing 2022-11-14 15:41:50 +05:30
Kovid Goyal
10a39d3757
Fix reset mode incorrectly setting mode instead 2022-11-14 15:41:50 +05:30
Kovid Goyal
d2a15a2009
Make using alternate screen the default 2022-11-14 15:41:50 +05:30
Kovid Goyal
235eb868b2
More misc fixes for TUI 2022-11-14 15:41:50 +05:30
Kovid Goyal
5703a3370e
Move wcswidth into its own package as it is very slow to build 2022-11-14 15:41:50 +05:30
Kovid Goyal
5dca2a1a25
Fix stringifying mods 2022-11-14 15:41:50 +05:30
Kovid Goyal
4b18b575cd
Misc fixes for TUI 2022-11-14 15:41:50 +05:30
Kovid Goyal
818f68ec53
Initialize various maps 2022-11-14 15:41:50 +05:30
Kovid Goyal
cd54fefa99
Ignore more types of temporary errors 2022-11-14 15:41:50 +05:30
Kovid Goyal
4ab5456ead
Less layering 2022-11-14 15:41:49 +05:30
Kovid Goyal
10d11bc749
Drop another dependency 2022-11-14 15:41:49 +05:30
Kovid Goyal
19ffbc6f3d
Implement wcswidth() for Go 2022-11-14 15:41:49 +05:30
Kovid Goyal
79b1af28b4
Fix errors reported by compiler 2022-11-14 15:41:49 +05:30
Kovid Goyal
05d768d8df
Generate a wcwidth for Go as well 2022-11-14 15:41:49 +05:30
Kovid Goyal
7bb310d3af
Port recent changes from cli.py to Go 2022-11-14 15:41:49 +05:30
Kovid Goyal
9d56f8eed2
Use TUI to build a nice password read control 2022-11-14 15:41:49 +05:30
Kovid Goyal
42a5129553
Wire up key handling 2022-11-14 15:41:49 +05:30
Kovid Goyal
d6ed20323b
Implement key event parsing and matching 2022-11-14 15:41:49 +05:30
Kovid Goyal
63fdbd3fa0
Start work on decoding key events in Go 2022-11-14 15:41:49 +05:30
Kovid Goyal
99fde8723a
Wire up the signal handlers 2022-11-14 15:41:49 +05:30
Kovid Goyal
526a331f47
Wire up a bunch of callbacks 2022-11-14 15:41:49 +05:30
Kovid Goyal
e18b6638bb
Allow propagating errors from the escape code handlers 2022-11-14 15:41:49 +05:30
Kovid Goyal
3c3e7b7f70
Start work on proper TUI support 2022-11-14 15:41:49 +05:30
Kovid Goyal
67f03621ae
Handle EINTR in IsTerminal 2022-11-14 15:41:49 +05:30
Kovid Goyal
10cef16210
DRYer 2022-11-14 15:41:49 +05:30
Kovid Goyal
6a79b450f7
Drop another dependency and get a better read password function 2022-11-14 15:41:48 +05:30
Kovid Goyal
eb4ee13f73
Drop another dependency 2022-11-14 15:41:48 +05:30
Kovid Goyal
cf287015de
... 2022-11-14 15:41:48 +05:30
Kovid Goyal
246277e7af
Refactor tty code into its own package 2022-11-14 15:41:48 +05:30
Kovid Goyal
13758e9600
Drop one dependency 2022-11-14 15:41:48 +05:30
Kovid Goyal
73e4deb1c2
Show suggestions based on levenshtein distance 2022-11-14 15:41:48 +05:30
Kovid Goyal
68d589826a
... 2022-11-14 15:41:48 +05:30
Kovid Goyal
7457746d65
Fix @command form not supporting global options 2022-11-14 15:41:48 +05:30
Kovid Goyal
eec8f04e93
fix reading from tty 2022-11-14 15:41:48 +05:30
Kovid Goyal
3a7d26a3ef
Work on reading command responses 2022-11-14 15:41:48 +05:30
Kovid Goyal
91b15d1a90
Fix incorrect err handling 2022-11-14 15:41:48 +05:30
Kovid Goyal
12b0f632bd
Allow OSC to be terminated by BEL
Also prevent changing streaming state unless in reset state
2022-11-14 15:41:48 +05:30
Kovid Goyal
84cb2638d6
Work on an escape code parser 2022-11-14 15:41:48 +05:30
Kovid Goyal
7eb6cb2407
Update script that counts lines of code 2022-11-14 15:41:48 +05:30
Kovid Goyal
ce3062cbde
UTF-8 decode/encode for Go
The builtin utf-8 package has semantics not suitable for us
2022-11-14 15:41:48 +05:30
Kovid Goyal
e599a2c87f
The stupid term package is not EINTR safe 2022-11-14 15:41:48 +05:30
Kovid Goyal
15e1f376a4
EINTR safe function to get tty size 2022-11-14 15:41:48 +05:30
Kovid Goyal
82d0bd9364
Use the term package to get tty size since it has a function for it 2022-11-14 15:41:47 +05:30
Kovid Goyal
6a9f3feba2
... 2022-11-14 15:41:47 +05:30
Kovid Goyal
2e31178980
Workaround for go unix package not wrapping pselect() on darwin 2022-11-14 15:41:47 +05:30
Kovid Goyal
141b9c8f08
Adjust select() timeout on EINTR 2022-11-14 15:41:47 +05:30
Kovid Goyal
17629add66
Handle EINTR 2022-11-14 15:41:47 +05:30
Kovid Goyal
352a78f056
Add a debug print method to tty and use pselect rather than select for greater timeout precision 2022-11-14 15:41:47 +05:30
Kovid Goyal
2ef5d0a140
... 2022-11-14 15:41:47 +05:30
Kovid Goyal
08b4741024
Get rid of a couple of unneeded dependencies 2022-11-14 15:41:47 +05:30
Kovid Goyal
11ffa961bc
Use local hyperlinks for :doc: 2022-11-14 15:41:47 +05:30
Kovid Goyal
ad6d928c12
Port various recent changes to CLI help output 2022-11-14 15:41:47 +05:30
Kovid Goyal
74b768bfc2
... 2022-11-14 15:41:47 +05:30
Kovid Goyal
9b703078dd
See if at least the field names are the same 2022-11-14 15:41:47 +05:30
Kovid Goyal
43e93414ea
Some work on implementing TTYIO 2022-11-14 15:41:47 +05:30
Kovid Goyal
6c3a439455
Use the io.Reader interface 2022-11-14 15:41:47 +05:30
Kovid Goyal
a7bc2fcba8
Code to parse socket addresses 2022-11-14 15:41:47 +05:30
Kovid Goyal
417c8887b9
Start on testing infra for command to JSON serialization 2022-11-14 15:41:47 +05:30
Kovid Goyal
47feb73cdf
Code to generate structs for JSON marshalling 2022-11-14 15:41:47 +05:30
Kovid Goyal
0aa1bacbe7
... 2022-11-14 15:41:47 +05:30
Kovid Goyal
63512f0512
Implement setting of option values into a struct 2022-11-14 15:41:46 +05:30
Kovid Goyal
a32251cab4
Handle aliased flags 2022-11-14 15:41:46 +05:30
Kovid Goyal
2ca8ae8e5f
normalize flag names so that underscores are interchangeable with hyphens 2022-11-14 15:41:46 +05:30
Kovid Goyal
2d466f343d
Finish mapping of python cli opt to go cli opt 2022-11-14 15:41:46 +05:30
Kovid Goyal
4596dc39ce
Fix formatting of lines with only spaces 2022-11-14 15:41:46 +05:30
Kovid Goyal
605882582e
Transfer response_timeout 2022-11-14 15:41:46 +05:30
Kovid Goyal
a5876e5231
Refactor conversion of py opt to go opt 2022-11-14 15:41:46 +05:30
Kovid Goyal
e127579ae6
DRYer 2022-11-14 15:41:46 +05:30
Kovid Goyal
b3be6792fd
General cleanup 2022-11-14 15:41:46 +05:30
Kovid Goyal
6c25f0cf4b
Use cobra's builtin machinery for creating new types 2022-11-14 15:41:46 +05:30
Kovid Goyal
a0bff4abab
Let kitty-tool know if it was built for a frozen kitty 2022-11-14 15:41:46 +05:30
Kovid Goyal
82410c58ed
Hide the default completion command 2022-11-14 15:41:46 +05:30
Kovid Goyal
3a87cfce3e
Get bool set flags ported 2022-11-14 15:41:46 +05:30
Kovid Goyal
15ffd8e6d8
Support older Go 2022-11-14 15:41:46 +05:30
Kovid Goyal
33e16df586
Add some basic RC serialization tests 2022-11-14 15:41:46 +05:30
Kovid Goyal
4432c1a2ea
Move the command types into a separate package 2022-11-14 15:41:46 +05:30
Kovid Goyal
45540561cc
More debug info about PATH in CI 2022-11-14 15:41:46 +05:30
Kovid Goyal
f90753c69b
Use whatever version of go is available on CI 2022-11-14 15:41:46 +05:30
Kovid Goyal
bab914c497
Create hidden alias commands so kitty-tool @ls also works 2022-11-14 15:41:45 +05:30
Kovid Goyal
d3bb69a0ac
strip whitespace from long descriptions just to be safe 2022-11-14 15:41:45 +05:30
Kovid Goyal
e356af2dc4
Build kitty-tool as a universal binary for freeze builds on macOS 2022-11-14 15:41:45 +05:30
Kovid Goyal
e9e7b97c48
And we have frozen builds working with kitty-tool 2022-11-14 15:41:45 +05:30
Kovid Goyal
1c7d6f8bc6
Dont sync kitty-tool to build vms 2022-11-14 15:41:45 +05:30
Kovid Goyal
82a0e56eb2
Fix go tests not being excluded correctly 2022-11-14 15:41:45 +05:30
Kovid Goyal
54fd2c6773
Get linux freeze working 2022-11-14 15:41:45 +05:30
Kovid Goyal
fb4c7db25e
Add a test for existence of kitty-tool 2022-11-14 15:41:45 +05:30
Kovid Goyal
c85af36116
Simplify cleanup and ignoring of generated go files 2022-11-14 15:41:45 +05:30
Kovid Goyal
780b5ca8bd
misc fixes 2022-11-14 15:41:45 +05:30
Kovid Goyal
20ad7ca437
Output VCSRevision with --version 2022-11-14 15:41:45 +05:30
Kovid Goyal
d39036de2a
Add vcs revision to version string 2022-11-14 15:41:45 +05:30
Kovid Goyal
4ac4ee643e
Have the rc command wrapper sauto-generated on build 2022-11-14 15:41:45 +05:30
Kovid Goyal
47f35a06e6
Start work on generating rc cmd wrappers 2022-11-14 15:41:45 +05:30
Kovid Goyal
77f7ce82c0
Parse global options 2022-11-14 15:41:45 +05:30
Kovid Goyal
10b74d0703
Update documentation of --to 2022-11-14 15:41:45 +05:30
Kovid Goyal
393820e77a
Dont sort flags by default 2022-11-14 15:41:45 +05:30
Kovid Goyal
1b8805bc6f
document we need go >= 1.19 2022-11-14 15:41:44 +05:30
Kovid Goyal
07dc83670b
Fix go in home dir getting removed from PATH on CI 2022-11-14 15:41:44 +05:30
Kovid Goyal
1429be3a19
Run gofmt via python, easier to debug 2022-11-14 15:41:44 +05:30
Kovid Goyal
4b69a600e5
Nicer error when go is not found during build 2022-11-14 15:41:44 +05:30
Kovid Goyal
ce9a5528bc
Pass verbose to go build 2022-11-14 15:41:44 +05:30
Kovid Goyal
2ea3fa36d2
... 2022-11-14 15:41:44 +05:30
Kovid Goyal
14262b158d
Log which go exe is being used to run the tests 2022-11-14 15:41:44 +05:30
Kovid Goyal
2fd013b593
Add source code linting for go to CI 2022-11-14 15:41:44 +05:30
Kovid Goyal
1325844539
Add some go testing infrastructure 2022-11-14 15:41:44 +05:30
Kovid Goyal
3a21605b05
... 2022-11-14 15:41:44 +05:30
Kovid Goyal
cea9ff30dc
Add the go dependency to CI and Brewfile 2022-11-14 15:41:44 +05:30
Kovid Goyal
63da2e1ec6
gofmt 2022-11-14 15:41:44 +05:30
Kovid Goyal
083deec663
Build kitty-tool via the build system 2022-11-14 15:41:44 +05:30
Kovid Goyal
8b91c227f6
... 2022-11-14 15:41:44 +05:30
Kovid Goyal
06bd1f5d48
DRYer 2022-11-14 15:41:44 +05:30
Kovid Goyal
a7f0a471ed
Dont fail to output usage when less is not present 2022-11-14 15:41:44 +05:30
Kovid Goyal
2a7aa46b77
Use pager even for usage + error 2022-11-14 15:41:44 +05:30
Kovid Goyal
c04b002d4e
Use a pager for displaying usage, matches kitty behavior
Also dont tell less to squeeze lines
2022-11-14 15:41:44 +05:30
Kovid Goyal
46840df1ad
CLI help output make kitty.conf a clickable URL 2022-11-14 15:41:43 +05:30
Kovid Goyal
aaf0dea8dc
Use a single wrapper binary for all command line tools
This is because Go has a multi megabyte overhead for its binaries
2022-11-14 15:41:43 +05:30
Kovid Goyal
abaafc2d68
Parse roles in the help strings 2022-11-14 15:41:43 +05:30
Kovid Goyal
c97556de65
Show help when command is specified 2022-11-14 15:41:43 +05:30
Kovid Goyal
bbf7504303
Start work on implementing kitty @ as a static binary using Go 2022-11-14 15:41:43 +05:30
Kovid Goyal
126468a5dd
Fix #5668 2022-11-14 15:40:24 +05:30
Kovid Goyal
8280899ce1
IBUS: When creating the connection mark as focused if any top level window has focus. Fixes #5655 2022-11-10 07:21:34 +05:30
Kovid Goyal
b15c9f7419
Function should be static 2022-11-10 07:18:17 +05:30
Kovid Goyal
2e8ef66496
Another mypy update another round of spurious errors 2022-11-08 17:17:40 +05:30
Kovid Goyal
72f92b395f
version 0.26.5 2022-11-07 15:36:42 +05:30
Kovid Goyal
c9c8eb6e94
... 2022-11-05 11:37:07 +05:30
Kovid Goyal
59ded41f7a
When no OS Window is focused the active_* should return those belonging to the last focused OS Window 2022-11-05 11:34:10 +05:30
Kovid Goyal
10ad56885e
Properly specify semantics of active and focused
active means active in parent. focused means actually has keyboard
focus.
2022-11-04 10:38:18 +05:30
Kovid Goyal
d1eb9340ac
Output the actual tab id in its repr 2022-11-04 09:29:33 +05:30
Kovid Goyal
a856c64104
Have the semantics of is_focused match that of state:focused otherwise things are liable to get confusing
The previous value is now available as is_active_window
2022-11-03 22:32:07 +05:30
Kovid Goyal
c0b11c5656
Also change the behavior of state:focused matching for tabs 2022-11-03 21:56:23 +05:30
Kovid Goyal
935c4ded6b
Remote control: When matching window by state:focused match the window belonging to the OS window that was last focused
Fixes #5602
2022-11-03 21:52:20 +05:30
Kovid Goyal
f5de08d5fa
Splits layout: Add a new mappable action to move the active window to the screen edge
Fixes #5643
2022-11-03 17:40:04 +05:30
Kovid Goyal
9d471782dd
Increase some more timeouts 2022-11-03 13:13:14 +05:30
Kovid Goyal
dea3df66f8
system python appears broken on macos-latest image
The pip scripts install directory is not on PATH
2022-11-03 13:05:03 +05:30
Kovid Goyal
ec80a1532c
Try to make mypy happy with the contortions needed for importlib.resources 2022-11-03 12:41:13 +05:30
Kovid Goyal
93563f1280
More pointless code churn thanks to importlib.resources
They've deprecated a bunch of API but the suggested replacement is
either not present in versions of python that are not EOLed or doesn't
actually work.
2022-11-03 12:13:47 +05:30
Kovid Goyal
e309e54002
Allow using the re module in tab title templates
Fix #5639
2022-11-01 22:25:58 +05:30
Kovid Goyal
0b3228ab16
... 2022-11-01 12:51:36 +05:30
Kovid Goyal
3f28cf45d4
Dont use the deprecated importlib.resources API 2022-11-01 12:38:24 +05:30
Kovid Goyal
88b829fc9b
cleanup comment 2022-11-01 12:22:05 +05:30
Kovid Goyal
458ac6953f
Update changelog for last PR 2022-11-01 12:21:09 +05:30
Kovid Goyal
a6855bde3c
Merge branch 'no_cursor_update_if_not_changed' of https://github.com/wengxt/kitty 2022-11-01 12:20:18 +05:30
Kovid Goyal
f6f2f00c53
Add a note about wayland semantics 2022-11-01 12:13:23 +05:30
Kovid Goyal
00324c96fc
... 2022-10-31 22:09:01 +05:30
Kovid Goyal
2435a8ccfd
Wayland GNOME: Fix incorrect window size when in some circumstances when switching between windows with window decorations disabled
Only call wl_surface_commit() after a resize when the correct size buffer is
attached to the surface. This is ensured by setting a flag on the window that prevents
all surface commits till it is cleared. The flag is cleared at next
eglSwapBuffers().

I dont actually understand if this guarantees that the
buffer size is always correct. For example, if the back buffer is
latched when wl_egl_resize_window() is called, the backbuffer will be
correct only after two swaps (I think). Or maybe the old back buffer is
discarded, I cant find any documentation about it.

All I can say is that doing it this way seems to fix the issue.

Thanks to @jadahl for his help with tracking down the root cause.

Fixes #4802
2022-10-31 21:59:01 +05:30
Kovid Goyal
de122ed727
Bind eglQuerySurface 2022-10-31 21:03:39 +05:30
Kovid Goyal
c2ead407ae
... 2022-10-31 18:14:38 +05:30
Kovid Goyal
16b322616a
Fix cursor position at x=0 changing to x=1 on resize
Fixes #5635
2022-10-31 08:03:42 +05:30
Kovid Goyal
e0b4c7edc5
Increase the timeout for shell integration tests
Needed for ARM running non-natively
2022-10-30 11:09:36 +05:30
Kovid Goyal
a8ab4eaf23
Use a larger timeout when running prewarm test 2022-10-30 10:36:10 +05:30
Kovid Goyal
3847837bd0
Forgot to run gen-config.py 2022-10-19 20:50:53 +05:30
Kovid Goyal
1747bbbbcb
ssh kitten: Allow using absolute paths for the location of transferred data
Fixes #5607
2022-10-19 20:43:53 +05:30
Kovid Goyal
90e80477e9
Fix background_tint with background_opacity < 1 causing colors in cell area and padding to not match 2022-10-19 19:24:37 +05:30
Kovid Goyal
4f90110a7c
Fix ghosting when using background_tint under GNOME+Wayland
The problem was that on Wayland if the buffer contains pixels with alpha
< 1 they are blended with something, even if the window is opaque. Under
mutter that something was the previous frame, under sway it was the
background/whatever is under the window.

So when blending the tint color, use a blend mode that results in opaque
pixels.

Fixes #5605
2022-10-19 19:02:05 +05:30
Kovid Goyal
28c616d3ff
Move blend mode selection into draw_tint 2022-10-19 17:13:46 +05:30
Kovid Goyal
f5126c664c
Wayland KDE: Fix abort when pasting into Firefox
Dunno why kwin uses drag and drop callbacks when pasting into Firefox on
Wayland, but then this is Wayland, so every stupid thing imaginable will
be done at least once.

Fixes #5603
2022-10-19 11:28:33 +05:30
Kovid Goyal
0f340086c0
Fix resize_draw_strategy=static
The text is now static again but the background image is still scaled, cant be
bothered about that. Fixes #5601
2022-10-19 08:26:31 +05:30
Kovid Goyal
5c34f16ab4
Fix #5600 2022-10-19 07:45:27 +05:30
Kovid Goyal
03fe928e3f
show progress while compressing release tarballs 2022-10-17 09:55:09 +05:30
Kovid Goyal
55b53bcac6
version 0.26.4 2022-10-17 08:18:51 +05:30
Kovid Goyal
57d044861f
Merge branch 'patch-1' of https://github.com/ms-test/kitty 2022-10-16 13:28:06 +05:30
ms-test
aab149366d
Check correct pair member
I haven't looked deeply, but this looked to be a simple typo unless it's checking one both times because of a type invariant. If that is the case, and the check is correct, then a comment and/or code refactoring to call attention to this would likely be a good idea.
2022-10-16 03:53:16 -04:00
Kovid Goyal
896f93822d
kitty shell: Also output active tab id
Fixes #5590
2022-10-16 08:52:35 +05:30
Kovid Goyal
6890e265b6
GNOME Wayland: Fix a memory leak in gnome-shell when using client side decorations
destroy CSD buffers that were never attached explicitly, as mutter does
not send release events for these even when the pool is destroyed.
2022-10-12 17:52:47 +05:30
Kovid Goyal
48a4edc199
Merge branch 'action_cwd_doc' of https://github.com/cbosdo/kitty 2022-10-10 14:04:29 +05:30
Cédric Bosdonnat
d63be90a7f
Recommend using --cwd=current in open-actions.conf
Editors like Vim are basing path-related commands on the current working
directory. Launching the action with the current CWD in hyperlink opens
makes life easier and would work with every editor.
2022-10-10 10:12:20 +02:00
Kovid Goyal
6af020e4ef
Merge branch 'marksisson/simple-docs-change' of https://github.com/marksisson/kitty 2022-10-09 12:18:25 +05:30
Mark Sisson
ca24e9ca67
change linux_package build instructions to use make target 2022-10-09 00:02:38 -05:00
Kovid Goyal
fbfaefd72a
Wayland: Fix an abort when changing background colors with wayland_titlebar_color set to background
Fixes #5562
2022-10-07 14:13:12 +05:30
Kovid Goyal
94b3776066
Merge branch 'master' of https://github.com/Diff-fusion/kitty 2022-10-05 09:09:23 +05:30
Felix
15e4be9051 Fix clipboard target properties and memory leak 2022-10-04 17:22:15 +02:00
Kovid Goyal
ae8f3de070
Allow centering the background image
Fixes #5525
2022-10-04 08:26:28 +05:30
Kovid Goyal
c8d18ffe26
Add a note about yet another gnome bug 2022-10-03 22:06:00 +05:30
Kovid Goyal
4d80427908
Wayland: Fix background image scaling using tiled mode on high DPI screens 2022-10-03 21:49:52 +05:30
Kovid Goyal
0e69324469
Fix resize draw strategy == static causing background image/borders to not be drawn 2022-10-03 21:40:00 +05:30
Kovid Goyal
cf22729dfa
Fix background_tint not applying to window margins and padding
Fixes #3933
2022-10-03 21:39:57 +05:30
Kovid Goyal
1402c5bbfa
Forgot to change check for space for next tab to use its max tab length rather than the current tabs max tab length, since they can now be different 2022-10-03 16:21:50 +05:30
Kovid Goyal
f0f0c8f4fe
max_title_length -> max_tab_length 2022-10-03 16:15:24 +05:30
Kovid Goyal
96faac95db
DRYer 2022-10-03 15:32:42 +05:30
Kovid Goyal
08041415d1
Document the purpose of for_layout 2022-10-03 13:26:55 +05:30
Kovid Goyal
647b18d345
Tab bar: Improve empty space management when some tabs have short titles, allocate the saved space to the active tab
Fixes #5548
2022-10-03 13:24:21 +05:30
Kovid Goyal
a116e3cadd
Merge branch 'patch-1' of https://github.com/sorrycc/kitty 2022-09-30 07:46:32 +05:30
chencheng (云谦)
52c9b5f5b8
Update custom.css 2022-09-30 08:44:09 +08:00
Kovid Goyal
bbc9f588f1
Merge branch 'unicode-15' of https://github.com/page-down/kitty 2022-09-29 09:17:02 +05:30
pagedown
13a3c6b5b2
Update to Unicode 15.0 2022-09-29 10:13:21 +08:00
pagedown
fc15b20f24
Update to Nerd Fonts 2.2.2 2022-09-29 10:13:10 +08:00
Kovid Goyal
cd8f2e5cc6
another mypy update another round of breakage 2022-09-27 07:19:03 +05:30
Kovid Goyal
267798a277
Update the docs of open_url_with to indicate that open-actions.conf is read by the "default" handler 2022-09-26 20:21:44 +05:30
Kovid Goyal
921ac12e90
Clear both actions caches when config file is reloaded 2022-09-26 20:15:08 +05:30
Kovid Goyal
901e00cab1
Cleanup previous PR
1) Dont use deprecated code
2) Always set the dock icon on startup as the dock icon doesnt change
   till the dock is restarted
3) Update the app icon automatically if the mtime on the custom icon in
   the config dir is newer than the mtime of the sentinel file apple
   puts inside the application bundle to indicate it has a custom icon
2022-09-25 18:11:17 +05:30
Kovid Goyal
d0769f3979
... 2022-09-25 17:36:32 +05:30
Kovid Goyal
7e4dd8cf1e
Merge branch 'macos-set-icon' of https://github.com/page-down/kitty 2022-09-25 14:40:36 +05:30
Kovid Goyal
5ea0519f62
Pass through python used for type check to the test code from before the env is sanitized 2022-09-25 14:36:12 +05:30
pagedown
a1029418f8
macOS: Allow to set custom app icon automatically 2022-09-25 15:25:43 +08:00
Kovid Goyal
98eacb2067
panel kitten: Do not depend on xprop 2022-09-24 15:44:54 +05:30
Kovid Goyal
2cef9abbd3
Get rid of one call to xprop in the panel kitten 2022-09-24 15:17:11 +05:30
Kovid Goyal
0fa158c809
Merge branch 'docs' of https://github.com/page-down/kitty 2022-09-24 14:38:42 +05:30
pagedown
c54a6b398b
Add some missing no_response for rc commands 2022-09-24 12:43:13 +08:00
pagedown
27ea367123
Docs: Remove the extra backslashes from the install commands 2022-09-24 12:39:05 +08:00
Kovid Goyal
42178a4570
X11: Fix a regression in the previous release that caused pasting from GTK based applications to have extra newlines
Fixes #5528

And let me just re-iterate, GNOME/GTK is developed by morons.
2022-09-24 08:56:50 +05:30
Kovid Goyal
e98ecc1c4f
Another auto-indent fix 2022-09-24 08:34:07 +05:30
Kovid Goyal
0d64246209
fix vim autoindent 2022-09-24 08:31:14 +05:30
Kovid Goyal
a0495219ab
... 2022-09-24 08:30:40 +05:30
Kovid Goyal
9d98aa3159
Merge branch 'patch-2' of https://github.com/sashashura/kitty 2022-09-24 07:29:42 +05:30
Alex
5c82f4beca build: harden ci.yml permissions
Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-09-23 22:14:57 +02:00
Alex
13539bd8c6 build: harden codeql-analysis.yml permissions
Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-09-23 22:14:16 +02:00
Kovid Goyal
26b8ab9adf
Use a regex for bracketed paste sanitization 2022-09-23 22:18:03 +05:30
Weng Xuetian
7fd119d0eb
Fix message recursion between wayland compositor (#5360)
1. Only update preedit if preedit changed.
2. Only send cursor update if cursor position is not changed.
2022-08-11 15:45:45 -07:00
563 changed files with 110575 additions and 92426 deletions

View File

@ -1,12 +1,12 @@
root = true
[*]
indent_style = spaces
indent_style = space
indent_size = 4
end_of_line = lf
trim_trailing_whitespace = true
[{Makefile,*.terminfo}]
[{Makefile,*.terminfo,*.go}]
indent_style = tab
# Autogenerated files with tabs below this line.

5
.gitattributes vendored
View File

@ -3,7 +3,9 @@ kitty/emoji.h linguist-generated=true
kitty/charsets.c linguist-generated=true
kitty/key_encoding.py linguist-generated=true
kitty/unicode-data.c linguist-generated=true
kitty/rowcolumn-diacritics.c linguist-generated=true
kitty/rgb.py linguist-generated=true
kitty/srgb_gamma.c linguist-generated=true
kitty/gl-wrapper.* linguist-generated=true
kitty/glfw-wrapper.* linguist-generated=true
kitty/parse-graphics-command.h linguist-generated=true
@ -15,6 +17,9 @@ kittens/diff/options/parse.py linguist-generated=true
glfw/*.c linguist-vendored=true
glfw/*.h linguist-vendored=true
kittens/unicode_input/names.h linguist-generated=true
tools/wcswidth/std.go linguist-generated=true
tools/unicode_names/names.txt linguist-generated=true
*.py text diff=python
*.m text diff=objc
*.go text diff=go

4
.github/FUNDING.yml vendored
View File

@ -1,4 +1,2 @@
github: kovidgoyal
patreon: kovidgoyal
liberapay: kovidgoyal
custom: https://my.fsf.org/donate
custom: https://sw.kovidgoyal.net/kitty/support.html

View File

@ -30,8 +30,9 @@ def install_deps():
print('Installing kitty dependencies...')
sys.stdout.flush()
if is_macos:
items = (x.split()[1].strip('"') for x in open('Brewfile').readlines() if x.strip().startswith('brew '))
items = [x.split()[1].strip('"') for x in open('Brewfile').readlines() if x.strip().startswith('brew ')]
openssl = 'openssl'
items.remove('go') # already installed by ci.yml
import ssl
if ssl.OPENSSL_VERSION_INFO[0] == 1:
openssl += '@1.1'
@ -129,6 +130,12 @@ def main():
package_kitty()
elif action == 'test':
test_kitty()
elif action == 'gofmt':
q = subprocess.check_output('gofmt -s -l tools'.split())
if q.strip():
q = '\n'.join(filter(lambda x: not x.rstrip().endswith('_generated.go'), q.decode().strip().splitlines())).strip()
if q:
raise SystemExit(q)
else:
raise SystemExit(f'Unknown action: {action}')

View File

@ -6,6 +6,9 @@ env:
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
linux:
name: Linux (python=${{ matrix.pyver }} cc=${{ matrix.cc }} sanitize=${{ matrix.sanitize }})
@ -24,11 +27,11 @@ jobs:
sanitize: 0
- python: b
pyver: "3.9"
pyver: "3.11"
sanitize: 1
- python: c
pyver: "3.10"
pyver: "3.9"
sanitize: 1
@ -45,11 +48,17 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 10
- name: Set up Python ${{ matrix.pyver }}
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.pyver }}
- name: Install Go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
- name: Build kitty
run: python .github/workflows/ci.py build
@ -68,18 +77,26 @@ jobs:
fetch-depth: 0 # needed for :commit: docs role
- name: Test for trailing whitespace
run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst *.go .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: "3.10"
- name: Install Go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
- name: Install build-only deps
run: pip install -r docs/requirements.txt flake8 mypy types-requests types-docutils
run: python -m pip install -r docs/requirements.txt ruff mypy types-requests types-docutils
- name: Run pyflakes
run: python -m flake8 --count .
- name: Run ruff
run: ruff .
- name: Run gofmt
run: go version && python .github/workflows/ci.py gofmt
- name: Build kitty package
run: python .github/workflows/ci.py package
@ -87,8 +104,14 @@ jobs:
- name: Build kitty
run: python setup.py build --debug
- name: Build static kitten
run: python setup.py build-static-binaries
- name: Run mypy
run: ./test.py mypy
run: which python && python -m mypy --version && ./test.py mypy
- name: Run go vet
run: go version && go vet ./...
- name: Build man page
run: make FAIL_WARN=1 man
@ -106,10 +129,15 @@ jobs:
KITTY_BUNDLE: 1
steps:
- name: Checkout source code
uses: actions/checkout@master
uses: actions/checkout@v3
with:
fetch-depth: 10
- name: Install Go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
- name: Build kitty
run: which python3 && python3 .github/workflows/ci.py build
@ -121,10 +149,20 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout source code
uses: actions/checkout@master
uses: actions/checkout@v3
with:
fetch-depth: 0 # needed for :commit: docs role
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
- name: Build kitty
run: python3 .github/workflows/ci.py build

View File

@ -9,12 +9,20 @@ on:
schedule:
- cron: '0 22 * * 5'
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
CodeQL-Build:
permissions:
contents: read # to fetch code (actions/checkout)
security-events: write # to upload SARIF results (github/codeql-action/analyze)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
@ -22,9 +30,14 @@ jobs:
# a pull request then we can checkout the head.
fetch-depth: 2
- name: Install Go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: python, c
setup-python-dependencies: false
@ -33,4 +46,4 @@ jobs:
run: python3 .github/workflows/ci.py build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

7
.gitignore vendored
View File

@ -1,6 +1,7 @@
*.so
*.pyc
*.pyo
*.bin
*_stub.pyi
*_generated.go
*_generated.h
@ -9,16 +10,16 @@
/build/
/linux-package/
/kitty.app/
/compile_commands.json
/link_commands.json
/glad/out/
/kitty/launcher/kitty*
/kitty/launcher/kitt*
/*.dSYM/
__pycache__/
/glfw/wayland-*-client-protocol.[ch]
/docs/_build/
/docs/generated/
/.mypy_cache
/.ruff_cache
.DS_Store
.cache
bypy/b
bypy/virtual-machines.conf

View File

@ -5,3 +5,4 @@ brew "python"
brew "imagemagick"
brew "harfbuzz"
brew "sphinx-doc"
brew "go"

View File

@ -7,6 +7,11 @@ When reporting a bug, provide full details of your environment, that means, at
a minimum, kitty version, OS and OS version, kitty config (ideally a minimal
config to reproduce the issue with).
Note that bugs and feature requests are often closed quickly as they are either
fixed or deemed wontfix/invalid. In my experience, this is the only scaleable way to
manage a bug tracker. Feel free to continue to post to a closed bug report
if you would like to discuss the issue further. Being closed does not mean you
will not get any more responses.
### Contributing code

View File

@ -11,9 +11,8 @@ import sys
import tempfile
from contextlib import suppress
from bypy.constants import (
LIBDIR, PREFIX, PYTHON, SRC as KITTY_DIR, ismacos, worker_env
)
from bypy.constants import LIBDIR, PREFIX, PYTHON, ismacos, worker_env
from bypy.constants import SRC as KITTY_DIR
from bypy.utils import run_shell, walk
@ -63,20 +62,31 @@ def build_frozen_launcher(extra_include_dirs):
def run_tests(kitty_exe):
with tempfile.TemporaryDirectory() as tdir:
env = {
uenv = {
'KITTY_CONFIG_DIRECTORY': os.path.join(tdir, 'conf'),
'KITTY_CACHE_DIRECTORY': os.path.join(tdir, 'cache')
}
[os.mkdir(x) for x in env.values()]
cmd = [kitty_exe, '+runpy', 'from kitty_tests.main import run_tests; run_tests()']
[os.mkdir(x) for x in uenv.values()]
env = os.environ.copy()
env.update(uenv)
cmd = [kitty_exe, '+runpy', 'from kitty_tests.main import run_tests; run_tests(report_env=True)']
print(*map(shlex.quote, cmd), flush=True)
if subprocess.call(cmd, env=env) != 0:
print('Checking of kitty build failed', file=sys.stderr)
if subprocess.call(cmd, env=env, cwd=build_frozen_launcher.writeable_src_dir) != 0:
print('Checking of kitty build failed, in directory:', build_frozen_launcher.writeable_src_dir, file=sys.stderr)
os.chdir(os.path.dirname(kitty_exe))
run_shell()
raise SystemExit('Checking of kitty build failed')
def build_frozen_tools(kitty_exe):
cmd = SETUP_CMD + ['--prefix', os.path.dirname(kitty_exe)] + ['build-frozen-tools']
if run(*cmd, cwd=build_frozen_launcher.writeable_src_dir) != 0:
print('Building of frozen kitten failed', file=sys.stderr)
os.chdir(KITTY_DIR)
run_shell()
raise SystemExit('Building of kitten launcher failed')
def sanitize_source_folder(path: str) -> None:
for q in walk(path):
if os.path.splitext(q)[1] not in ('.py', '.glsl', '.ttf', '.otf'):
@ -96,6 +106,8 @@ def build_c_extensions(ext_dir, args):
cmd = SETUP_CMD + ['macos-freeze' if ismacos else 'linux-freeze']
if args.dont_strip:
cmd.append('--debug')
if args.extra_program_data:
cmd.append(f'--vcs-rev={args.extra_program_data}')
dest = kitty_constants['appname'] + ('.app' if ismacos else '')
dest = build_frozen_launcher.prefix = os.path.join(ext_dir, dest)
cmd += ['--prefix', dest, '--full']

View File

@ -1,3 +1,3 @@
image 'https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-{}.img'
deps 'bison flex libxcursor-dev libxrandr-dev libxi-dev libxinerama-dev libgl1-mesa-dev libxcb-xkb-dev libfontconfig1-dev libdbus-1-dev'
deps 'bison flex libxcursor-dev libxrandr-dev libxi-dev libxinerama-dev libgl1-mesa-dev libx11-xcb-dev libxcb-xkb-dev libfontconfig1-dev libdbus-1-dev'

View File

@ -10,12 +10,8 @@ import subprocess
import tarfile
import time
from bypy.constants import (
OUTPUT_DIR, PREFIX, is64bit, python_major_minor_version
)
from bypy.freeze import (
extract_extension_modules, freeze_python, path_to_freeze_dir
)
from bypy.constants import OUTPUT_DIR, PREFIX, is64bit, python_major_minor_version
from bypy.freeze import extract_extension_modules, freeze_python, path_to_freeze_dir
from bypy.utils import get_dll_path, mkdtemp, py_compile, walk
j = os.path.join
@ -220,7 +216,7 @@ def create_tarfile(env, compression_level='9'):
print('Compressing archive...')
ans = f'{dist.rpartition(".")[0]}.txz'
start_time = time.time()
subprocess.check_call(['xz', '--threads=0', '-f', f'-{compression_level}', dist])
subprocess.check_call(['xz', '--verbose', '--threads=0', '-f', f'-{compression_level}', dist])
secs = time.time() - start_time
print('Compressed in {} minutes {} seconds'.format(secs // 60, secs % 60))
os.rename(f'{dist}.xz', ans)
@ -238,10 +234,12 @@ def main():
files = find_binaries(env)
fix_permissions(files)
add_ca_certs(env)
kitty_exe = os.path.join(env.base, 'bin', 'kitty')
iv['build_frozen_tools'](kitty_exe)
if not args.dont_strip:
strip_binaries(files)
if not args.skip_tests:
iv['run_tests'](os.path.join(env.base, 'bin', 'kitty'))
iv['run_tests'](kitty_exe)
create_tarfile(env, args.compression_level)

View File

@ -1,4 +1,4 @@
# Requires installation of XCode 10.3 and Python 3 and
# Requires installation of XCode 10.3 and go 1.19 and Python 3 and
# python3 -m pip install certifi
vm_name 'macos-kitty'

View File

@ -13,16 +13,9 @@ import tempfile
import zipfile
from bypy.constants import PREFIX, PYTHON, SW, python_major_minor_version
from bypy.freeze import (
extract_extension_modules, freeze_python, path_to_freeze_dir
)
from bypy.macos_sign import (
codesign, create_entitlements_file, make_certificate_useable, notarize_app,
verify_signature
)
from bypy.utils import (
current_dir, mkdtemp, py_compile, run_shell, timeit, walk
)
from bypy.freeze import extract_extension_modules, freeze_python, path_to_freeze_dir
from bypy.macos_sign import codesign, create_entitlements_file, make_certificate_useable, notarize_app, verify_signature
from bypy.utils import current_dir, mkdtemp, py_compile, run_shell, timeit, walk
iv = globals()['init_env']
kitty_constants = iv['kitty_constants']
@ -113,6 +106,9 @@ def do_sign(app_dir):
codesign(fw)
items = set(os.listdir('.')) - fw
codesign(expand_dirs(items))
# Sign kitten
with current_dir('MacOS'):
codesign('kitten')
# Now sign the main app
codesign(app_dir)
@ -171,6 +167,7 @@ class Freeze(object):
self.add_misc_libraries()
self.freeze_python()
self.add_ca_certs()
self.build_frozen_tools()
if not self.dont_strip:
self.strip_files()
if not self.skip_tests:
@ -378,6 +375,10 @@ class Freeze(object):
if f.endswith('.so') or f.endswith('.dylib'):
self.fix_dependencies_in_lib(f)
@flush
def build_frozen_tools(self):
iv['build_frozen_tools'](join(self.contents_dir, 'MacOS', 'kitty'))
@flush
def add_site_packages(self):
print('\nAdding site-packages')

View File

@ -1 +1 @@
to_vm_excludes '/build /dist /kitty/launcher/kitty /.build-cache /tags __pycache__ /*_commands.json *.so *.pyd *.pyc'
to_vm_excludes '/build /dist /kitty/launcher/kitty* /.build-cache /tags __pycache__ /*_commands.json *.so *.pyd *.pyc *_generated.go'

View File

@ -2,8 +2,8 @@
{
"name": "zlib",
"unix": {
"filename": "zlib-1.2.11.tar.xz",
"hash": "sha256:4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
"filename": "zlib-1.2.13.tar.xz",
"hash": "sha256:d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98",
"urls": ["https://zlib.net/{filename}"]
}
},
@ -163,15 +163,6 @@
}
},
{
"name": "pygments",
"unix": {
"filename": "Pygments-2.11.2.tar.gz",
"hash": "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a",
"urls": ["pypi"]
}
},
{
"name": "libpng",
"unix": {

View File

@ -2,29 +2,20 @@
import subprocess
files_to_exclude = '''\
kitty/wcwidth-std.h
kitty/charsets.c
kitty/unicode-data.c
kitty/key_encoding.py
kitty/rgb.py
kitty/gl.h
kitty/gl-wrapper.h
kitty/gl-wrapper.c
kitty/glfw-wrapper.h
kitty/glfw-wrapper.c
kitty/emoji.h
kittens/unicode_input/names.h
kitty/parse-graphics-command.h
kitty/options/types.py
kitty/options/parse.py
kitty/options/to-c-generated.h
kittens/diff/options/types.py
kittens/diff/options/parse.py
'''
ignored = []
for line in subprocess.check_output(['git', 'status', '--ignored', '--porcelain']).decode().splitlines():
if line.startswith('!! '):
ignored.append(line[3:])
files_to_exclude = '\n'.join(ignored)
cp = subprocess.run(['git', 'check-attr', 'linguist-generated', '--stdin'],
check=True, stdout=subprocess.PIPE, input=subprocess.check_output([ 'git', 'ls-files']))
for line in cp.stdout.decode().splitlines():
if line.endswith(' true'):
files_to_exclude += '\n' + line.split(':')[0]
p = subprocess.Popen([
'cloc', '--exclude-list-file', '/dev/stdin', 'kitty', 'kittens'
'cloc', '--exclude-list-file', '/dev/stdin', 'kitty', 'kittens', 'tools', 'kitty_tests', 'docs',
], stdin=subprocess.PIPE)
p.communicate(files_to_exclude.encode('utf-8'))
raise SystemExit(p.wait())

View File

@ -10,7 +10,7 @@
}
.sidebar-logo {
max-height: 128px;
height: 128px;
}
.major-features li {

View File

@ -27,6 +27,11 @@ Browse scrollback in less :sc:`show_scrollback`
Browse last cmd output :sc:`show_last_command_output` (see :ref:`shell_integration`)
========================= =======================
The scroll actions only take effect when the terminal is in the main screen.
When the alternate screen is active (for example when using a full screen
program like an editor) the key events are instead passed to program running in the
terminal.
Tabs
~~~~~~~~~~~
@ -53,6 +58,7 @@ Action Shortcut
New window :sc:`new_window` (also :kbd:`⌘+↩` on macOS)
New OS window :sc:`new_os_window` (also :kbd:`⌘+n` on macOS)
Close window :sc:`close_window` (also :kbd:`⇧+⌘+d` on macOS)
Resize window :sc:`start_resizing_window` (also :kbd:`⌘+r` on macOS)
Next window :sc:`next_window`
Previous window :sc:`previous_window`
Move window forward :sc:`move_window_forward`

View File

@ -22,7 +22,8 @@ simply re-run the command.
.. warning::
**Do not** copy the kitty binary out of the installation folder. If you want
to add it to your :envvar:`PATH`, create a symlink in :file:`~/.local/bin` or
:file:`/usr/bin` or wherever.
:file:`/usr/bin` or wherever. You should create a symlink for the :file:`kitten`
binary as well.
Manually installing
@ -30,7 +31,7 @@ Manually installing
If something goes wrong or you simply do not want to run the installer, you can
manually download and install |kitty| from the `GitHub releases page
<https://github.com/kovidgoyal/kitty/releases>`__. If you are on macOS, download
<https://gitea.rexy712.xyz/KittyPatch/kitty/releases>`__. If you are on macOS, download
the :file:`.dmg` and install as normal. If you are on Linux, download the
tarball and extract it into a directory. The |kitty| executable will be in the
:file:`bin` sub-directory.
@ -46,9 +47,9 @@ particular desktop, but it should work for most major desktop environments.
.. code-block:: sh
# Create a symbolic link to add kitty to PATH (assuming ~/.local/bin is in
# Create symbolic links to add kitty and kitten to PATH (assuming ~/.local/bin is in
# your system-wide PATH)
ln -s ~/.local/kitty.app/bin/kitty ~/.local/bin/
ln -sf ~/.local/kitty.app/bin/kitty ~/.local/kitty.app/bin/kitten ~/.local/bin/
# Place the kitty.desktop file somewhere it can be found by the OS
cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications/
# If you want to open text files and images in kitty via your file manager also add the kitty-open.desktop file
@ -85,7 +86,7 @@ Customizing the installation
.. code-block:: sh
_kitty_install_cmd \\
_kitty_install_cmd \
installer=nightly
If you want to install it in parallel to the released kitty specify a
@ -93,14 +94,14 @@ Customizing the installation
.. code-block:: sh
_kitty_install_cmd \\
_kitty_install_cmd \
installer=nightly dest=/some/other/location
* You can specify a different install location, with ``dest``:
.. code-block:: sh
_kitty_install_cmd \\
_kitty_install_cmd \
dest=/some/other/location
* You can tell the installer not to launch |kitty| after installing it with
@ -108,14 +109,14 @@ Customizing the installation
.. code-block:: sh
_kitty_install_cmd \\
_kitty_install_cmd \
launch=n
* You can use a previously downloaded dmg/tarball, with ``installer``:
.. code-block:: sh
_kitty_install_cmd \\
_kitty_install_cmd \
installer=/path/to/dmg or tarball

View File

@ -1,9 +1,9 @@
Build from source
==================
.. image:: https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg
.. image:: https://gitea.rexy712.xyz/KittyPatch/kitty/workflows/CI/badge.svg
:alt: Build status
:target: https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI
:target: https://gitea.rexy712.xyz/KittyPatch/kitty/actions?query=workflow%3ACI
.. highlight:: sh
@ -39,13 +39,13 @@ Run-time dependencies:
* ``freetype`` (not needed on macOS)
* ``fontconfig`` (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)
* ``pygments`` (optional, needed for syntax highlighting in ``kitty +kitten diff``)
* ``ImageMagick`` (optional, needed to display uncommon image formats in the terminal)
Build-time dependencies:
* ``gcc`` or ``clang``
* ``go`` >= _build_go_version (see :file:`go.mod` for go packages used during building)
* ``pkg-config``
* For building on Linux in addition to the above dependencies you might also
need to install the following packages, if they are not already installed by
@ -61,6 +61,7 @@ Build-time dependencies:
- ``libfontconfig-dev``
- ``libx11-xcb-dev``
- ``liblcms2-dev``
- ``libssl-dev``
- ``libpython3-dev``
- ``librsync-dev``
@ -70,7 +71,7 @@ Install and run from source
.. code-block:: sh
git clone https://github.com/kovidgoyal/kitty && cd kitty
git clone https://gitea.rexy712.xyz/KittyPatch/kitty && cd kitty
Now build the native code parts of |kitty| with the following command::
@ -105,7 +106,7 @@ dependencies you might have to rebuild the app.
.. note::
The released :file:`kitty.dmg` includes all dependencies, unlike the
:file:`kitty.app` built above and is built automatically by using the
`bypy framework <https://github.com/kovidgoyal/bypy>`__ however, that is
`bypy framework <https://gitea.rexy712.xyz/KittyPatch/bypy>`__ however, that is
designed to run on Linux and is not for the faint of heart.
.. note::
@ -154,13 +155,13 @@ Notes for Linux/macOS packagers
----------------------------------
The released |kitty| source code is available as a `tarball`_ from
`the GitHub releases page <https://github.com/kovidgoyal/kitty/releases>`__.
`the GitHub releases page <https://gitea.rexy712.xyz/KittyPatch/kitty/releases>`__.
While |kitty| does use Python, it is not a traditional Python package, so please
do not install it in site-packages.
Instead run::
python3 setup.py linux-package
make linux-package
This will install |kitty| into the directory :file:`linux-package`. You can run
|kitty| with :file:`linux-package/bin/kitty`. All the files needed to run kitty

View File

@ -35,6 +35,233 @@ mouse anywhere in the current command to move the cursor there. See
Detailed list of changes
-------------------------------------
0.28.2 [future]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A new escape code ``<ESC>[22J`` that moves the current contents of the screen into the scrollback before clearing it
- unicode_input kitten: Fix a regression in 0.28.0 that caused the order of recent and favorites entries to not be respected (:iss:`6214`)
- unicode_input kitten: Fix a regression in 0.28.0 that caused editing of favorites to sometimes hang
- clipboard kitten: Fix a bug causing the last MIME type available on the clipboard not being recognized when pasting
- Fix regression in 0.28.0 causing color fringing when rendering in transparent windows on light backgrounds (:iss:`6209`)
- show_key kitten: In kitty mode show the actual bytes sent by the terminal rather than a re-encoding of the parsed key event
- hints kitten: Fix a regression in 0.28.0 that broke using sub-groups in regexp captures (:iss:`6228`)
- hints kitten: Fix a regression in 0.28.0 that broke using lookahead/lookbehind in regexp captures (:iss:`6265`)
- diff kitten: Fix a regression in 0.28.0 that broke using relative paths as arguments to the kitten (:iss:`6325`)
- Fix re-using the image id of an animated image for a still image causing a crash (:iss:`6244`)
- kitty +open: Ask for permission before executing script files that are not marked as executable. This prevents accidental execution
of script files via MIME type association from programs that unconditionally "open" attachments/downloaded files
- edit-in-kitty: Fix running edit-in-kitty with elevated privileges to edit a restricted file not working (:disc:`6245`)
- ssh kitten: Fix a regression in 0.28.0 that caused interrupt during setup to not be handled gracefully (:iss:`6254`)
0.28.1 [2023-04-21]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix a regression in the previous release that broke the remote file kitten (:iss:`6186`)
- Fix a regression in the previous release that broke handling of some keyboard shortcuts in some kittens on some keyboard layouts (:iss:`6189`)
- Fix a regression in the previous release that broke usage of custom themes (:iss:`6191`)
0.28.0 [2023-04-15]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- **Text rendering change**: Use sRGB correct linear gamma blending for nicer font
rendering and better color accuracy with transparent windows.
See the option :opt:`text_composition_strategy` for details.
The obsolete :opt:`macos_thicken_font` will make the font too thick and needs to be removed manually
if it is configured. (:pull:`5969`)
- icat kitten: Support display of images inside tmux >= 3.3 (:pull:`5664`)
- Graphics protocol: Add support for displaying images inside programs that do not support the protocol such as vim and tmux (:pull:`5664`)
- diff kitten: Add support for selecting multi-line text with the mouse
- Fix a regression in 0.27.0 that broke ``kitty @ set-font-size 0`` (:iss:`5992`)
- launch: When using ``--cwd=current`` for a remote system support running non shell commands as well (:disc:`5987`)
- When changing the cursor color via escape codes or remote control to a fixed color, do not reset cursor_text_color (:iss:`5994`)
- Input Method Extensions: Fix incorrect rendering of IME in-progress and committed text in some situations (:pull:`6049`, :pull:`6087`)
- Linux: Reduce minimum required OpenGL version from 3.3 to 3.1 + extensions (:iss:`2790`)
- Fix a regression that broke drawing of images below cell backgrounds (:iss:`6061`)
- macOS: Fix the window buttons not being hidden after exiting the traditional full screen (:iss:`6009`)
- When reloading configuration, also reload custom MIME types from :file:`mime.types` config file (:pull:`6012`)
- launch: Allow specifying the state (full screen/maximized/minimized) for newly created OS Windows (:iss:`6026`)
- Sessions: Allow specifying the OS window state via the ``os_window_state`` directive (:iss:`5863`)
- macOS: Display the newly created OS window in specified state to avoid or reduce the window transition animations (:pull:`6035`)
- macOS: Fix the maximized window not taking up full space when the title bar is hidden or when :opt:`resize_in_steps` is configured (:iss:`6021`)
- Linux: A new option :opt:`linux_bell_theme` to control which sound theme is used for the bell sound (:pull:`4858`)
- ssh kitten: Change the syntax of glob patterns slightly to match common usage
elsewhere. Now the syntax is the same as "extendedglob" in most shells.
- hints kitten: Allow copying matches to named buffers (:disc:`6073`)
- Fix overlay windows not inheriting the per-window padding and margin settings
of their parents (:iss:`6063`)
- Wayland KDE: Fix selecting in un-focused OS window not working correctly (:iss:`6095`)
- Linux X11: Fix a crash if the X server requests clipboard data after we have relinquished the clipboard (:iss:`5650`)
- Allow stopping of URL detection at newlines via :opt:`url_excluded_characters` (:iss:`6122`)
- Linux Wayland: Fix animated images not being animated continuously (:iss:`6126`)
- Keyboard input: Fix text not being reported as unicode codepoints for multi-byte characters in the kitty keyboard protocol (:iss:`6167`)
0.27.1 [2023-02-07]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix :opt:`modify_font` not working for strikethrough position (:iss:`5946`)
- Fix a regression causing the ``edit-in-kitty`` command not working if :file:`kitten` is not added
to PATH (:iss:`5956`)
- icat kitten: Fix a regression that broke display of animated GIFs over SSH (:iss:`5958`)
- Wayland GNOME: Fix for ibus not working when using XWayland (:iss:`5967`)
- Fix regression in previous release that caused incorrect entries in terminfo for modifier+F3 key combinations (:pull:`5970`)
- Bring back the deprecated and removed ``kitty +complete`` and delegate it to :program:`kitten` for backward compatibility (:pull:`5977`)
- Bump the version of Go needed to build kitty to ``1.20`` so we can use the Go stdlib ecdh package for crypto.
0.27.0 [2023-01-31]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A new statically compiled, standalone executable, ``kitten`` (written in Go)
that can be used on all UNIX-like servers for remote control (``kitten @``),
viewing images (``kitten icat``), manipulating the clipboard (``kitten clipboard``), etc.
- :doc:`clipboard kitten </kittens/clipboard>`: Allow copying arbitrary data types to/from the clipboard, not just plain text
- Speed up the ``kitty @`` executable by ~10x reducing the time for typical
remote control commands from ~50ms to ~5ms
- icat kitten: Speed up by using POSIX shared memory when possible to transfer
image data to the terminal. Also support common image formats
GIF/PNG/JPEG/WEBP/TIFF/BMP out of the box without needing ImageMagick.
- Option :opt:`show_hyperlink_targets` to show the target of terminal hyperlinks when hovering over them with the mouse (:pull:`5830`)
- Keyboard protocol: Remove ``CSI R`` from the allowed encodings of the :kbd:`F3` key as it conflicts with the *Cursor Position Report* escape code (:disc:`5813`)
- Allow using the cwd of the original process for :option:`launch --cwd` (:iss:`5672`)
- Session files: Expand environment variables (:disc:`5917`)
- Pass key events mapped to scroll actions to the program running in the terminal when the terminal is in alternate screen mode (:iss:`5839`)
- Implement :ref:`edit-in-kitty <edit_file>` using the new ``kitten`` static executable (:iss:`5546`, :iss:`5630`)
- Add an option :opt:`background_tint_gaps` to control background image tinting for window gaps (:iss:`5596`)
- A new option :opt:`undercurl_style` to control the rendering of undercurls (:pull:`5883`)
- Bash integration: Fix ``clone-in-kitty`` not working on bash >= 5.2 if environment variable values contain newlines or other special characters (:iss:`5629`)
- A new :ac:`sleep` action useful in combine based mappings to make kitty sleep before executing the next action
- Wayland GNOME: Workaround for latest mutter release breaking full screen for semi-transparent kitty windows (:iss:`5677`)
- A new option :opt:`tab_title_max_length` to limit the length of tab (:iss:`5718`)
- When drawing the tab bar have the default left and right margins drawn in a color matching the neighboring tab (:iss:`5719`)
- When using the :code:`include` directive in :file:`kitty.conf` make the environment variable :envvar:`KITTY_OS` available for OS specific config
- Wayland: Fix signal handling not working with some GPU drivers (:iss:`4636`)
- Remote control: When matching windows allow using negative id numbers to match recently created windows (:iss:`5753`)
- ZSH Integration: Bind :kbd:`alt+left` and :kbd:`alt+right` to move by word if not already bound. This mimics the default bindings in Terminal.app (:iss:`5793`)
- macOS: Allow to customize :sc:`Hide <hide_macos_app>`, :sc:`Hide Others <hide_macos_other_apps>`, :sc:`Minimize <minimize_macos_window>`, and :sc:`Quit <quit>` global menu shortcuts. Note that :opt:`clear_all_shortcuts` will remove these shortcuts now (:iss:`948`)
- When a multi-key sequence does not match any action, send all key events to the child program (:pull:`5841`)
- broadcast kitten: Allow pressing a key to stop echoing of input into the broadcast window itself (:disc:`5868`)
- When reporting unused activity in a window, ignore activity that occurs soon after a window resize (:iss:`5881`)
- Fix using :opt:`cursor` = ``none`` not working on text that has reverse video (:iss:`5897`)
- Fix ssh kitten not working on FreeBSD (:iss:`5928`)
- macOS: Export kitty selected text to the system for use with services that accept it (patch by Sertaç Ö. Yıldız)
0.26.5 [2022-11-07]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Splits layout: Add a new mappable action to move the active window to the screen edge (:iss:`5643`)
- ssh kitten: Allow using absolute paths for the location of transferred data (:iss:`5607`)
- Fix a regression in the previous release that caused a :opt:`resize_draw_strategy` of ``static`` to not work (:iss:`5601`)
- Wayland KDE: Fix abort when pasting into Firefox (:iss:`5603`)
- Wayland GNOME: Fix ghosting when using :opt:`background_tint` (:iss:`5605`)
- Fix cursor position at x=0 changing to x=1 on resize (:iss:`5635`)
- Wayland GNOME: Fix incorrect window size in some circumstances when switching between windows with window decorations disabled (:iss:`4802`)
- Wayland: Fix high CPU usage when using some input methods (:pull:`5369`)
- Remote control: When matching window by `state:focused` and no window currently has keyboard focus, match the window belonging to the OS window that was last focused (:iss:`5602`)
0.26.4 [2022-10-17]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- macOS: Allow changing the kitty icon by placing a custom icon in the kitty config folder (:pull:`5464`)
- Allow centering the :opt:`background_image` (:iss:`5525`)
- X11: Fix a regression in the previous release that caused pasting from GTK based applications to have extra newlines (:iss:`5528`)
- Tab bar: Improve empty space management when some tabs have short titles, allocate the saved space to the active tab (:iss:`5548`)
- Fix :opt:`background_tint` not applying to window margins and padding (:iss:`3933`)
- Wayland: Fix background image scaling using tiled mode on high DPI screens
- Wayland: Fix an abort when changing background colors with :opt:`wayland_titlebar_color` set to ``background`` (:iss:`5562`)
- Update to Unicode 15.0 (:pull:`5542`)
- GNOME Wayland: Fix a memory leak in gnome-shell when using client side decorations
0.26.3 [2022-09-22]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -85,6 +312,7 @@ Detailed list of changes
code execution if the user clicked on a notification popup from a malicious
source. Thanks to Carter Sande for discovering this vulnerability.
0.26.1 [2022-08-30]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -94,6 +322,7 @@ Detailed list of changes
- Allow specifying a title when using the :ac:`set_tab_title` action (:iss:`5441`)
0.26.0 [2022-08-29]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1580,6 +1809,7 @@ Detailed list of changes
- Fix :option:`--title` not being applied at window creation time (:iss:`2570`)
0.17.2 [2020-03-29]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1764,6 +1994,7 @@ Detailed list of changes
- When windows are semi-transparent and all contain graphics, correctly render
them. (:iss:`2310`)
0.15.1 [2019-12-21]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1872,6 +2103,7 @@ Detailed list of changes
- Use selection foreground color for underlines as well (:iss:`1982`)
0.14.4 [2019-08-31]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2178,6 +2410,7 @@ Detailed list of changes
- Mouse selection: When extending by word, fix extending selection to non-word
characters not working well (:iss:`1616`)
0.13.3 [2019-01-19]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2271,6 +2504,7 @@ Detailed list of changes
- Fix resizing window smaller and then restoring causing some wrapped lines to not
be properly unwrapped (:iss:`1206`)
0.13.0 [2018-12-05]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2368,6 +2602,7 @@ Detailed list of changes
- Fix hover detection of URLs not working when hovering over the first colon
and slash characters in short URLs (:iss:`1201`)
0.12.3 [2018-09-29]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2444,6 +2679,7 @@ Detailed list of changes
- Fix using :opt:`focus_follows_mouse` causing text selection with the
mouse to malfunction when using multiple kitty windows (:iss:`1002`)
0.12.1 [2018-09-08]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2487,6 +2723,7 @@ Detailed list of changes
- macOS: Diff kitten: Fix syntax highlighting not working because of
a bug in the 0.12.0 macOS package
0.12.0 [2018-09-01]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2997,6 +3234,7 @@ Detailed list of changes
- Fix a crash when getting the contents of the scrollback buffer as text
0.8.1 [2018-03-09]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -3074,6 +3312,7 @@ Detailed list of changes
- Browsing the scrollback buffer now happens in an overlay window instead of a
new window/tab.
0.7.1 [2018-01-31]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

160
docs/clipboard.rst Normal file
View File

@ -0,0 +1,160 @@
Copying all data types to the clipboard
==============================================
There already exists an escape code to allow terminal programs to
read/write plain text data from the system clipboard, *OSC 52*.
kitty introduces a more advanced protocol that supports:
* Copy arbitrary data including images, rich text documents, etc.
* Allow terminals to ask the user for permission to access the clipboard and
report permission denied
The escape code is *OSC 5522*, an extension of *OSC 52*. The basic format
of the escape code is::
<OSC>5522;metadata;payload<ST>
Here, *metadata* is a colon separated list of key-value pairs and payload is
base64 encoded data. :code:`OSC` is :code:`<ESC>[`.
:code:`ST` is the string terminator, :code:`<ESC>\\`.
Reading data from the system clipboard
----------------------------------------
To read data from the system clipboard, the escape code is::
<OSC>5522;type=read;<base 64 encoded space separated list of mime types to read><ST>
For example, to read plain text and PNG data, the payload would be::
text/plain image/png
encoded as base64. To read from the primary selection instead of the
clipboard, add the key ``loc=primary`` to the metadata section.
To get the list of MIME types available on the clipboard the payload must be
just a period (``.``), encoded as base64.
The terminal emulator will reply with a sequence of escape codes of the form::
<OSC>5522;type=read:status=OK<ST>
<OSC>5522;type=read:status=DATA:mime=<base 64 encoded mime type>;<base64 encoded data><ST>
<OSC>5522;type=read:status=DATA:mime=<base 64 encoded mime type>;<base64 encoded data><ST>
.
.
.
<OSC>5522;type=read:status=DONE<ST>
Here, the ``status=DATA`` packets deliver the data (as base64 encoded bytes)
associated with each MIME type. The terminal emulator should chunk up the data
for an individual type. A recommended size for each chunk is 4096 bytes. All
the chunks for a given type must be transmitted sequentially and only once they
are done the chunks for the next type, if any, should be sent. The end of data
is indicated by a ``status=DONE`` packet.
If an error occurs, instead of the opening ``status=OK`` packet the terminal
must send a ``status=ERRORCODE`` packet. The error code must be one of:
``status=ENOSYS``
Sent if the requested clipboard type is not available. For example, primary
selection is not available on all systems and ``loc=primary`` was used.
``status=EPERM``
Sent if permission to read from the clipboard was denied by the system or
the user.
``status=EBUSY``
Sent if there is some temporary problem, such as multiple clients in a
multiplexer trying to access the clipboard simultaneously.
Terminals should ask the user for permission before allowing a read request.
However, if a read request only wishes to list the available data types on the
clipboard, it should be allowed without a permission prompt. This is so that
the user is not presented with a double permission prompt for reading the
available MIME types and then reading the actual data.
Writing data to the system clipboard
----------------------------------------
To write data to the system clipboard, the terminal programs sends the
following sequence of packets::
<OSC>5522;type=write<ST>
<OSC>5522;type=wdata:mime=<base64 encoded mime type>;<base 64 encoded chunk of data for this type><ST>
<OSC>5522;type=wdata:mime=<base64 encoded mime type>;<base 64 encoded chunk of data for this type><ST>
.
.
.
<OSC>5522;type=wdata<ST>
The final packet with no mime and no data indicates end of transmission. The
data for every MIME type should be split into chunks of no more than 4096
bytes. All the chunks for a given MIME type must be sent sequentially, before
sending chunks for the next MIME type. After the transmission is complete, the
terminal replies with a single packet indicating success::
<OSC>5522;type=write:status=DONE<ST>
If an error occurs the terminal can, at any time, send an error packet of the
form::
<OSC>5522;type=write:status=ERRORCODE<ST>
Here ``ERRORCODE`` must be one of:
``status=EIO``
An I/O error occurred while processing the data
``status=EINVAL``
One of the packets was invalid, usually because of invalid base64 encoding.
``status=ENOSYS``
The client asked to write to the primary selection with (``loc=primary``) and that is not
available on the system
``status=EPERM``
Sent if permission to write to the clipboard was denied by the system or
the user.
``status=EBUSY``
Sent if there is some temporary problem, such as multiple clients in a
multiplexer trying to access the clipboard simultaneously.
Once an error occurs, the terminal must ignore all further OSC 5522 write related packets until it
sees the start of a new write with a ``type=write`` packet.
The client can send to the primary selection instead of the clipboard by adding
``loc=primary`` to the initial ``type=write`` packet.
Finally, clients have the ability to *alias* MIME types when sending data to
the clipboard. To do that, the client must send a ``type=walias`` packet of the
form::
<OSC>5522;type=walias;mime=<base64 encoded target MIME type>;<base64 encoded, space separated list of aliases><ST>
The effect of an alias is that the system clipboard will make available all the
aliased MIME types, with the same data as was transmitted for the target MIME
type. This saves bandwidth, allowing the client to only transmit one copy of
the data, but create multiple references to it in the system clipboard. Alias
packets can be sent anytime after the initial write packet and before the end
of data packet.
Support for terminal multiplexers
------------------------------------
Since this protocol involves two way communication between the terminal
emulator and the client program, multiplexers need a way to know which window
to send responses from the terminal to. In order to make this possible, the
metadata portion of this escape code includes an optional ``id`` field. If
present the terminal emulator must send it back unchanged with every response.
Valid ids must include only characters from the set: ``[a-zA-Z0-9-_+.]``. Any
other characters must be stripped out from the id by the terminal emulator
before retransmitting it.
Note that when using a terminal multiplexer it is possible for two different
programs to tread on each others clipboard requests. This is fundamentally
unavoidable since the system clipboard is a single global shared resource.
However, there is an additional complication where responses form this protocol
could get lost if, for instance, multiple write requests are received
simultaneously. It is up to well designed multiplexers to ensure that only a
single request is in flight at a time. The multiplexer can abort requests by
sending back the ``EBUSY`` error code indicating some other window is trying
to access the clipboard.

View File

@ -18,9 +18,7 @@ from typing import Any, Callable, Dict, Iterable, List, Tuple
from docutils import nodes
from docutils.parsers.rst.roles import set_classes
from pygments.lexer import RegexLexer, bygroups # type: ignore
from pygments.token import ( # type: ignore
Comment, Keyword, Literal, Name, Number, String, Whitespace
)
from pygments.token import Comment, Keyword, Literal, Name, Number, String, Whitespace # type: ignore
from sphinx import addnodes, version_info
from sphinx.util.logging import getLogger
@ -35,8 +33,8 @@ from kitty.constants import str_version, website_url # noqa
# -- Project information -----------------------------------------------------
project = 'kitty'
copyright = time.strftime('%Y, Kovid Goyal')
author = 'Kovid Goyal'
copyright = time.strftime('%Y, Kovid Goyal, KittyPatch')
author = 'Kovid Goyal, KittyPatch'
building_man_pages = 'man' in sys.argv
# The short X.Y version
@ -67,6 +65,10 @@ extensions = [
# URL for OpenGraph tags
ogp_site_url = website_url()
# OGP needs a PNG image because of: https://github.com/wpilibsuite/sphinxext-opengraph/issues/96
ogp_social_cards = {
'image': '../logo/kitty.png'
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -98,14 +100,23 @@ exclude_patterns = [
rst_prolog = '''
.. |kitty| replace:: *kitty*
.. |version| replace:: VERSION
.. _tarball: https://github.com/kovidgoyal/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
.. _tarball: https://gitea.rexy712.xyz/KittyPatch/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
.. role:: italic
'''.replace('VERSION', str_version)
smartquotes_action = 'qe' # educate quotes and ellipses but not dashes
def go_version(go_mod_path: str) -> str: # {{{
with open(go_mod_path) as f:
for line in f:
if line.startswith('go '):
return line.strip().split()[1]
raise SystemExit(f'No Go version in {go_mod_path}')
# }}}
string_replacements = {
'_kitty_install_cmd': 'curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin',
'_build_go_version': go_version('../go.mod'),
}
@ -204,7 +215,7 @@ def commit_role(
f'GitHub commit id "{text}" not recognized.', line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
url = f'https://github.com/kovidgoyal/kitty/commit/{commit_id}'
url = f'https://gitea.rexy712.xyz/KittyPatch/kitty/commit/{commit_id}'
set_classes(options)
short_id = subprocess.check_output(
f'git rev-list --max-count=1 --abbrev-commit --skip=# {commit_id}'.split()).decode('utf-8').strip()
@ -215,15 +226,16 @@ def commit_role(
# CLI docs {{{
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
from kittens.ssh.main import copy_message, option_text
from kitty.cli import option_spec_as_rst
from kitty.launch import options_spec as launch_options_spec
from kittens.ssh.copy import option_text
from kittens.ssh.options.definition import copy_message
with open('generated/ssh-copy.rst', 'w') as f:
f.write(option_spec_as_rst(
appname='copy', ospec=option_text, heading_char='^',
usage='file-or-dir-to-copy ...', message=copy_message
))
del sys.modules['kittens.ssh.main']
from kitty.launch import options_spec as launch_options_spec
with open('generated/launch.rst', 'w') as f:
f.write(option_spec_as_rst(
appname='launch', ospec=launch_options_spec, heading_char='_',
@ -255,6 +267,7 @@ if you specify a program-to-run you can use the special placeholder
p('.. program::', 'kitty @', func.name)
p('\n\n' + as_rst(*cli_params_for(func)))
from kittens.runner import get_kitten_cli_docs
for kitten in all_kitten_names:
data = get_kitten_cli_docs(kitten)
if data:
@ -263,7 +276,8 @@ if you specify a program-to-run you can use the special placeholder
p('.. program::', 'kitty +kitten', kitten)
p('\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}>`_.')
scurl = f'https://github.com/kovidgoyal/kitty/tree/master/kittens/{kitten}'
p(f'\nThe source code for this kitten is `available on GitHub <{scurl}>`_.')
p('\nCommand Line Interface')
p('-' * 72)
p('\n\n' + option_spec_as_rst(
@ -274,10 +288,8 @@ if you specify a program-to-run you can use the special placeholder
def write_remote_control_protocol_docs() -> None: # {{{
from kitty.rc.base import (
RemoteCommand, all_command_names, command_for_name
)
field_pat = re.compile(r'\s*([a-zA-Z0-9_+/]+)\s*:\s*(.+)')
from kitty.rc.base import RemoteCommand, all_command_names, command_for_name
field_pat = re.compile(r'\s*([^:]+?)\s*:\s*(.+)')
def format_cmd(p: Callable[..., None], name: str, cmd: RemoteCommand) -> None:
p(name)
@ -502,7 +514,7 @@ def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
conf_name = re.sub(r'^kitten-', '', name) + '.conf'
with open(f'generated/conf/{conf_name}', 'w', encoding='utf-8') as f:
text = '\n'.join(definition.as_conf())
text = '\n'.join(definition.as_conf(commented=True))
print(text, file=f)
from kitty.options.definition import definition
@ -510,9 +522,9 @@ def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
from kittens.runner import get_kitten_conf_docs
for kitten in all_kitten_names:
definition = get_kitten_conf_docs(kitten)
if definition:
generate_default_config(definition, f'kitten-{kitten}')
defn = get_kitten_conf_docs(kitten)
if defn is not None:
generate_default_config(defn, f'kitten-{kitten}')
from kitty.actions import as_rst
with open('generated/actions.rst', 'w', encoding='utf-8') as f:

View File

@ -31,7 +31,9 @@ You can include secondary config files via the :code:`include` directive. If
you use a relative path for :code:`include`, it is resolved with respect to the
location of the current config file. Note that environment variables are
expanded, so :code:`${USER}.conf` becomes :file:`name.conf` if
:code:`USER=name`. Also, you can use :code:`globinclude` to include files
:code:`USER=name`. A special environment variable :envvar:`KITTY_OS` is available,
to detect the operating system. It is ``linux``, ``macos`` or ``bsd``.
Also, you can use :code:`globinclude` to include files
matching a shell glob pattern and :code:`envinclude` to include configuration
from environment variables. For example::
@ -66,6 +68,11 @@ Sample kitty.conf
pre-existing :file:`kitty.conf`, then that will be used instead, delete it to
see the sample file.
A default configuration file can also be generated by running::
kitty +runpy 'from kitty.config import *; print(commented_out_default_config())'
This will print the commented out default config file to :file:`STDOUT`.
All mappable actions
------------------------

View File

@ -50,7 +50,8 @@ 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).
limit to avoid Denial-of-Service attacks). The size of the payload must be no
longer than ``2048`` bytes, *before being encoded*.
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

View File

@ -27,96 +27,145 @@ turned off for specific symbols using :opt:`narrow_symbols`.
Using a color theme with a background color does not work well in vim?
-----------------------------------------------------------------------
First make sure you have not changed the :envvar:`TERM` environment variable, it
should be ``xterm-kitty``. vim uses *background color erase* even if the
terminfo file does not contain the ``bce`` capability. This is a bug in vim. You
can work around it by adding the following to your vimrc::
Sadly, vim has very poor out-of-the-box detection for modern terminal features.
Furthermore, it `recently broke detection even more <https://github.com/vim/vim/issues/11729>`__.
It kind of, but not really, supports terminfo, except it overrides it with its own hard-coded
values when it feels like it. Worst of all, it has no ability to detect modern
features not present in terminfo, at all, even security sensitive ones like
bracketed paste.
Thankfully, probably as a consequence of this lack of detection, vim allows users to
configure these low level details. So, to make vim work well with any modern
terminal, including kitty, add the following to your :file:`~/.vimrc`.
.. code-block:: vim
" Mouse support
set mouse=a
set ttymouse=sgr
set balloonevalterm
" Styled and colored underline support
let &t_AU = "\e[58:5:%dm"
let &t_8u = "\e[58:2:%lu:%lu:%lum"
let &t_Us = "\e[4:2m"
let &t_Cs = "\e[4:3m"
let &t_ds = "\e[4:4m"
let &t_Ds = "\e[4:5m"
let &t_Ce = "\e[4:0m"
" Strikethrough
let &t_Ts = "\e[9m"
let &t_Te = "\e[29m"
" Truecolor support
let &t_8f = "\e[38:2:%lu:%lu:%lum"
let &t_8b = "\e[48:2:%lu:%lu:%lum"
let &t_RF = "\e]10;?\e\\"
let &t_RB = "\e]11;?\e\\"
" Bracketed paste
let &t_BE = "\e[?2004h"
let &t_BD = "\e[?2004l"
let &t_PS = "\e[200~"
let &t_PE = "\e[201~"
" Cursor control
let &t_RC = "\e[?12$p"
let &t_SH = "\e[%d q"
let &t_RS = "\eP$q q\e\\"
let &t_SI = "\e[5 q"
let &t_SR = "\e[3 q"
let &t_EI = "\e[1 q"
let &t_VS = "\e[?12l"
" Focus tracking
let &t_fe = "\e[?1004h"
let &t_fd = "\e[?1004l"
execute "set <FocusGained>=\<Esc>[I"
execute "set <FocusLost>=\<Esc>[O"
" Window title
let &t_ST = "\e[22;2t"
let &t_RT = "\e[23;2t"
" vim hardcodes background color erase even if the terminfo file does
" not contain bce. This causes incorrect background rendering when
" using a color theme with a background color in terminals such as
" kitty that do not support background color erase.
let &t_ut=''
See :doc:`here <deccara>` for why |kitty| does not support background color
erase.
These settings must be placed **before** setting the ``colorscheme``. It is
also important that the value of the vim ``term`` variable is not changed
after these settings.
I get errors about the terminal being unknown or opening the terminal failing or functional keys like arrow keys don't work?
-------------------------------------------------------------------------------------------------------------------------------
I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?
-----------------------------------------------------------------------------------------------------------------------
This happens because the |kitty| terminfo files are not available on the server.
You can ssh in using the following command which will automatically copy the
terminfo files to the server::
These issues all have the same root cause: the kitty terminfo files not being
available. The most common way this happens is SSHing into a computer that does
not have the kitty terminfo files. The simplest fix for that is running::
kitty +kitten ssh myserver
It will automatically copy over the terminfo files and also magically enable
:doc:`shell integration </shell-integration>` on the remote machine.
This :doc:`ssh kitten <kittens/ssh>` takes all the same command line arguments
as :program:`ssh`, you can alias it to something small in your shell's rc files
to avoid having to type it each time::
alias s="kitty +kitten ssh"
If the ssh kitten fails, use the following one-liner instead (it is slower as it
needs to ssh into the server twice, but will work with most servers)::
If this does not work, see :ref:`manual_terminfo_copy` for alternative ways to
get the kitty terminfo files onto a remote computer.
infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin
The next most common reason for this is if you are running commands as root
using :program:`sudo` or :program:`su`. These programs often filter the
:envvar:`TERMINFO` environment variable which is what points to the kitty
terminfo files.
If you are behind a proxy (like Balabit) that prevents this, or :program:`tic`
comes with macOS that does not support reading from STDIN, you must redirect the
first command to a file, copy that to the server and run :program:`tic`
manually. If you connect to a server, embedded or Android system that doesn't
have :program:`tic`, copy over your local file terminfo to the other system as
:file:`~/.terminfo/x/xterm-kitty`.
First, make sure the :envvar:`TERM` is set to ``xterm-kitty`` in the sudo
environment. By default, it should be automatically copied over.
Really, the correct solution for this is to convince the OpenSSH maintainers to
have :program:`ssh` do this automatically, if possible, when connecting to a
server, so that all terminals work transparently.
If you are using a well maintained Linux distribution, it will have a
``kitty-terminfo`` package that you can simply install to make the kitty
terminfo files available system-wide. Then the problem will no longer occur.
If the server is running FreeBSD, or another system that relies on termcap
rather than terminfo, you will need to convert the terminfo file on your local
machine by running (on local machine with |kitty|)::
infocmp -CrT0 xterm-kitty
The output of this command is the termcap description, which should be appended
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
command to apply your change (on the server)::
cap_mkdb /usr/share/misc/termcap
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
-------------------------------------------------------------------------------------------------
Make sure the :envvar:`TERM` environment variable, is ``xterm-kitty``. And
either the :envvar:`TERMINFO` environment variable points to a directory
containing :file:`x/xterm-kitty` or that file is under :file:`~/.terminfo/x/`.
For macOS, you may also need to put that file under :file:`~/.terminfo/78/`::
mkdir -p ~/.terminfo/{78,x}
ln -snf ../x/xterm-kitty ~/.terminfo/78/xterm-kitty
tic -x -o ~/.terminfo "$KITTY_INSTALLATION_DIR/terminfo/kitty.terminfo"
Note that :program:`sudo` might remove :envvar:`TERMINFO`. Then setting it at
the shell prompt can be too late, because command line editing may not be
reinitialized. In that case you can either ask :program:`sudo` to set it or if
that is not supported, insert an :program:`env` command before starting the
shell, or, if not possible, after sudo start another shell providing the right
terminfo path::
sudo … TERMINFO=$HOME/.terminfo bash -i
sudo … env TERMINFO=$HOME/.terminfo bash -i
TERMINFO=/home/ORIGINALUSER/.terminfo exec bash -i
You can configure :program:`sudo` to preserve :envvar:`TERMINFO` by running
``sudo visudo`` and adding the following line::
Alternately, you can configure :program:`sudo` to preserve :envvar:`TERMINFO`
by running ``sudo visudo`` and adding the following line::
Defaults env_keep += "TERM TERMINFO"
If none of these are suitable for you, you can run sudo as follows::
sudo TERMINFO="$TERMINFO" -s -H
This will start a new root shell with the correct :envvar:`TERMINFO` value from your
current environment copied over.
If you have double width characters in your prompt, you may also need to
explicitly set a UTF-8 locale, like::
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
I cannot use the key combination X in program Y?
-------------------------------------------------------
First, run::
kitty +kitten show_key -m kitty
Press the key combination X. If the kitten reports the key press
that means kitty is correctly sending the key press to terminal programs.
You need to report the issue to the developer of the terminal program. Most
likely they have not added support for :doc:`/keyboard-protocol`.
If the kitten does not report it, it means that the key is bound to some action
in kitty. You can unbind it in :file:`kitty.conf` with:
.. code-block:: conf
map X no_op
Here X is the keys you press on the keyboard. So for example
:kbd:`ctrl+shift+1`.
How do I change the colors in a running kitty instance?
------------------------------------------------------------
@ -205,13 +254,15 @@ fonts to be freely resizable, so it does not support bitmapped fonts.
.. note::
If you are trying to use a font patched with `Nerd Fonts
<https://nerdfonts.com/>`__ symbols, don't do that as patching destroys
fonts. There is no need, simply install the standalone ``Symbols Nerd Font``
fonts. There is no need, simply install the standalone ``Symbols Nerd Font Mono``
(the file :file:`NerdFontsSymbolsOnly.zip` from the `Nerd Fonts releases page
<https://github.com/ryanoasis/nerd-fonts/releases>`__). kitty should pick up
symbols from it automatically, and you can tell it to do so explicitly in
case it doesn't with the :opt:`symbol_map` directive::
symbol_map U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0C8,U+E0CA,U+E0CC-U+E0D2,U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E62F,U+E700-U+E7C5,U+F000-U+F2E0,U+F300-U+F31C,U+F400-U+F4A9,U+F500-U+F8FF Symbols Nerd Font
# Nerd Fonts v2.3.3
symbol_map U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono
Those Unicode symbols beyond the ``E000-F8FF`` Unicode private use area are
not included.
@ -263,7 +314,7 @@ I do not like the kitty icon!
There are many alternate icons available, click on an icon to visit its
homepage:
.. image:: https://github.com/k0nserv/kitty-icon/raw/main/icon_512x512.png
.. image:: https://github.com/k0nserv/kitty-icon/raw/main/kitty.iconset/icon_256x256.png
:target: https://github.com/k0nserv/kitty-icon
:width: 256
@ -287,13 +338,44 @@ homepage:
:target: https://github.com/samholmes/whiskers
:width: 256
On macOS you can change the icon by following the steps:
.. 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
.. image:: https://github.com/eccentric-j/eccentric-icons/raw/main/icons/kitty-terminal/3d/kitty-preview.png
:target: https://github.com/eccentric-j/eccentric-icons
:width: 256
On macOS you can put :file:`kitty.app.icns` or :file:`kitty.app.png` in the
:ref:`kitty configuration directory <confloc>`, and this icon will be applied
automatically at startup. Unfortunately, Apple's Dock does not change its
cached icon so the custom icon will revert when kitty is quit. Run the
following to force the Dock to update its cached icons:
.. code-block:: sh
rm /var/folders/*/*/*/com.apple.dock.iconcache; killall Dock
If you prefer not to keep a custom icon in the kitty config folder, you can
also set it with the following command:
.. code-block:: sh
# Set kitty.icns as the icon for currently running kitty
kitty +runpy 'from kitty.fast_data_types import cocoa_set_app_icon; import sys; cocoa_set_app_icon(*sys.argv[1:]); print("OK")' kitty.icns
# Set the icon for app bundle specified by the path
kitty +runpy 'from kitty.fast_data_types import cocoa_set_app_icon; import sys; cocoa_set_app_icon(*sys.argv[1:]); print("OK")' /path/to/icon.png /Applications/kitty.app
You can also change the icon manually by following the steps:
#. Find :file:`kitty.app` in the Applications folder, select it and press :kbd:`⌘+I`
#. Drag :file:`kitty.icns` onto the application icon in the kitty info pane
#. Delete the icon cache and restart Dock::
#. Delete the icon cache and restart Dock:
$ rm /var/folders/*/*/*/com.apple.dock.iconcache; killall Dock
.. code-block:: sh
rm /var/folders/*/*/*/com.apple.dock.iconcache; killall Dock
How do I map key presses in kitty to different keys in the terminal program?

View File

@ -45,6 +45,12 @@ Glossary
hyperlink, based on the type of link and its URL. See also `Hyperlinks in terminal
emulators <https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`__.
kittens
Small, independent statically compiled command line programs that are designed to run
inside kitty windows and provide it with lots of powerful and flexible
features such as viewing images, connecting conveniently to remote
computers, transferring files, inputting unicode characters, etc.
.. _env_vars:
Environment variables
@ -212,3 +218,8 @@ Variables that kitty sets when running child programs
Set when enabling :ref:`shell_integration` with :program:`bash`, allowing
:program:`bash` to automatically load the integration script.
.. envvar:: KITTY_OS
Set when using the include directive in kitty.conf. Can take values:
``linux``, ``macos``, ``bsd``.

View File

@ -28,15 +28,14 @@ alpha-blending and text over graphics.
Some programs and libraries that use the kitty graphics protocol:
* `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
image previews, see this `PR <https://github.com/ranger/ranger/pull/1077>`_
* `ranger <https://github.com/ranger/ranger>`_ - a terminal file manager, with image previews
* :doc:`kitty-diff <kittens/diff>` - a side-by-side terminal diff program with support for images
* `tpix <https://github.com/jesvedberg/tpix>`_ - a statically compiled binary that can be used to display images and easily installed on remote servers without root access
* `mpv <https://github.com/mpv-player/mpv/commit/874e28f4a41a916bb567a882063dd2589e9234e1>`_ - A video player that can play videos in the terminal
* `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
information tool
* `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
* `ctx.graphics <https://ctx.graphics/>`_ - Library for drawing graphics
* `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
@ -44,6 +43,8 @@ Some programs and libraries that use the kitty graphics protocol:
* `chafa <https://github.com/hpjansson/chafa>`_ - a terminal image viewer
* `hologram.nvim <https://github.com/edluffy/hologram.nvim>`_ - view images inside nvim
* `term-image <https://github.com/AnonymouX47/term-image>`_ - A Python library, CLI and TUI to display and browse images in the terminal
* `glkitty <https://github.com/michaeljclark/glkitty>`_ - C library to draw OpenGL shaders in the terminal with a glgears demo
* `twitch-tui <https://github.com/Xithrius/twitch-tui>`_ - Twitch chat in the terminal
Other terminals that have implemented the graphics protocol:
@ -57,7 +58,8 @@ Getting the window size
In order to know what size of images to display and how to position them, the
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. The cell width is then simply the window size divided by the
number of rows. This can be done by using the ``TIOCGWINSZ`` ioctl. Some
code to demonstrate its use
.. tab:: C
@ -88,6 +90,31 @@ code to demonstrate its use
'number of rows: {} number of columns: {}'
'screen width: {} screen height: {}').format(*buf))
.. tab:: Go
.. code-block:: go
import "golang.org/x/sys/unix"
fd, err := unix.Open(fd, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666)
sz, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
fmt.Println("rows: %v columns: %v width: %v height %v", sz.Row, sz.Col, sz.Xpixel, sz.Ypixel)
.. tab:: Bash
.. code-block:: sh
#!/bin/bash
# This uses the kitten standalone binary from kitty to get the pixel sizes
# since we cant do IOCTLs directly. Fortunately, kitten is a static exe
# pre-built for every Unix like OS under the sun.
builtin read -r rows cols < <(command stty size)
IFS=x builtin read -r width height < <(command kitten icat --print-window-size); builtin unset IFS
builtin echo "number of rows: $rows number of columns: $cols screen width: $width screen height: $height"
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 that return correct values: ``kitty, xterm``
@ -101,15 +128,40 @@ kitty.
A minimal example
------------------
Some minimal python code to display PNG images in kitty, using the most basic
Some minimal code to display PNG images in kitty, using the most basic
features of the graphics protocol:
.. tab:: Bash
.. code-block:: sh
#!/bin/bash
transmit_png() {
data=$(base64 "$1")
data="${data//[[:space:]]}"
builtin local pos=0
builtin local chunk_size=4096
while [ $pos -lt ${#data} ]; do
builtin printf "\e_G"
[ $pos = "0" ] && printf "a=T,f=100,"
builtin local chunk="${data:$pos:$chunk_size}"
pos=$(($pos+$chunk_size))
[ $pos -lt ${#data} ] && builtin printf "m=1"
[ ${#chunk} -gt 0 ] && builtin printf ";%s" "${chunk}"
builtin printf "\e\\"
done
}
transmit_png "$1"
.. tab:: Python
.. code-block:: python
#!/usr/bin/python
import sys
from base64 import standard_b64encode
def serialize_gr_command(**cmd):
payload = cmd.pop('payload', None)
cmd = ','.join(f'{k}={v}' for k, v in cmd.items())
@ -122,7 +174,6 @@ features of the graphics protocol:
w(b'\033\\')
return b''.join(ans)
def write_chunked(**cmd):
data = standard_b64encode(cmd.pop('data'))
while data:
@ -133,15 +184,15 @@ features of the graphics protocol:
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:`send-png`, then you can use it to display any PNG
file in kitty as::
python png.py file.png
chmod +x send-png
./send-png file.png
The graphics escape code
@ -295,12 +346,13 @@ sequence of escape codes to the terminal emulator::
<ESC>_Gm=0;<encoded pixel data last chunk><ESC>\
Note that only the first escape code needs to have the full set of control
codes such as width, height, format etc. Subsequent chunks **must** have
only the ``m`` key. The client **must** finish sending all chunks for a single image
before sending any other graphics related escape codes. Note that the cursor
position used to display the image **must** be the position when the final chunk is
received. Finally, terminals must not display anything, until the entire sequence is
received and validated.
codes such as width, height, format, etc. Subsequent chunks **must** have only
the ``m`` and optionally ``q`` keys. When sending animation frame data, subsequent
chunks **must** also specify the ``a=f`` key. The client **must** finish sending
all chunks for a single image before sending any other graphics related escape
codes. Note that the cursor position used to display the image **must** be the
position when the final chunk is received. Finally, terminals must not display
anything, until the entire sequence is received and validated.
Querying support and available transmission mediums
@ -436,6 +488,132 @@ z-index and the same id, then the behavior is undefined.
Support for the C=1 cursor movement policy
.. _graphics_unicode_placeholders:
Unicode placeholders
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 0.28.0
Support for image display via Unicode placeholders
You can also use a special Unicode character ``U+10EEEE`` as a placeholder for
an image. This approach is less flexible, but it allows using images inside
any host application that supports Unicode and foreground colors (tmux, vim, weechat, etc.)
and has a way to pass escape codes through to the underlying terminal.
The central idea is that we use a single *Private Use* Unicode character as a
*placeholder* to indicate to the terminal that an image is supposed to be
displayed at that cell. Since this character is just normal text, Unicode aware
application will move it around as needed when they redraw their screens,
thereby automatically moving the displayed image as well, even though they know
nothing about the graphics protocol. So an image is first created using the
normal graphics protocol escape codes (albeit in quiet mode (``q=2``) so that there are
no responses from the terminal that could confuse the host application). Then,
the actual image is displayed by getting the host application to emit normal
text consisting of ``U+10EEEE`` and various diacritics (Unicode combining
characters) and colors.
To use it, first create an image as you would normally with the graphics
protocol with (``q=2``), but do not create a placement for it, that is, do not
display it. Then, create a *virtual image placement* by specifying ``U=1`` and
the desired number of lines and columns::
<ESC>_Ga=p,U=1,i=<image_id>,c=<columns>,r=<rows><ESC>\
The creation of the placement need not be a separate escape code, it can be
combined with ``a=T`` to both transmit and create the virtual placement with a
single code.
The image will eventually be fit to the specified rectangle, its aspect ratio
preserved. Finally, the image can be actually displayed by using the
placeholder character, encoding the image ID in its foreground color. The row
and column values are specified with diacritics listed in
:download:`rowcolumn-diacritics.txt <../rowcolumn-diacritics.txt>`. For
example, here is how you can print a ``2x2`` placeholder for image ID ``42``:
.. code-block:: sh
printf "\e[38;5;42m\U10EEEE\U0305\U0305\U10EEEE\U0305\U030D\e[39m\n"
printf "\e[38;5;42m\U10EEEE\U030D\U0305\U10EEEE\U030D\U030D\e[39m\n"
Here, ``U+305`` is the diacritic corresponding to the number ``0``
and ``U+30D`` corresponds to ``1``. So these two commands create the following
``2x2`` placeholder:
========== ==========
(0, 0) (1, 0)
(1, 0) (1, 1)
========== ==========
This will cause the image with ID ``42`` to be displayed in a ``2x2`` grid.
Ideally, you would print out as many cells as the number of rows and columns
specified when creating the virtual placement, but in case of a mismatch only
part of the image will be displayed.
By using only the foreground color for image ID you are limited to either 8-bit IDs in 256 color
mode or 24-bit IDs in true color mode. Since IDs are in a global namespace
there can easily be collisions. If you need more bits for the image
ID, you can specify the most significant byte via a third diacritic. For
example, this is the placeholder for the image ID ``33554474 = 42 + (2 << 24)``:
.. code-block:: sh
printf "\e[38;5;42m\U10EEEE\U0305\U0305\U030E\U10EEEE\U0305\U030D\U030E\n"
printf "\e[38;5;42m\U10EEEE\U030D\U0305\U030E\U10EEEE\U030D\U030D\U030E\n"
Here, ``U+30E`` is the diacritic corresponding to the number ``2``.
You can also specify a placement ID using the underline color (if it's omitted
or zero, the terminal may choose any virtual placement of the given image). The
background color is interpreted as the background color, visible if the image is
transparent. Other text attributes are reserved for future use.
Row, column and most significant byte diacritics may also be omitted, in which
case the placeholder cell will inherit the missing values from the placeholder
cell to the left, following the algorithm:
- If no diacritics are present, and the previous placeholder cell has the same
foreground and underline colors, then the row of the current cell will be the
row of the cell to the left, the column will be the column of the cell to the
left plus one, and the most significant image ID byte will be the most
significant image ID byte of the cell to the left.
- If only the row diacritic is present, and the previous placeholder cell has
the same row and the same foreground and underline colors, then the column of
the current cell will be the column of the cell to the left plus one, and the
most significant image ID byte will be the most significant image ID byte of
the cell to the left.
- If only the row and column diacritics are present, and the previous
placeholder cell has the same row, the same foreground and underline colors,
and its column is one less than the current column, then the most significant
image ID byte of the current cell will be the most significant image ID byte
of the cell to the left.
These rules are applied left-to-right, which allows specifying only row
diacritics of the first column, i.e. here is a 2 rows by 3 columns placeholder:
.. code-block:: sh
printf "\e[38;5;42m\U10EEEE\U0305\U10EEEE\U10EEEE\n"
printf "\e[38;5;42m\U10EEEE\U030D\U10EEEE\U10EEEE\n"
This will not work for horizontal scrolling and overlapping images since the two
given rules will fail to guess the missing information. In such cases, the
terminal may apply other heuristics (but it doesn't have to).
It is important to distinguish between virtual image placements and real images
displayed on top of Unicode placeholders. Virtual placements are invisible and only play
the role of prototypes for real images. Virtual placements can be deleted by a
deletion command only when the `d` key is equal to ``i``, ``I``, ``n`` or ``N``.
The key values ``a``, ``c``, ``p``, ``q``, ``x``, ``y``, ``z`` and their capital
variants never affect virtual placements because they do not have a physical
location on the screen.
Real images displayed on top of Unicode placeholders are not considered
placements from the protocol perspective. They cannot be manipulated using
graphics commands, instead they should be moved, deleted, or modified by
manipulating the underlying Unicode placeholder as normal text.
Deleting images
---------------------
@ -754,6 +932,8 @@ Key Value Default Description
``r`` Positive integer ``0`` The number of rows to display the image over
``C`` Positive integer ``0`` Cursor movement policy. ``0`` is the default, to move the cursor to after the image.
``1`` is to not move the cursor at all when placing the image.
``U`` Positive integer ``0`` Set to ``1`` to create a virtual placement for a Unicode placeholder.
``1`` is to not move the cursor at all when placing the image.
``z`` 32-bit integer ``0`` The *z-index* vertical stacking order of the image
**Keys for animation frame loading**

View File

@ -46,7 +46,7 @@ detect_os() {
'Linux')
OS="linux"
case "$(command uname -m)" in
x86_64) arch="x86_64";;
amd64|x86_64) arch="x86_64";;
aarch64*) arch="arm64";;
armv8*) arch="arm64";;
i386) arch="i686";;
@ -114,36 +114,38 @@ get_download_url() {
esac
}
linux_install() {
if [ "$installer_is_file" = "y" ]; then
command tar -C "$dest" "-xJof" "$installer"
else
download_installer() {
tdir=$(command mktemp -d "/tmp/kitty-install-XXXXXXXXXXXX")
[ "$installer_is_file" != "y" ] && {
printf '%s\n\n' "Downloading from: $url"
fetch "$url" | command tar -C "$dest" "-xJof" "-"
if [ "$OS" = "macos" ]; then
installer="$tdir/kitty.dmg"
else
installer="$tdir/kitty.txz"
fi
fetch "$url" > "$installer" || die "Failed to download: $url"
installer_is_file="y"
}
}
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"
command mv "$tdir/mp" "$dest" || die "Failed to move kitty.app to $dest"
}
macos_install() {
tdir=$(command mktemp -d "/tmp/kitty-install-XXXXXXXXXXXX")
[ "$installer_is_file" != "y" ] && {
installer="$tdir/kitty.dmg"
printf '%s\n\n' "Downloading from: $url"
fetch "$url" > "$installer" || die "Failed to download: $url"
}
command mkdir "$tdir/mp"
command hdiutil attach "$installer" "-mountpoint" "$tdir/mp" || die "Failed to mount kitty.dmg"
command ditto -v "$tdir/mp/kitty.app" "$dest"
rc="$?"
command hdiutil detach "$tdir/mp"
command rm -rf "$tdir"
tdir=''
[ "$rc" != "0" ] && die "Failed to copy kitty.app from mounted dmg"
}
prepare_install_dest() {
printf "%s\n" "Installing to $dest"
command rm -rf "$dest"
command mkdir -p "$dest" || die "Failed to create the directory: $dest"
command ditto -v "$tdir/mp/kitty.app" "$dest"
rc="$?"
command hdiutil detach "$tdir/mp"
[ "$rc" != "0" ] && die "Failed to copy kitty.app from mounted dmg"
}
exec_kitty() {
@ -160,12 +162,13 @@ main() {
parse_args "$@"
detect_network_tool
get_download_url
prepare_install_dest
download_installer
if [ "$OS" = "macos" ]; then
macos_install
else
linux_install
fi
cleanup
[ "$launch" = "y" ] && exec_kitty
exit 0
}

View File

@ -80,6 +80,17 @@ base application that uses kitty's graphics protocol for images.
A text mode WWW browser that supports kitty's graphics protocol to display
images.
`awrit <https://github.com/chase/awrit>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A full Chromium based web browser running in the terminal using kitty's
graphics protocol.
.. _tool_mpv:
`mpv <https://github.com/mpv-player/mpv/commit/874e28f4a41a916bb567a882063dd2589e9234e1>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A video player that can play videos in the terminal.
.. _tool_timg:
`timg <https://github.com/hzeller/timg>`_
@ -214,7 +225,8 @@ Allows easily running tests in a terminal window
`hologram.nvim <https://github.com/edluffy/hologram.nvim>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Terminal image viewer for Neovim
Terminal image viewer for Neovim. For a bit of fun, you can even have `cats
running around inside nvim <https://github.com/giusgad/pets.nvim>`__.
Scrollback manipulation

View File

@ -40,9 +40,13 @@ In addition to kitty, this protocol is also implemented in:
<https://github.com/dankamongmen/notcurses/issues/2131>`__
* The `crossterm library
<https://github.com/crossterm-rs/crossterm/pull/688>`__
* The `neovim text editor <https://github.com/neovim/neovim/pull/18181>`__
* 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>`__
* The `kakoune text editor <https://github.com/mawww/kakoune/issues/4103>`__
* The `dte text editor <https://gitlab.com/craigbarnes/dte/-/issues/138>`__
* The `Helix text editor <https://github.com/helix-editor/helix/pull/4939>`__
* The `far2l file manager <https://github.com/elfmz/far2l/commit/e1f2ee0ef2b8332e5fa3ad7f2e4afefe7c96fc3b>`__
.. versionadded:: 0.20.0
@ -60,14 +64,14 @@ without too many changes, do the following:
that are easy to parse unambiguously.
#. Emit the escape sequence ``CSI < u`` at application exit if using the main
screen or just before leaving alternate screen mode if using the alternate screen,
to restore the previously used keyboard mode.
to restore whatever the keyboard mode was before step 1.
Key events will all be delivered to your application either as plain UTF-8
text, or using the following escape codes, for those keys that do not produce
text (``CSI`` is the bytes ``0x1b 0x5b``)::
CSI number ; modifiers [u~]
CSI 1; modifiers [ABCDEFHPQRS]
CSI 1; modifiers [ABCDEFHPQS]
0x0d - for the Enter key
0x7f or 0x08 - for Backspace
0x09 - for Tab
@ -82,7 +86,7 @@ The second form is used for a few functional keys, such as the :kbd:`Home`,
:kbd:`End`, :kbd:`Arrow` keys and :kbd:`F1` ... :kbd:`F4`, they are enumerated in
the :ref:`functional` table below. Note that if no modifiers are present the
parameters are omitted entirely giving an escape code of the form ``CSI
[ABCDEFHPQRS]``.
[ABCDEFHPQS]``.
If you want support for more advanced features such as repeat and release
events, alternate keys for shortcut matching et cetera, these can be turned on
@ -313,7 +317,7 @@ With this flag turned on, all key events that do not generate text are
represented in one of the following two forms::
CSI number; modifier u
CSI 1; modifier [~ABCDEFHPQRS]
CSI 1; modifier [~ABCDEFHPQS]
This makes it very easy to parse key events in an application. In particular,
:kbd:`ctrl+c` will no longer generate the ``SIGINT`` signal, but instead be
@ -404,7 +408,7 @@ Legacy functional keys
These keys are encoded using three schemes::
CSI number ; modifier ~
CSI 1 ; modifier {ABCDEFHPQRS}
CSI 1 ; modifier {ABCDEFHPQS}
SS3 {ABCDEFHPQRS}
In the above, if there are no modifiers, the modifier parameter is omitted.
@ -532,7 +536,7 @@ compatibility reasons.
"NUM_LOCK", "``57360 u``", "PRINT_SCREEN", "``57361 u``"
"PAUSE", "``57362 u``", "MENU", "``57363 u``"
"F1", "``1 P or 11 ~``", "F2", "``1 Q or 12 ~``"
"F3", "``1 R or 13 ~``", "F4", "``1 S or 14 ~``"
"F3", "``13 ~``", "F4", "``1 S or 14 ~``"
"F5", "``15 ~``", "F6", "``17 ~``"
"F7", "``18 ~``", "F8", "``19 ~``"
"F9", "``20 ~``", "F10", "``21 ~``"
@ -581,9 +585,15 @@ compatibility reasons.
.. end functional key table
.. }}}
Note that the escape codes above of the form ``CSI 1 letter`` will omit the
.. note::
The escape codes above of the form ``CSI 1 letter`` will omit the
``1`` if there are no modifiers, since ``1`` is the default value.
.. note::
The original version of this specification allowed F3 to be encoded as both
CSI R and CSI ~. However, CSI R conflicts with the Cursor Position Report,
so it was removed.
.. _ctrl_mapping:
Legacy :kbd:`ctrl` mapping of ASCII keys
@ -675,3 +685,31 @@ specification.
* Handwaves that :kbd:`ctrl` *tends to* mask with ``0x1f``. In actual fact it
does this only for some keys. The action of :kbd:`ctrl` is not specified and
varies between terminals, historically because of different keyboard layouts.
Why xterm's modifyOtherKeys should not be used
---------------------------------------------------
* Does not support release events
* Does not fix the issue of :kbd:`Esc` key presses not being distinguishable from
escape codes.
* Does not fix the issue of some keypresses generating identical bytes and thus
being indistinguishable
* There is no robust way to query it or manage its state from a program running
in the terminal.
* No support for shifted keys.
* No support for alternate keyboard layouts.
* No support for modifiers beyond the basic four.
* No support for lock keys like Num lock and Caps lock.
* Is completely unspecified. The most discussion of it available anywhere is
`here <https://invisible-island.net/xterm/modified-keys.html>`__
And it contains no specification of what numbers to assign to what function
keys beyond running a Perl script on an X11 system!!

View File

@ -11,14 +11,46 @@ from the shell. It even works over SSH. Using it is as simple as::
echo hooray | kitty +kitten clipboard
All text received on :file:`stdin` is copied to the clipboard.
All text received on :file:`STDIN` is copied to the clipboard.
To get text from the clipboard you have to enable reading of the clipboard
in :opt:`clipboard_control` in :file:`kitty.conf`. Once you do that, you can
use::
To get text from the clipboard::
kitty +kitten clipboard --get-clipboard
The text will be written to :file:`STDOUT`. Note that by default kitty asks for
permission when a program attempts to read the clipboard. This can be
controlled via :opt:`clipboard_control`.
.. versionadded:: 0.27.0
Support for copying arbitrary data types
The clipboard kitten can be used to send/receive
more than just plain text from the system clipboard. You can transfer arbitrary
data types. Best illustrated with some examples::
# Copy an image to the clipboard:
kitty +kitten clipboard picture.png
# Copy an image and some text to the clipboard:
kitty +kitten clipboard picture.jpg text.txt
# Copy text from STDIN and an image to the clipboard:
echo hello | kitty +kitten clipboard picture.png /dev/stdin
# Copy any raster image available on the clipboard to a PNG file:
kitty +kitten clipboard -g picture.png
# Copy an image to a file and text to STDOUT:
kitty +kitten clipboard -g picture.png /dev/stdout
# List the formats available on the system clipboard
kitty +kitten clipboard -g -m . /dev/stdout
Normally, the kitten guesses MIME types based on the file names. To control the
MIME types precisely, use the :option:`--mime <kitty +kitten clipboard --mime>` option.
This kitten uses a new protocol developed by kitty to function, for details,
see :doc:`/clipboard`.
.. program:: kitty +kitten clipboard

View File

@ -31,11 +31,7 @@ Major Features
Installation
---------------
Simply :ref:`install kitty <quickstart>`. You also need to have either the `git
<https://git-scm.com/>`__ program or the :program:`diff` program installed.
Additionally, for syntax highlighting to work, `pygments
<https://pygments.org/>`__ must be installed (note that pygments is included in
the official kitty binary builds).
Simply :ref:`install kitty <quickstart>`.
Usage
@ -65,10 +61,10 @@ directory contents.
Keyboard controls
----------------------
========================= ===========================
=========================== ===========================
Action Shortcut
========================= ===========================
Quit :kbd:`Q`, :kbd:`Ctrl+C`, :kbd:`Esc`
=========================== ===========================
Quit :kbd:`Q`, :kbd:`Esc`
Scroll line up :kbd:`K`, :kbd:`Up`
Scroll line down :kbd:`J`, :kbd:`Down`
Scroll page up :kbd:`PgUp`
@ -88,7 +84,9 @@ Search backwards :kbd:`?`
Clear search :kbd:`Esc`
Scroll to next match :kbd:`>`, :kbd:`.`
Scroll to previous match :kbd:`<`, :kbd:`,`
========================= ===========================
Copy selection to clipboard :kbd:`y`
Copy selection or exit :kbd:`Ctrl+C`
=========================== ===========================
Integrating with git
@ -124,7 +122,7 @@ The diff kitten makes use of various features that are :doc:`kitty only
</graphics-protocol>`, the :doc:`extended keyboard protocol
</keyboard-protocol>`, etc. It also leverages terminal program 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).
(the entire implementation is under 3000 lines of code).
And fundamentally, it's kitty only because I wrote it for myself, and I am
highly unlikely to use any other terminals :)

View File

@ -72,7 +72,8 @@ the :ref:`kitty config directory <confloc>` with the following contents:
start, end = m.span()
mark_text = text[start:end].replace('\n', '').replace('\0', '')
# The empty dictionary below will be available as groupdicts
# in handle_result() and can contain arbitrary data.
# in handle_result() and can contain string keys and arbitrary JSON
# serializable values.
yield Mark(idx, start, end, mark_text, {})

View File

@ -17,12 +17,12 @@ following contents:
# by the hyperlink_grep kitten and nothing else so far.
protocol file
fragment_matches [0-9]+
action launch --type=overlay vim +${FRAGMENT} ${FILE_PATH}
action launch --type=overlay --cwd=current vim +${FRAGMENT} ${FILE_PATH}
# Open text files without fragments in the editor
protocol file
mime text/*
action launch --type=overlay ${EDITOR} ${FILE_PATH}
action launch --type=overlay --cwd=current ${EDITOR} ${FILE_PATH}
Now, run a search with::
@ -43,46 +43,18 @@ You can now run searches with::
hg some-search-term
If you want to enable completion, for the kitten, you can delegate completion
to :program:`rg`. How to do that varies based on the shell:
.. tab:: zsh
Instead of using an alias, create a simple wrapper script named
:program:`hg` somewhere in your :envvar:`PATH`:
.. code-block:: sh
#!/bin/sh
exec kitty +kitten hyperlinked_grep "$@"
Then, add the following to :file:`.zshrc`::
compdef _rg hg
.. tab:: fish
You can combine both the aliasing/wrapping and pointing fish to ripgrep's
autocompletion with a fish wrapper function in your :file:`config.fish`
or :file:`~/.config/fish/functions/hg.fish`:
.. code-block:: fish
function hg --wraps rg; kitty +kitten hyperlinked_grep $argv; end
To learn more about kitty's powerful framework for customizing URL click
actions, see :doc:`here </open_actions>`.
By default, this kitten adds hyperlinks for several parts of ripgrep output:
the per-file header, match context lines, and match lines. You can control
which items are linked with a :command:`--kitten hyperlink` flag. For example,
:command:`--kitten hyperlink=matching_lines` will only add hyperlinks to the
match lines. :command:`--kitten hyperlink=file_headers,context_lines` will link
file headers and context lines but not match lines. :command:`--kitten
which items are linked with a :code:`--kitten hyperlink` flag. For example,
:code:`--kitten hyperlink=matching_lines` will only add hyperlinks to the
match lines. :code:`--kitten hyperlink=file_headers,context_lines` will link
file headers and context lines but not match lines. :code:`--kitten
hyperlink=none` will cause the command line to be passed to directly to
:command:`rg` so no hyperlinking will be performed. :command:`--kitten
hyperlink` may be specified multiple times.
:command:`rg` so no hyperlinking will be performed. :code:`--kitten hyperlink`
may be specified multiple times.
Hopefully, someday this functionality will make it into some `upstream grep
<https://github.com/BurntSushi/ripgrep/issues/665>`__ program directly removing
@ -93,3 +65,9 @@ the need for this kitten.
While you can pass any of ripgrep's comand line options to the kitten and
they will be forwarded to :program:`rg`, do not use options that change the
output formatting as the kitten works by parsing the output from ripgrep.
The unsupported options are: :code:`--context-separator`,
:code:`--field-context-separator`, :code:`--field-match-separator`,
:code:`--json`, :code:`-I --no-filename`, :code:`-0 --null`,
:code:`--null-data`, :code:`--path-separator`. If you specify options via
configuration file, then any changes to the default output format will not be
supported, not just the ones listed.

View File

@ -7,6 +7,7 @@ The ``icat`` kitten can be used to display arbitrary images in the |kitty|
terminal. Using it is as simple as::
kitty +kitten icat image.jpeg
kitten icat image.jpeg
It supports all image types supported by `ImageMagick
<https://www.imagemagick.org>`__. It even works over SSH. For details, see the
@ -20,8 +21,9 @@ Then you can simply use ``icat image.png`` to view images.
.. note::
`ImageMagick <https://www.imagemagick.org>`__ must be installed for icat
kitten to work.
`ImageMagick <https://www.imagemagick.org>`__ must be installed for the
full range of image types. Without it only PNG/JPG/GIF/BMP/TIFF/WEBP are
supported.
.. note::
@ -35,16 +37,15 @@ Then you can simply use ``icat image.png`` to view images.
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`,
:option:`--detect-support`, :option:`--silent` and
:option:`--print-window-size`.
:option:`--detect-support` and :option:`--print-window-size`.
If you are trying to integrate icat into a complex program like a file manager
or editor, there are a few things to keep in mind. icat works by communicating
over the TTY device, it both writes to and reads from the TTY. So it is
imperative that while it is running the host program does not do any TTY I/O.
Any key presses or other input from the user on the TTY device will be
discarded. At a minimum, you should use the :option:`--silent` and
:option:`--transfer-mode` command line arguments. To be really robust you should
discarded. At a minimum, you should use the :option:`--transfer-mode`
command line arguments. To be really robust you should
consider writing proper support for the :doc:`kitty graphics protocol
</graphics-protocol>` in the program instead. Nowadays there are many libraries
that have support for it.

View File

@ -162,3 +162,42 @@ The copy command
--------------------
.. include:: /generated/ssh-copy.rst
.. _manual_terminfo_copy:
Copying terminfo files manually
-------------------------------------
Sometimes, the ssh kitten can fail, or maybe you dont like to use it. In such
cases, the terminfo files can be copied over manually to a server with the
following one liner::
infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin
If you are behind a proxy (like Balabit) that prevents this, or you are SSHing
into macOS where the :program:`tic` does not support reading from :file:`STDIN`,
you must redirect the first command to a file, copy that to the server and run :program:`tic`
manually. If you connect to a server, embedded, or Android system that doesn't
have :program:`tic`, copy over your local file terminfo to the other system as
:file:`~/.terminfo/x/xterm-kitty`.
If the server is running a relatively modern Linux distribution and you have
root access to it, you could simply install the ``kitty-terminfo`` package on
the server to make the terminfo files available.
Really, the correct solution for this is to convince the OpenSSH maintainers to
have :program:`ssh` do this automatically, if possible, when connecting to a
server, so that all terminals work transparently.
If the server is running FreeBSD, or another system that relies on termcap
rather than terminfo, you will need to convert the terminfo file on your local
machine by running (on local machine with |kitty|)::
infocmp -CrT0 xterm-kitty
The output of this command is the termcap description, which should be appended
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
command to apply your change (on the server)::
cap_mkdb /usr/share/misc/termcap

View File

@ -44,7 +44,8 @@ You can also create your own themes as :file:`.conf` files. Put them in the
usually, :file:`~/.config/kitty/themes`. The kitten will automatically add them
to the list of themes. You can use this to modify the builtin themes, by giving
the conf file the name :file:`Some theme name.conf` to override the builtin
theme of that name. Note that after doing so you have to run the kitten and
theme of that name. Here, ``Some theme name`` is the actual builtin theme name, not
its file name. Note that after doing so you have to run the kitten and
choose that theme once for your changes to be applied.

View File

@ -1,295 +0,0 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
import argparse
import base64
import hashlib
import json
import os
import sys
import termios
import time
import tty
from contextlib import contextmanager
from ctypes import (
CDLL, POINTER, byref, c_char_p, c_int, c_size_t, c_void_p,
create_string_buffer
)
from ctypes.util import find_library
_plat = sys.platform.lower()
is_macos: bool = 'darwin' in _plat
def build_crypto_tools(): # {{{
class EVP_PKEY_POINTER(c_void_p):
algorithm = 0
def __del__(self):
EVP_PKEY_free(self)
@property
def public(self):
sz = c_size_t(0)
EVP_PKEY_get_raw_public_key(self, None, byref(sz))
buf = create_string_buffer(sz.value)
EVP_PKEY_get_raw_public_key(self, buf, byref(sz))
return buf.raw
def derive_secret(self, pubkey):
pubkey = EVP_PKEY_new_raw_public_key(self.algorithm, None, pubkey, len(pubkey))
ctx = EVP_PKEY_CTX_new(self, None)
EVP_PKEY_derive_init(ctx)
EVP_PKEY_derive_set_peer(ctx, pubkey)
sz = c_size_t(0)
EVP_PKEY_derive(ctx, None, byref(sz))
buf = create_string_buffer(sz.value)
EVP_PKEY_derive(ctx, buf, byref(sz))
return hashlib.sha256(buf.raw).digest()
class EVP_PKEY_CTX_POINTER(c_void_p):
def __del__(self):
EVP_PKEY_CTX_free(self)
class EVP_CIPHER_CTX_POINTER(c_void_p):
def __del__(self):
EVP_CIPHER_CTX_free(self)
class EVP_CIPHER_POINTER(c_void_p):
pass
cl = find_library('crypto')
if not cl:
raise SystemExit('Failed to find libcrypto on your system, make sure OpenSSL is installed')
crypto = CDLL(cl)
libc = CDLL(None)
def create_crypto_func(name, *argtypes, restype=c_int, int_return_ok=lambda x: x == 1):
impl = getattr(crypto, name)
impl.restype = restype
impl.argtypes = argtypes
def func(*a):
res = impl(*a)
if restype is c_int:
if not int_return_ok(res):
print('Call to', name, 'failed with return code:', res, file=sys.stderr)
abort_on_openssl_error()
elif restype is not None and issubclass(restype, c_void_p):
if res.value is None:
print('Call to', name, 'failed with NULL return', file=sys.stderr)
abort_on_openssl_error()
return res
return func
OBJ_txt2nid = create_crypto_func('OBJ_txt2nid', c_char_p, int_return_ok=bool)
EVP_PKEY_CTX_new_id = create_crypto_func('EVP_PKEY_CTX_new_id', c_int, c_void_p, restype=EVP_PKEY_CTX_POINTER)
EVP_PKEY_CTX_new = create_crypto_func('EVP_PKEY_CTX_new', EVP_PKEY_POINTER, c_void_p, restype=EVP_PKEY_CTX_POINTER)
EVP_PKEY_keygen_init = create_crypto_func('EVP_PKEY_keygen_init', EVP_PKEY_CTX_POINTER)
EVP_PKEY_keygen = create_crypto_func('EVP_PKEY_keygen', EVP_PKEY_CTX_POINTER, POINTER(EVP_PKEY_POINTER))
ERR_print_errors_fp = create_crypto_func('ERR_print_errors_fp', c_void_p, restype=None)
EVP_PKEY_free = create_crypto_func('EVP_PKEY_free', EVP_PKEY_POINTER, restype=None)
EVP_PKEY_CTX_free = create_crypto_func('EVP_PKEY_CTX_free', EVP_PKEY_CTX_POINTER, restype=None)
EVP_PKEY_get_raw_public_key = create_crypto_func('EVP_PKEY_get_raw_public_key', EVP_PKEY_POINTER, c_char_p, POINTER(c_size_t))
EVP_PKEY_new_raw_public_key = create_crypto_func('EVP_PKEY_new_raw_public_key', c_int, c_void_p, c_char_p, c_size_t, restype=EVP_PKEY_POINTER)
EVP_PKEY_derive_init = create_crypto_func('EVP_PKEY_derive_init', EVP_PKEY_CTX_POINTER)
EVP_PKEY_derive_set_peer = create_crypto_func('EVP_PKEY_derive_set_peer', EVP_PKEY_CTX_POINTER, EVP_PKEY_POINTER)
EVP_PKEY_derive = create_crypto_func('EVP_PKEY_derive', EVP_PKEY_CTX_POINTER, c_char_p, POINTER(c_size_t))
EVP_CIPHER_CTX_free = create_crypto_func('EVP_CIPHER_CTX_free', EVP_CIPHER_CTX_POINTER, restype=None)
EVP_get_cipherbyname = create_crypto_func('EVP_get_cipherbyname', c_char_p, restype=EVP_CIPHER_POINTER)
EVP_CIPHER_key_length = create_crypto_func('EVP_CIPHER_key_length', EVP_CIPHER_POINTER, int_return_ok=bool)
EVP_CIPHER_iv_length = create_crypto_func('EVP_CIPHER_iv_length', EVP_CIPHER_POINTER, int_return_ok=bool)
EVP_CIPHER_CTX_block_size = create_crypto_func('EVP_CIPHER_CTX_block_size', EVP_CIPHER_CTX_POINTER, int_return_ok=bool)
EVP_CIPHER_CTX_new = create_crypto_func('EVP_CIPHER_CTX_new', restype=EVP_CIPHER_CTX_POINTER)
EVP_EncryptInit_ex = create_crypto_func('EVP_EncryptInit_ex', EVP_CIPHER_CTX_POINTER, EVP_CIPHER_POINTER, c_void_p, c_char_p, c_char_p)
EVP_EncryptUpdate = create_crypto_func('EVP_EncryptUpdate', EVP_CIPHER_CTX_POINTER, c_char_p, POINTER(c_int), c_char_p, c_int)
EVP_EncryptFinal_ex = create_crypto_func('EVP_EncryptFinal_ex', EVP_CIPHER_CTX_POINTER, c_char_p, POINTER(c_int))
EVP_CIPHER_CTX_ctrl = create_crypto_func('EVP_CIPHER_CTX_ctrl', EVP_CIPHER_CTX_POINTER, c_int, c_int, c_char_p)
try:
EVP_CIPHER_CTX_tag_length = create_crypto_func('EVP_CIPHER_CTX_tag_length', EVP_CIPHER_CTX_POINTER, int_return_ok=bool)
except AttributeError: # need openssl >= 3
def EVP_CIPHER_CTX_tag_length(cipher):
return 16
EVP_CTRL_AEAD_GET_TAG, EVP_CTRL_AEAD_SET_TAG = 0x10, 0x11 # these are defines in the header dont know how to get them programmatically
EVP_CTRL_AEAD_SET_TAG
def abort_on_openssl_error():
stderr = c_void_p.in_dll(libc, 'stderr')
ERR_print_errors_fp(stderr)
raise SystemExit(1)
def elliptic_curve_keypair(algorithm='X25519'):
nid = OBJ_txt2nid(algorithm.encode())
pctx = EVP_PKEY_CTX_new_id(nid, None)
EVP_PKEY_keygen_init(pctx)
key = EVP_PKEY_POINTER()
EVP_PKEY_keygen(pctx, byref(key))
key.algorithm = nid
return key
def encrypt(plaintext, symmetric_key, algorithm='aes-256-gcm'):
cipher = EVP_get_cipherbyname(algorithm.encode())
if len(symmetric_key) != EVP_CIPHER_key_length(cipher):
raise KeyError(f'The symmetric key has length {len(symmetric_key)} != {EVP_CIPHER_key_length(cipher)} needed for {algorithm}')
ctx = EVP_CIPHER_CTX_new()
iv = os.urandom(EVP_CIPHER_iv_length(cipher))
EVP_EncryptInit_ex(ctx, cipher, None, symmetric_key, iv)
bs = EVP_CIPHER_CTX_block_size(ctx)
ciphertext = create_string_buffer(len(plaintext) + 2 * bs)
outlen = c_int(len(ciphertext))
EVP_EncryptUpdate(ctx, ciphertext, byref(outlen), plaintext, len(plaintext))
ans = ciphertext[:outlen.value]
outlen = c_int(len(ciphertext))
EVP_EncryptFinal_ex(ctx, ciphertext, byref(outlen))
if outlen.value:
ans += ciphertext[:outlen.value]
tag = create_string_buffer(EVP_CIPHER_CTX_tag_length(cipher))
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, len(tag), tag)
return iv, ans, tag.raw
return elliptic_curve_keypair, encrypt
# }}}
# utils {{{
def encrypt_cmd(cmd, password, pubkey=None):
elliptic_curve_keypair, encrypt = build_crypto_tools()
if pubkey is None:
pubkey = os.environ['KITTY_PUBLIC_KEY']
v, d = pubkey.split(':', 1)
if v != '1':
raise SystemExit(f'Unsupported encryption protocol: {v}')
pubkey = base64.b85decode(d)
k = elliptic_curve_keypair()
sk = k.derive_secret(pubkey)
cmd['timestamp'] = time.time_ns()
cmd['password'] = password
data = json.dumps(cmd).encode()
iv, encrypted, tag = encrypt(data, sk)
def e(x):
return base64.b85encode(x).decode('ascii')
return {
'encrypted': e(encrypted), 'iv': e(iv), 'tag': e(tag), 'pubkey': e(k.public), 'version': cmd['version']
}
@contextmanager
def raw_mode(fd):
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
yield
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
def config_dir():
if 'KITTY_CONFIG_DIRECTORY' in os.environ:
return os.path.abspath(os.path.expanduser(os.environ['KITTY_CONFIG_DIRECTORY']))
locations = []
if 'XDG_CONFIG_HOME' in os.environ:
locations.append(os.path.abspath(os.path.expanduser(os.environ['XDG_CONFIG_HOME'])))
locations.append(os.path.expanduser('~/.config'))
if is_macos:
locations.append(os.path.expanduser('~/Library/Preferences'))
for loc in filter(None, os.environ.get('XDG_CONFIG_DIRS', '').split(os.pathsep)):
locations.append(os.path.abspath(os.path.expanduser(loc)))
for loc in locations:
if loc:
q = os.path.join(loc, 'kitty')
if os.access(q, os.W_OK) and os.path.exists(os.path.join(q, 'kitty.conf')):
return q
for loc in locations:
if loc:
q = os.path.join(loc, 'kitty')
if os.path.isdir(q) and os.access(q, os.W_OK):
return q
return ''
def resolve_custom_file(path):
path = os.path.expanduser(path)
path = os.path.expandvars(path)
if not os.path.isabs(path):
cdir = config_dir()
if cdir:
path = os.path.join(cdir, path)
return path
def get_password(opts):
if opts.use_password == 'never':
return ''
ans = ''
if opts.password:
ans = opts.password
if not ans and opts.password_file:
if opts.password_file == '-':
if sys.stdin.isatty():
from getpass import getpass
ans = getpass()
else:
ans = sys.stdin.read().rstrip()
try:
tty_fd = os.open(os.ctermid(), os.O_RDONLY | os.O_CLOEXEC)
except OSError:
pass
else:
with open(tty_fd, closefd=True):
os.dup2(tty_fd, sys.stdin.fileno())
else:
try:
with open(resolve_custom_file(opts.password_file)) as f:
ans = f.read().rstrip()
except OSError:
pass
if not ans and opts.password_env:
ans = os.environ.get(opts.password_env, '')
if not ans and opts.use_password == 'always':
raise SystemExit('No password was found')
if ans and len(ans) > 1024:
raise SystemExit('Specified password is too long')
return ans
# }}}
arg_parser = argparse.ArgumentParser(prog='kitty@', description='Control kitty remotely.')
arg_parser.add_argument('--password', default='', help='''\
A password to use when contacting kitty. This will cause kitty to ask the user
for permission to perform the specified action, unless the password has been
accepted before or is pre-configured in kitty.conf''')
arg_parser.add_argument('--password-file', default='rc-pass', help='''\
A file from which to read the password. Trailing whitespace is ignored. Relative
paths are resolved from the kitty configuration directory. Use - to read from STDIN.
Used if no --password is supplied. Defaults to checking for the
rc-pass file in the kitty configuration directory.''')
arg_parser.add_argument('--password-env', default='KITTY_RC_PASSWORD', help='''\
The name of an environment variable to read the password from.
Used if no --password-file is supplied. Defaults to checking the KITTY_RC_PASSWORD.''')
arg_parser.add_argument('--use-password', default='if-available', choices=('if-available', 'always', 'never'), help='''\
If no password is available, kitty will usually just send the remote control command
without a password. This option can be used to force it to always or never use
the supplied password.''')
args = arg_parser.parse_args()
def populate_cmd(cmd):
raise NotImplementedError()
password = get_password(args)
cmd = {'version': [0, 20, 0]} # use a random version that's fairly old
populate_cmd(cmd)
if password:
encrypt_cmd(cmd, password)
# cmd = {'version': [0, 14, 2], 'cmd': 'ls'}
# cmd = encrypt_cmd(cmd, 'test')
# with open(os.open(os.ctermid(), os.O_RDWR | os.O_CLOEXEC), 'w') as tty_file, raw_mode(tty_file.fileno()):
# print(end=f'\x1bP@kitty-cmd{json.dumps(cmd)}\x1b\\', flush=True, file=tty_file)
# os.read(tty_file.fileno(), 4096)

View File

@ -167,6 +167,12 @@ define a few extra key bindings in :file:`kitty.conf`::
map shift+right move_window right
map shift+down move_window down
# Move the active window to the indicated screen edge
map ctrl+shift+up layout_action move_to_screen_edge top
map ctrl+shift+left layout_action move_to_screen_edge left
map ctrl+shift+right layout_action move_to_screen_edge right
map ctrl+shift+down layout_action move_to_screen_edge bottom
# Switch focus to the neighboring window in the indicated direction
map ctrl+left neighboring_window left
map ctrl+right neighboring_window right

View File

@ -68,6 +68,13 @@ some special variables, documented below:
The path, query and fragment portions of the URL, without any
unquoting.
``EDITOR``
The terminal based text editor. The configured :opt:`editor` in
:file:`kitty.conf` is preferred.
``SHELL``
The path to the shell. The configured :opt:`shell` in :file:`kitty.conf` is
preferred, without arguments.
.. note::
You can use the :opt:`action_alias` option just as in :file:`kitty.conf` to
@ -103,7 +110,8 @@ lines. The various available criteria are:
Useful if your 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 md``. Note that the MIME type for directories is
``inode/directory``.
``inode/directory``. MIME types are detected based on file extension, not
file contents.
``ext``
A comma separated list of file extensions, for example: ``jpeg, tar.gz``

View File

@ -10,8 +10,9 @@ 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,
written in a mix of C (for performance sensitive parts), Python (for easy
extensibility and flexibility of the UI) and Go (for the command line
:term:`kittens`). 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
@ -85,7 +86,7 @@ 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
programs called :doc:`kittens <kittens_intro>`. These can be 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,
@ -127,7 +128,7 @@ 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:
option in :file:`kitty.conf`. An example, showing all available commands:
.. code-block:: session
@ -154,12 +155,14 @@ option in :file:`kitty.conf`. For example:
launch zsh
# Create a new OS window
# Any definitions specifed before the first new_os_window will apply to first OS window.
# Any definitions specified before the first new_os_window will apply to first OS window.
new_os_window
# Set new window size to 80x24 cells
os_window_size 80c 24c
# Set the --class for the new OS window
os_window_class mywindow
# Change the OS window state to normal, fullscreen, maximized or minimized
os_window_state normal
launch sh
# Resize the current window (see the resize_window action for details)
resize_window wider 2
@ -173,6 +176,11 @@ option in :file:`kitty.conf`. For example:
The :doc:`launch <launch>` command when used in a session file cannot create
new OS windows, or tabs.
.. note::
Environment variables of the for :code:`${NAME}` or :code:`$NAME` are
expanded in the session file, except in the *arguments* (not options) to the
launch command.
Creating tabs/windows
-------------------------------
@ -227,9 +235,10 @@ 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 comein handy
for applications like powerline, without the need to use patched fonts. See the
various font related configuration directives in :ref:`conf-kitty-fonts`.
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:

View File

@ -32,3 +32,4 @@ please do so by opening issues in the `GitHub bug tracker
unscroll
color-stack
deccara
clipboard

View File

@ -15,6 +15,7 @@ Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form:
"cmd": "command name",
"version": "<kitty version>",
"no_response": "<Optional Boolean>",
"kitty_window_id": "<Optional value of the KITTY_WINDOW_ID env var>",
"payload": "<Optional JSON object>"
}
@ -40,6 +41,12 @@ 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 .
There is also the statically compiled stand-alone executable ``kitten``
that can be used for this, available from the `kitty releases
<https://github.com/kovidgoyal/kitty/releases>`__ page::
kitten @ --help
.. _rc_crypto:
Encrypted communication
@ -76,5 +83,25 @@ is created and transmitted that contains the fields:
"encrypted": "The original command encrypted and base85 encoded"
}
Async and streaming requests
---------------------------------
Some remote control commands require asynchronous communication, that is, the
response from the terminal can happen after an arbitrary amount of time. For
example, the :code:`select-window` command requires the user to select a window
before a response can be sent. Such command must set the field :code:`async`
in the JSON block above to a random string that serves as a unique id. The
client can cancel an async request in flight by adding the :code:`cancel_async`
field to the JSON block. A async response remains in flight until the terminal
sends a response to the request. Note that cancellation requests dont need to
be encrypted as users must not be prompted for these and the worst a malicious
cancellation request can do is prevent another sync request from getting a
response.
Similar to async requests are *streaming* requests. In these the client has to
send a large amount of data to the terminal and so the request is split into
chunks. In every chunk the JSON block must contain the field ``stream`` set to
``true`` and ``stream_id`` set to a random long string, that should be the same for
all chunks in a request. End of data is indicated by sending a chunk with no data.
.. include:: generated/rc.rst

View File

@ -304,7 +304,13 @@ The remote control protocol
-----------------------------------------------
If you wish to develop your own client to talk to |kitty|, you can use the
:doc:`remote control protocol specification <rc_protocol>`.
:doc:`remote control protocol specification <rc_protocol>`. Note that there
is a statically compiled, standalone executable, ``kitten`` available that
can be used as a remote control client on any UNIX like computer. This can be
downloaded and used directly from the `kitty releases
<https://github.com/kovidgoyal/kitty/releases>`__ page::
kitten @ --help
.. _search_syntax:

View File

@ -1,5 +1,21 @@
A message from us at KittyPatch
===============================
KittyPatch was created as a home for useful features that are unavailable
in the kitty main branch. To this end, we do not accept donations directly.
If you wish to support KittyPatch: share your ideas and spread the word.
If you still wish to donate, please `support the Free Software Foundation
<https://my.fsf.org/donate>`.
A message from the maintainer of Kitty
======================================
Support kitty development ❤️
==============================
>>>>>>> upstream/master
My goal with |kitty| is to move the stagnant terminal ecosystem forward. To that
end kitty has many foundational features, such as: :doc:`image support

View File

@ -274,6 +274,7 @@ def graphics_parser() -> None:
'Y': ('cell_y_offset', 'uint'),
'z': ('z_index', 'int'),
'C': ('cursor_movement', 'uint'),
'U': ('unicode_placement', 'uint'),
}
text = generate('parse_graphics_code', 'screen_handle_graphics_command', 'graphics_command', keymap, 'GraphicsCommand')
write_header(text, 'kitty/parse-graphics-command.h')

View File

@ -3,6 +3,7 @@
import re
import subprocess
from typing import List
from kitty.conf.generate import write_output
@ -11,14 +12,25 @@ from kitty.conf.generate import write_output
def patch_color_list(path: str, colors: List[str], name: str, spc: str = ' ') -> None:
with open(path, 'r+') as f:
raw = f.read()
colors = sorted(colors)
if path.endswith('.go'):
spc = '\t'
nraw = re.sub(
fr'(// {name}_COLORS_START).+?(\s+// {name}_COLORS_END)',
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'"{x}":true,', colors)) + r'\2',
raw, flags=re.DOTALL | re.MULTILINE)
else:
nraw = re.sub(
fr'(# {name}_COLORS_START).+?(\s+# {name}_COLORS_END)',
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'{x!r},', sorted(colors))) + r'\2',
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'{x!r},', colors)) + r'\2',
raw, flags=re.DOTALL | re.MULTILINE)
if nraw != raw:
f.seek(0)
f.truncate()
f.write(nraw)
f.flush()
if path.endswith('.go'):
subprocess.check_call(['gofmt', '-w', path])
def main() -> None:
@ -34,12 +46,8 @@ def main() -> None:
elif opt.parser_func.__name__ in ('to_color', 'titlebar_color', 'macos_titlebar_color'):
all_colors.append(opt.name)
patch_color_list('kitty/rc/set_colors.py', nullable_colors, 'NULLABLE')
patch_color_list('kittens/themes/collection.py', all_colors, 'ALL', ' ' * 8)
from kittens.diff.options.definition import definition as kd
write_output('kittens.diff', kd)
from kittens.ssh.options.definition import definition as sd
write_output('kittens.ssh', sd)
patch_color_list('tools/cmd/at/set_colors.go', nullable_colors, 'NULLABLE')
patch_color_list('tools/themes/collection.go', all_colors, 'ALL')
if __name__ == '__main__':

767
gen-go-code.py Executable file
View File

@ -0,0 +1,767 @@
#!./kitty/launcher/kitty +launch
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
import bz2
import io
import json
import os
import re
import struct
import subprocess
import sys
import tarfile
from contextlib import contextmanager, suppress
from functools import lru_cache
from itertools import chain
from typing import (
Any,
BinaryIO,
Dict,
Iterator,
List,
Optional,
Sequence,
Set,
TextIO,
Tuple,
Union,
)
import kitty.constants as kc
from kittens.tui.operations import Mode
from kittens.tui.spinners import spinners
from kitty.cli import (
CompletionSpec,
GoOption,
go_options_for_seq,
parse_option_spec,
serialize_as_go_string,
)
from kitty.conf.generate import gen_go_code
from kitty.conf.types import Definition
from kitty.guess_mime_type import known_extensions, text_mimes
from kitty.key_encoding import config_mod_map
from kitty.key_names import character_key_name_aliases, functional_key_name_aliases
from kitty.options.types import Options
from kitty.rc.base import RemoteCommand, all_command_names, command_for_name
from kitty.remote_control import global_options_spec
from kitty.rgb import color_names
changed: List[str] = []
def newer(dest: str, *sources: str) -> bool:
try:
dtime = os.path.getmtime(dest)
except OSError:
return True
for s in chain(sources, (__file__,)):
with suppress(FileNotFoundError):
if os.path.getmtime(s) >= dtime:
return True
return False
# Utils {{{
def serialize_go_dict(x: Union[Dict[str, int], Dict[int, str], Dict[int, int], Dict[str, str]]) -> str:
ans = []
def s(x: Union[int, str]) -> str:
if isinstance(x, int):
return str(x)
return f'"{serialize_as_go_string(x)}"'
for k, v in x.items():
ans.append(f'{s(k)}: {s(v)}')
return '{' + ', '.join(ans) + '}'
def replace(template: str, **kw: str) -> str:
for k, v in kw.items():
template = template.replace(k, v)
return template
# }}}
# Completions {{{
@lru_cache
def kitten_cli_docs(kitten: str) -> Any:
from kittens.runner import get_kitten_cli_docs
return get_kitten_cli_docs(kitten)
@lru_cache
def go_options_for_kitten(kitten: str) -> Tuple[Sequence[GoOption], Optional[CompletionSpec]]:
kcd = kitten_cli_docs(kitten)
if kcd:
ospec = kcd['options']
return (tuple(go_options_for_seq(parse_option_spec(ospec())[0])), kcd.get('args_completion'))
return (), None
def generate_kittens_completion() -> None:
from kittens.runner import all_kitten_names, get_kitten_wrapper_of
for kitten in sorted(all_kitten_names()):
kn = 'kitten_' + kitten
print(f'{kn} := plus_kitten.AddSubCommand(&cli.Command{{Name:"{kitten}", Group: "Kittens"}})')
wof = get_kitten_wrapper_of(kitten)
if wof:
print(f'{kn}.ArgCompleter = cli.CompletionForWrapper("{serialize_as_go_string(wof)}")')
print(f'{kn}.OnlyArgsAllowed = true')
continue
gopts, ac = go_options_for_kitten(kitten)
if gopts or ac:
for opt in gopts:
print(opt.as_option(kn))
if ac is not None:
print(''.join(ac.as_go_code(kn + '.ArgCompleter', ' = ')))
else:
print(f'{kn}.HelpText = ""')
@lru_cache
def clone_safe_launch_opts() -> Sequence[GoOption]:
from kitty.launch import clone_safe_opts, options_spec
ans = []
allowed = clone_safe_opts()
for o in go_options_for_seq(parse_option_spec(options_spec())[0]):
if o.obj_dict['name'] in allowed:
ans.append(o)
return tuple(ans)
def completion_for_launch_wrappers(*names: str) -> None:
for o in clone_safe_launch_opts():
for name in names:
print(o.as_option(name))
def generate_completions_for_kitty() -> None:
from kitty.config import option_names_for_completion
print('package completion\n')
print('import "kitty/tools/cli"')
print('import "kitty/tools/cmd/tool"')
print('import "kitty/tools/cmd/at"')
conf_names = ', '.join((f'"{serialize_as_go_string(x)}"' for x in option_names_for_completion()))
print('var kitty_option_names_for_completion = []string{' + conf_names + '}')
print('func kitty(root *cli.Command) {')
# The kitty exe
print('k := root.AddSubCommand(&cli.Command{'
'Name:"kitty", SubCommandIsOptional: true, ArgCompleter: cli.CompleteExecutableFirstArg, SubCommandMustBeFirst: true })')
print('kt := root.AddSubCommand(&cli.Command{Name:"kitten", SubCommandMustBeFirst: true })')
print('tool.KittyToolEntryPoints(kt)')
for opt in go_options_for_seq(parse_option_spec()[0]):
print(opt.as_option('k'))
# kitty +
print('plus := k.AddSubCommand(&cli.Command{Name:"+", Group:"Entry points", ShortDescription: "Various special purpose tools and kittens"})')
# kitty +launch
print('plus_launch := plus.AddSubCommand(&cli.Command{'
'Name:"launch", Group:"Entry points", ShortDescription: "Launch Python scripts", ArgCompleter: complete_plus_launch})')
print('k.AddClone("", plus_launch).Name = "+launch"')
# kitty +list-fonts
print('plus_list_fonts := plus.AddSubCommand(&cli.Command{'
'Name:"list-fonts", Group:"Entry points", ShortDescription: "List all available monospaced fonts"})')
print('k.AddClone("", plus_list_fonts).Name = "+list-fonts"')
# kitty +runpy
print('plus_runpy := plus.AddSubCommand(&cli.Command{'
'Name: "runpy", Group:"Entry points", ArgCompleter: complete_plus_runpy, ShortDescription: "Run Python code"})')
print('k.AddClone("", plus_runpy).Name = "+runpy"')
# kitty +open
print('plus_open := plus.AddSubCommand(&cli.Command{'
'Name:"open", Group:"Entry points", ArgCompleter: complete_plus_open, ShortDescription: "Open files and URLs"})')
print('for _, og := range k.OptionGroups { plus_open.OptionGroups = append(plus_open.OptionGroups, og.Clone(plus_open)) }')
print('k.AddClone("", plus_open).Name = "+open"')
# kitty +kitten
print('plus_kitten := plus.AddSubCommand(&cli.Command{Name:"kitten", Group:"Kittens", SubCommandMustBeFirst: true})')
generate_kittens_completion()
print('k.AddClone("", plus_kitten).Name = "+kitten"')
# @
print('at.EntryPoint(k)')
# clone-in-kitty, edit-in-kitty
print('cik := root.AddSubCommand(&cli.Command{Name:"clone-in-kitty"})')
completion_for_launch_wrappers('cik')
print('}')
print('func init() {')
print('cli.RegisterExeForCompletion(kitty)')
print('}')
# }}}
# rc command wrappers {{{
json_field_types: Dict[str, str] = {
'bool': 'bool', 'str': 'escaped_string', 'list.str': '[]escaped_string', 'dict.str': 'map[escaped_string]escaped_string', 'float': 'float64', 'int': 'int',
'scroll_amount': 'any', 'spacing': 'any', 'colors': 'any',
}
def go_field_type(json_field_type: str) -> str:
q = json_field_types.get(json_field_type)
if q:
return q
if json_field_type.startswith('choices.'):
return 'string'
if '.' in json_field_type:
p, r = json_field_type.split('.', 1)
p = {'list': '[]', 'dict': 'map[string]'}[p]
return p + go_field_type(r)
raise TypeError(f'Unknown JSON field type: {json_field_type}')
class JSONField:
def __init__(self, line: str) -> None:
field_def = line.split(':', 1)[0]
self.required = False
self.field, self.field_type = field_def.split('/', 1)
if self.field.endswith('+'):
self.required = True
self.field = self.field[:-1]
self.struct_field_name = self.field[0].upper() + self.field[1:]
def go_declaration(self) -> str:
return self.struct_field_name + ' ' + go_field_type(self.field_type) + f'`json:"{self.field},omitempty"`'
def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) -> str:
template = '\n' + template[len('//go:build exclude'):]
NO_RESPONSE_BASE = 'false'
af: List[str] = []
a = af.append
af.extend(cmd.args.as_go_completion_code('ans'))
od: List[str] = []
option_map: Dict[str, GoOption] = {}
for o in rc_command_options(name):
option_map[o.go_var_name] = o
a(o.as_option('ans'))
if o.go_var_name in ('NoResponse', 'ResponseTimeout'):
continue
od.append(o.struct_declaration())
jd: List[str] = []
json_fields = []
field_types: Dict[str, str] = {}
for line in cmd.protocol_spec.splitlines():
line = line.strip()
if ':' not in line:
continue
f = JSONField(line)
json_fields.append(f)
field_types[f.field] = f.field_type
jd.append(f.go_declaration())
jc: List[str] = []
handled_fields: Set[str] = set()
jc.extend(cmd.args.as_go_code(name, field_types, handled_fields))
unhandled = {}
used_options = set()
for field in json_fields:
oq = (cmd.field_to_option_map or {}).get(field.field, field.field)
oq = ''.join(x.capitalize() for x in oq.split('_'))
if oq in option_map:
o = option_map[oq]
used_options.add(oq)
if field.field_type == 'str':
jc.append(f'payload.{field.struct_field_name} = escaped_string(options_{name}.{o.go_var_name})')
elif field.field_type == 'list.str':
jc.append(f'payload.{field.struct_field_name} = escape_list_of_strings(options_{name}.{o.go_var_name})')
elif field.field_type == 'dict.str':
jc.append(f'payload.{field.struct_field_name} = escape_dict_of_strings(options_{name}.{o.go_var_name})')
else:
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
elif field.field in handled_fields:
pass
else:
unhandled[field.field] = field
for x in tuple(unhandled):
if x == 'match_window' and 'Match' in option_map and 'Match' not in used_options:
used_options.add('Match')
o = option_map['Match']
field = unhandled[x]
if field.field_type == 'str':
jc.append(f'payload.{field.struct_field_name} = escaped_string(options_{name}.{o.go_var_name})')
else:
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
del unhandled[x]
if unhandled:
raise SystemExit(f'Cant map fields: {", ".join(unhandled)} for cmd: {name}')
if name != 'send_text':
unused_options = set(option_map) - used_options - {'NoResponse', 'ResponseTimeout'}
if unused_options:
raise SystemExit(f'Unused options: {", ".join(unused_options)} for command: {name}')
argspec = cmd.args.spec
if argspec:
argspec = ' ' + argspec
ans = replace(
template,
CMD_NAME=name, __FILE__=__file__, CLI_NAME=name.replace('_', '-'),
SHORT_DESC=serialize_as_go_string(cmd.short_desc),
LONG_DESC=serialize_as_go_string(cmd.desc.strip()),
IS_ASYNC='true' if cmd.is_asynchronous else 'false',
NO_RESPONSE_BASE=NO_RESPONSE_BASE, ADD_FLAGS_CODE='\n'.join(af),
WAIT_TIMEOUT=str(cmd.response_timeout),
OPTIONS_DECLARATION_CODE='\n'.join(od),
JSON_DECLARATION_CODE='\n'.join(jd),
JSON_INIT_CODE='\n'.join(jc), ARGSPEC=argspec,
STRING_RESPONSE_IS_ERROR='true' if cmd.string_return_is_error else 'false',
STREAM_WANTED='true' if cmd.reads_streaming_data else 'false',
)
return ans
# }}}
# kittens {{{
@lru_cache
def wrapped_kittens() -> Sequence[str]:
with open('shell-integration/ssh/kitty') as f:
for line in f:
if line.startswith(' wrapped_kittens="'):
val = line.strip().partition('"')[2][:-1]
return tuple(sorted(filter(None, val.split())))
raise Exception('Failed to read wrapped kittens from kitty wrapper script')
def generate_conf_parser(kitten: str, defn: Definition) -> None:
with replace_if_needed(f'kittens/{kitten}/conf_generated.go'):
print(f'package {kitten}')
print(gen_go_code(defn))
def generate_extra_cli_parser(name: str, spec: str) -> None:
print('import "kitty/tools/cli"')
go_opts = tuple(go_options_for_seq(parse_option_spec(spec)[0]))
print(f'type {name}_options struct ''{')
for opt in go_opts:
print(opt.struct_declaration())
print('}')
print(f'func parse_{name}_args(args []string) (*{name}_options, []string, error) ''{')
print(f'root := cli.Command{{Name: `{name}` }}')
for opt in go_opts:
print(opt.as_option('root'))
print('cmd, err := root.ParseArgs(args)')
print('if err != nil { return nil, nil, err }')
print(f'var opts {name}_options')
print('err = cmd.GetOptionValues(&opts)')
print('if err != nil { return nil, nil, err }')
print('return &opts, cmd.Args, nil')
print('}')
def kitten_clis() -> None:
from kittens.runner import get_kitten_conf_docs, get_kitten_extra_cli_parsers
for kitten in wrapped_kittens():
defn = get_kitten_conf_docs(kitten)
if defn is not None:
generate_conf_parser(kitten, defn)
ecp = get_kitten_extra_cli_parsers(kitten)
if ecp:
for name, spec in ecp.items():
with replace_if_needed(f'kittens/{kitten}/{name}_cli_generated.go'):
print(f'package {kitten}')
generate_extra_cli_parser(name, spec)
with replace_if_needed(f'kittens/{kitten}/cli_generated.go'):
od = []
kcd = kitten_cli_docs(kitten)
has_underscore = '_' in kitten
print(f'package {kitten}')
print('import "kitty/tools/cli"')
print('func create_cmd(root *cli.Command, run_func func(*cli.Command, *Options, []string)(int, error)) {')
print('ans := root.AddSubCommand(&cli.Command{')
print(f'Name: "{kitten}",')
if kcd:
print(f'ShortDescription: "{serialize_as_go_string(kcd["short_desc"])}",')
if kcd['usage']:
print(f'Usage: "[options] {serialize_as_go_string(kcd["usage"])}",')
print(f'HelpText: "{serialize_as_go_string(kcd["help_text"])}",')
print('Run: func(cmd *cli.Command, args []string) (int, error) {')
print('opts := Options{}')
print('err := cmd.GetOptionValues(&opts)')
print('if err != nil { return 1, err }')
print('return run_func(cmd, &opts, args)},')
if has_underscore:
print('Hidden: true,')
print('})')
gopts, ac = go_options_for_kitten(kitten)
for opt in gopts:
print(opt.as_option('ans'))
od.append(opt.struct_declaration())
if ac is not None:
print(''.join(ac.as_go_code('ans.ArgCompleter', ' = ')))
if has_underscore:
print("clone := root.AddClone(ans.Group, ans)")
print('clone.Hidden = false')
print(f'clone.Name = "{serialize_as_go_string(kitten.replace("_", "-"))}"')
if not kcd:
print('specialize_command(ans)')
print('}')
print('type Options struct {')
print('\n'.join(od))
print('}')
# }}}
# Constants {{{
def generate_spinners() -> str:
ans = ['package tui', 'import "time"', 'func NewSpinner(name string) *Spinner {', 'var ans *Spinner', 'switch name {']
a = ans.append
for name, spinner in spinners.items():
a(f'case "{serialize_as_go_string(name)}":')
a('ans = &Spinner{')
a(f'Name: "{serialize_as_go_string(name)}",')
a(f'interval: {spinner["interval"]},')
frames = ', '.join(f'"{serialize_as_go_string(x)}"' for x in spinner['frames'])
a(f'frames: []string{{{frames}}},')
a('}')
a('}')
a('if ans != nil {')
a('ans.interval *= time.Millisecond')
a('ans.current_frame = -1')
a('ans.last_change_at = time.Now().Add(-ans.interval)')
a('}')
a('return ans}')
return '\n'.join(ans)
def generate_color_names() -> str:
selfg = "" if Options.selection_foreground is None else Options.selection_foreground.as_sharp
selbg = "" if Options.selection_background is None else Options.selection_background.as_sharp
cursor = "" if Options.cursor is None else Options.cursor.as_sharp
return 'package style\n\nvar ColorNames = map[string]RGBA{' + '\n'.join(
f'\t"{name}": RGBA{{ Red:{val.red}, Green:{val.green}, Blue:{val.blue} }},'
for name, val in color_names.items()
) + '\n}' + '\n\nvar ColorTable = [256]uint32{' + ', '.join(
f'{x}' for x in Options.color_table) + '}\n' + f'''
var DefaultColors = struct {{
Foreground, Background, Cursor, SelectionFg, SelectionBg string
}}{{
Foreground: "{Options.foreground.as_sharp}",
Background: "{Options.background.as_sharp}",
Cursor: "{cursor}",
SelectionFg: "{selfg}",
SelectionBg: "{selbg}",
}}
'''
def load_ref_map() -> Dict[str, Dict[str, str]]:
with open('kitty/docs_ref_map_generated.h') as f:
raw = f.read()
raw = raw.split('{', 1)[1].split('}', 1)[0]
data = json.loads(bytes(bytearray(json.loads(f'[{raw}]'))))
return data # type: ignore
def generate_constants() -> str:
from kittens.hints.main import DEFAULT_REGEX
from kitty.options.types import Options
from kitty.options.utils import allowed_shell_integration_values
del sys.modules['kittens.hints.main']
ref_map = load_ref_map()
with open('kitty/data-types.h') as dt:
m = re.search(r'^#define IMAGE_PLACEHOLDER_CHAR (\S+)', dt.read(), flags=re.M)
assert m is not None
placeholder_char = int(m.group(1), 16)
dp = ", ".join(map(lambda x: f'"{serialize_as_go_string(x)}"', kc.default_pager_for_help))
url_prefixes = ','.join(f'"{x}"' for x in Options.url_prefixes)
return f'''\
package kitty
type VersionType struct {{
Major, Minor, Patch int
}}
const VersionString string = "{kc.str_version}"
const WebsiteBaseURL string = "{kc.website_base_url}"
const ImagePlaceholderChar rune = {placeholder_char}
const VCSRevision string = ""
const SSHControlMasterTemplate = "{kc.ssh_control_master_template}"
const RC_ENCRYPTION_PROTOCOL_VERSION string = "{kc.RC_ENCRYPTION_PROTOCOL_VERSION}"
const IsFrozenBuild bool = false
const IsStandaloneBuild bool = false
const HandleTermiosSignals = {Mode.HANDLE_TERMIOS_SIGNALS.value[0]}
const HintsDefaultRegex = `{DEFAULT_REGEX}`
var Version VersionType = VersionType{{Major: {kc.version.major}, Minor: {kc.version.minor}, Patch: {kc.version.patch},}}
var DefaultPager []string = []string{{ {dp} }}
var FunctionalKeyNameAliases = map[string]string{serialize_go_dict(functional_key_name_aliases)}
var CharacterKeyNameAliases = map[string]string{serialize_go_dict(character_key_name_aliases)}
var ConfigModMap = map[string]uint16{serialize_go_dict(config_mod_map)}
var RefMap = map[string]string{serialize_go_dict(ref_map['ref'])}
var DocTitleMap = map[string]string{serialize_go_dict(ref_map['doc'])}
var AllowedShellIntegrationValues = []string{{ {str(sorted(allowed_shell_integration_values))[1:-1].replace("'", '"')} }}
var KittyConfigDefaults = struct {{
Term, Shell_integration, Select_by_word_characters string
Wheel_scroll_multiplier int
Url_prefixes []string
}}{{
Term: "{Options.term}", Shell_integration: "{' '.join(Options.shell_integration)}", Url_prefixes: []string{{ {url_prefixes} }},
Select_by_word_characters: `{Options.select_by_word_characters}`, Wheel_scroll_multiplier: {Options.wheel_scroll_multiplier},
}}
''' # }}}
# Boilerplate {{{
@contextmanager
def replace_if_needed(path: str, show_diff: bool = False) -> Iterator[io.StringIO]:
buf = io.StringIO()
origb = sys.stdout
sys.stdout = buf
try:
yield buf
finally:
sys.stdout = origb
orig = ''
with suppress(FileNotFoundError), open(path, 'r') as f:
orig = f.read()
new = buf.getvalue()
new = f'// Code generated by {os.path.basename(__file__)}; DO NOT EDIT.\n\n' + new
if orig != new:
changed.append(path)
if show_diff:
with open(path + '.new', 'w') as f:
f.write(new)
subprocess.run(['diff', '-Naurp', path, f.name], stdout=open('/dev/tty', 'w'))
os.remove(f.name)
with open(path, 'w') as f:
f.write(new)
@lru_cache(maxsize=256)
def rc_command_options(name: str) -> Tuple[GoOption, ...]:
cmd = command_for_name(name)
return tuple(go_options_for_seq(parse_option_spec(cmd.options_spec or '\n\n')[0]))
def update_at_commands() -> None:
with open('tools/cmd/at/template.go') as f:
template = f.read()
for name in all_command_names():
cmd = command_for_name(name)
code = go_code_for_remote_command(name, cmd, template)
dest = f'tools/cmd/at/cmd_{name}_generated.go'
with replace_if_needed(dest) as f:
f.write(code)
struct_def = []
opt_def = []
for o in go_options_for_seq(parse_option_spec(global_options_spec())[0]):
struct_def.append(o.struct_declaration())
opt_def.append(o.as_option(depth=1, group="Global options"))
sdef = '\n'.join(struct_def)
odef = '\n'.join(opt_def)
code = f'''
package at
import "kitty/tools/cli"
type rc_global_options struct {{
{sdef}
}}
var rc_global_opts rc_global_options
func add_rc_global_opts(cmd *cli.Command) {{
{odef}
}}
'''
with replace_if_needed('tools/cmd/at/global_opts_generated.go') as f:
f.write(code)
def update_completion() -> None:
with replace_if_needed('tools/cmd/completion/kitty_generated.go'):
generate_completions_for_kitty()
with replace_if_needed('tools/cmd/edit_in_kitty/launch_generated.go'):
print('package edit_in_kitty')
print('import "kitty/tools/cli"')
print('func AddCloneSafeOpts(cmd *cli.Command) {')
completion_for_launch_wrappers('cmd')
print(''.join(CompletionSpec.from_string('type:file mime:text/* group:"Text files"').as_go_code('cmd.ArgCompleter', ' = ')))
print('}')
def define_enum(package_name: str, type_name: str, items: str, underlying_type: str = 'uint') -> str:
actions = []
for x in items.splitlines():
x = x.strip()
if x:
actions.append(x)
ans = [f'package {package_name}', 'import "strconv"', f'type {type_name} {underlying_type}', 'const (']
stringer = [f'func (ac {type_name}) String() string ''{', 'switch(ac) {']
for i, ac in enumerate(actions):
stringer.append(f'case {ac}: return "{ac}"')
if i == 0:
ac = ac + f' {type_name} = iota'
ans.append(ac)
ans.append(')')
stringer.append('}\nreturn strconv.Itoa(int(ac)) }')
return '\n'.join(ans + stringer)
def generate_readline_actions() -> str:
return define_enum('readline', 'Action', '''\
ActionNil
ActionBackspace
ActionDelete
ActionMoveToStartOfLine
ActionMoveToEndOfLine
ActionMoveToStartOfDocument
ActionMoveToEndOfDocument
ActionMoveToEndOfWord
ActionMoveToStartOfWord
ActionCursorLeft
ActionCursorRight
ActionEndInput
ActionAcceptInput
ActionCursorUp
ActionHistoryPreviousOrCursorUp
ActionCursorDown
ActionHistoryNextOrCursorDown
ActionHistoryNext
ActionHistoryPrevious
ActionHistoryFirst
ActionHistoryLast
ActionHistoryIncrementalSearchBackwards
ActionHistoryIncrementalSearchForwards
ActionTerminateHistorySearchAndApply
ActionTerminateHistorySearchAndRestore
ActionClearScreen
ActionAddText
ActionAbortCurrentLine
ActionStartKillActions
ActionKillToEndOfLine
ActionKillToStartOfLine
ActionKillNextWord
ActionKillPreviousWord
ActionKillPreviousSpaceDelimitedWord
ActionEndKillActions
ActionYank
ActionPopYank
ActionNumericArgumentDigit0
ActionNumericArgumentDigit1
ActionNumericArgumentDigit2
ActionNumericArgumentDigit3
ActionNumericArgumentDigit4
ActionNumericArgumentDigit5
ActionNumericArgumentDigit6
ActionNumericArgumentDigit7
ActionNumericArgumentDigit8
ActionNumericArgumentDigit9
ActionNumericArgumentDigitMinus
ActionCompleteForward
ActionCompleteBackward
''')
def generate_mimetypes() -> str:
import mimetypes
if not mimetypes.inited:
mimetypes.init()
ans = ['package utils', 'import "sync"', 'var only_once sync.Once', 'var builtin_types_map map[string]string',
'func set_builtins() {', 'builtin_types_map = map[string]string{',]
for k, v in mimetypes.types_map.items():
ans.append(f' "{serialize_as_go_string(k)}": "{serialize_as_go_string(v)}",')
ans.append('}}')
return '\n'.join(ans)
def generate_textual_mimetypes() -> str:
ans = ['package utils', 'var KnownTextualMimes = map[string]bool{',]
for k in text_mimes:
ans.append(f' "{serialize_as_go_string(k)}": true,')
ans.append('}')
ans.append('var KnownExtensions = map[string]string{')
for k, v in known_extensions.items():
ans.append(f' ".{serialize_as_go_string(k)}": "{serialize_as_go_string(v)}",')
ans.append('}')
return '\n'.join(ans)
def write_compressed_data(data: bytes, d: BinaryIO) -> None:
d.write(struct.pack('<I', len(data)))
d.write(bz2.compress(data))
def generate_unicode_names(src: TextIO, dest: BinaryIO) -> None:
num_names, num_of_words = map(int, next(src).split())
gob = io.BytesIO()
gob.write(struct.pack('<II', num_names, num_of_words))
for line in src:
line = line.strip()
if line:
a, aliases = line.partition('\t')[::2]
cp, name = a.partition(' ')[::2]
ename = name.encode()
record = struct.pack('<IH', int(cp), len(ename)) + ename
if aliases:
record += aliases.encode()
gob.write(struct.pack('<H', len(record)) + record)
write_compressed_data(gob.getvalue(), dest)
def generate_ssh_kitten_data() -> None:
files = {
'terminfo/kitty.terminfo', 'terminfo/x/xterm-kitty',
}
for dirpath, dirnames, filenames in os.walk('shell-integration'):
for f in filenames:
path = os.path.join(dirpath, f)
files.add(path.replace(os.sep, '/'))
dest = 'kittens/ssh/data_generated.bin'
def normalize(t: tarfile.TarInfo) -> tarfile.TarInfo:
t.uid = t.gid = 0
t.uname = t.gname = ''
return t
if newer(dest, *files):
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode='w') as tf:
for f in sorted(files):
tf.add(f, filter=normalize)
with open(dest, 'wb') as d:
write_compressed_data(buf.getvalue(), d)
def main() -> None:
with replace_if_needed('constants_generated.go') as f:
f.write(generate_constants())
with replace_if_needed('tools/utils/style/color-names_generated.go') as f:
f.write(generate_color_names())
with replace_if_needed('tools/tui/readline/actions_generated.go') as f:
f.write(generate_readline_actions())
with replace_if_needed('tools/tui/spinners_generated.go') as f:
f.write(generate_spinners())
with replace_if_needed('tools/utils/mimetypes_generated.go') as f:
f.write(generate_mimetypes())
with replace_if_needed('tools/utils/mimetypes_textual_generated.go') as f:
f.write(generate_textual_mimetypes())
if newer('tools/unicode_names/data_generated.bin', 'tools/unicode_names/names.txt'):
with open('tools/unicode_names/data_generated.bin', 'wb') as dest, open('tools/unicode_names/names.txt') as src:
generate_unicode_names(src, dest)
generate_ssh_kitten_data()
update_completion()
update_at_commands()
kitten_clis()
print(json.dumps(changed, indent=2))
if __name__ == '__main__':
main() # }}}

View File

@ -2,8 +2,8 @@
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
import string
from typing import Dict, List, Any
from pprint import pformat
from typing import Any, Dict, List, Union
functional_key_defs = '''# {{{
# kitty XKB macVK macU
@ -130,7 +130,7 @@ functional_encoding_overrides = {
}
different_trailer_functionals = {
'up': 'A', 'down': 'B', 'right': 'C', 'left': 'D', 'kp_begin': 'E', 'end': 'F', 'home': 'H',
'f1': 'P', 'f2': 'Q', 'f3': 'R', 'f4': 'S', 'enter': 'u', 'tab': 'u',
'f1': 'P', 'f2': 'Q', 'f3': '~', 'f4': 'S', 'enter': 'u', 'tab': 'u',
'backspace': 'u', 'escape': 'u'
}
@ -248,6 +248,19 @@ def serialize_dict(x: Dict[Any, Any]) -> str:
return pformat(x, indent=4).replace('{', '{\n ', 1)
def serialize_go_dict(x: Union[Dict[str, int], Dict[int, str], Dict[int, int]]) -> str:
ans = []
def s(x: Union[int, str]) -> str:
if isinstance(x, int):
return str(x)
return f'"{x}"'
for k, v in x.items():
ans.append(f'{s(k)}: {s(v)}')
return '{' + ', '.join(ans) + '}'
def generate_glfw_header() -> None:
lines = [
'typedef enum {',
@ -309,14 +322,20 @@ def generate_functional_table() -> None:
patch_file('kitty/key_encoding.c', 'special numbers', '\n'.join(enc_lines))
code_to_name = {v: k.upper() for k, v in name_to_code.items()}
csi_map = {v: name_to_code[k] for k, v in functional_encoding_overrides.items()}
letter_trailer_codes = {
v: functional_encoding_overrides.get(k, name_to_code.get(k))
letter_trailer_codes: Dict[str, int] = {
v: functional_encoding_overrides.get(k, name_to_code.get(k, 0))
for k, v in different_trailer_functionals.items() if v in 'ABCDEHFPQRSZ'}
text = f'functional_key_number_to_name_map = {serialize_dict(code_to_name)}'
text += f'\ncsi_number_to_functional_number_map = {serialize_dict(csi_map)}'
text += f'\nletter_trailer_to_csi_number_map = {letter_trailer_codes!r}'
text += f'\ntilde_trailers = {tilde_trailers!r}'
patch_file('kitty/key_encoding.py', 'csi mapping', text, start_marker='# ', end_marker='')
text = f'var functional_key_number_to_name_map = map[int]string{serialize_go_dict(code_to_name)}\n'
text += f'\nvar csi_number_to_functional_number_map = map[int]int{serialize_go_dict(csi_map)}\n'
text += f'\nvar letter_trailer_to_csi_number_map = map[string]int{serialize_go_dict(letter_trailer_codes)}\n'
tt = ', '.join(f'{x}: true' for x in tilde_trailers)
text += '\nvar tilde_trailers = map[int]bool{' + f'{tt}' + '}\n'
patch_file('tools/tui/loop/key-encoding.go', 'csi mapping', text, start_marker='// ', end_marker='')
def generate_legacy_text_key_maps() -> None:

48
gen-srgb-lut.py Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
# vim:fileencoding=utf-8
import os
from typing import List
def to_linear(a: float) -> float:
if a <= 0.04045:
return a / 12.92
else:
return float(pow((a + 0.055) / 1.055, 2.4))
def generate_srgb_lut(line_prefix: str = '') -> List[str]:
values: List[str] = []
lines: List[str] = []
for i in range(256):
values.append('{:1.5f}f'.format(to_linear(i / 255.0)))
for i in range(16):
lines.append(line_prefix + ', '.join(values[i * 16:(i + 1) * 16]) + ',')
return lines
def generate_srgb_gamma_c() -> str:
lines: List[str] = []
lines.append('// Generated by gen-srgb-lut.py DO NOT edit')
lines.append('#include "srgb_gamma.h"')
lines.append('')
lines.append('const GLfloat srgb_lut[256] = {')
lines += generate_srgb_lut(' ')
lines.append('};')
return "\n".join(lines)
def main() -> None:
c = generate_srgb_gamma_c()
with open(os.path.join('kitty', 'srgb_gamma.c'), 'w') as f:
f.write(f'{c}\n')
if __name__ == '__main__':
main()

View File

@ -3,17 +3,26 @@
import os
import re
import subprocess
import sys
from collections import defaultdict
from contextlib import contextmanager
from datetime import date
from functools import partial
from functools import lru_cache, partial
from html.entities import html5
from itertools import groupby
from operator import itemgetter
from typing import (
Callable, DefaultDict, Dict, FrozenSet, Generator, Iterable, List,
Optional, Set, Tuple, Union
Callable,
DefaultDict,
Dict,
FrozenSet,
Generator,
Iterable,
List,
Optional,
Set,
Tuple,
Union,
)
from urllib.request import urlopen
@ -44,6 +53,15 @@ def get_data(fname: str, folder: str = 'UCD') -> Iterable[str]:
yield line
@lru_cache(maxsize=2)
def unicode_version() -> Tuple[int, int, int]:
for line in get_data("ReadMe.txt"):
m = re.search(r'Version\s+(\d+)\.(\d+)\.(\d+)', line)
if m is not None:
return int(m.group(1)), int(m.group(2)), int(m.group(3))
raise ValueError('Could not find Unicode Version')
# Map of class names to set of codepoints in class
class_maps: Dict[str, Set[int]] = {}
all_symbols: Set[int] = set()
@ -254,8 +272,12 @@ def get_ranges(items: List[int]) -> Generator[Union[int, Tuple[int, int]], None,
yield a, b
def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None]) -> None:
def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None], for_go: bool = False) -> None:
if isinstance(spec, tuple):
if for_go:
v = ', '.join(f'0x{x:x}' for x in range(spec[0], spec[1] + 1))
p(f'\t\tcase {v}:')
else:
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
else:
p(f'\t\tcase 0x{spec:x}:')
@ -265,8 +287,8 @@ def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None]) -> Non
def create_header(path: str, include_data_types: bool = True) -> Generator[Callable[..., None], None, None]:
with open(path, 'w') as f:
p = partial(print, file=f)
p('// unicode data, built from the unicode standard on:', date.today())
p('// see gen-wcwidth.py')
p('// Unicode data, built from the Unicode Standard', '.'.join(map(str, unicode_version())))
p(f'// Code generated by {os.path.basename(__file__)}, DO NOT EDIT.', end='\n\n')
if path.endswith('.h'):
p('#pragma once')
if include_data_types:
@ -347,13 +369,19 @@ def codepoint_to_mark_map(p: Callable[..., None], mark_map: List[int]) -> Dict[i
return rmap
def classes_to_regex(classes: Iterable[str], exclude: str = '') -> Iterable[str]:
def classes_to_regex(classes: Iterable[str], exclude: str = '', for_go: bool = True) -> Iterable[str]:
chars: Set[int] = set()
for c in classes:
chars |= class_maps[c]
for x in map(ord, exclude):
chars.discard(x)
if for_go:
def as_string(codepoint: int) -> str:
if codepoint < 256:
return fr'\x{codepoint:02x}'
return fr'\x{{{codepoint:x}}}'
else:
def as_string(codepoint: int) -> str:
if codepoint < 256:
return fr'\x{codepoint:02x}'
@ -416,153 +444,144 @@ def gen_ucd() -> None:
f.truncate()
f.write(raw)
with open('kittens/hints/url_regex.py', 'w') as f:
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'))))
chars = ''.join(classes_to_regex(cz, exclude='\n\r'))
with open('tools/cmd/hints/url_regex.go', 'w') as f:
f.write('// generated by gen-wcwidth.py, do not edit\n\n')
f.write('package hints\n\n')
f.write(f'const URL_DELIMITERS = `{chars}`\n')
def gen_names() -> None:
with create_header('kittens/unicode_input/names.h') as p:
mark_to_cp = list(sorted(name_map))
cp_to_mark = {cp: m for m, cp in enumerate(mark_to_cp)}
# Mapping of mark to codepoint name
p(f'static const char* name_map[{len(mark_to_cp)}] = {{' ' // {{{')
for cp in mark_to_cp:
w = name_map[cp].replace('"', '\\"')
p(f'\t"{w}",')
p("}; // }}}\n")
# Mapping of mark to codepoint
p(f'static const char_type mark_to_cp[{len(mark_to_cp)}] = {{' ' // {{{')
p(', '.join(map(str, mark_to_cp)))
p('}; // }}}\n')
# Function to get mark number for codepoint
p('static char_type mark_for_codepoint(char_type c) {')
codepoint_to_mark_map(p, mark_to_cp)
p('}\n')
p('static inline const char* name_for_codepoint(char_type cp) {')
p('\tchar_type m = mark_for_codepoint(cp); if (m == 0) return NULL;')
p('\treturn name_map[m];')
p('}\n')
# Array of all words
word_map = tuple(sorted(word_search_map))
word_rmap = {w: i for i, w in enumerate(word_map)}
p(f'static const char* all_words_map[{len(word_map)}] = {{' ' // {{{')
cwords = (w.replace('"', '\\"') for w in word_map)
p(', '.join(f'"{w}"' for w in cwords))
p('}; // }}}\n')
# Array of sets of marks for each word
word_to_marks = {word_rmap[w]: frozenset(map(cp_to_mark.__getitem__, cps)) for w, cps in word_search_map.items()}
all_mark_groups = frozenset(word_to_marks.values())
array = [0]
mg_to_offset = {}
for mg in all_mark_groups:
mg_to_offset[mg] = len(array)
array.append(len(mg))
array.extend(sorted(mg))
p(f'static const char_type mark_groups[{len(array)}] = {{' ' // {{{')
p(', '.join(map(str, array)))
p('}; // }}}\n')
offsets_array = []
for wi, w in enumerate(word_map):
mg = word_to_marks[wi]
offsets_array.append(mg_to_offset[mg])
p(f'static const char_type mark_to_offset[{len(offsets_array)}] = {{' ' // {{{')
p(', '.join(map(str, offsets_array)))
p('}; // }}}\n')
# The trie
p('typedef struct { uint32_t children_offset; uint32_t match_offset; } word_trie;\n')
all_trie_nodes: List['TrieNode'] = [] # noqa
class TrieNode:
def __init__(self) -> None:
self.match_offset = 0
self.children_offset = 0
self.children: Dict[int, int] = {}
def add_letter(self, letter: int) -> int:
if letter not in self.children:
self.children[letter] = len(all_trie_nodes)
all_trie_nodes.append(TrieNode())
return self.children[letter]
def __str__(self) -> str:
return f'{{ .children_offset={self.children_offset}, .match_offset={self.match_offset} }}'
root = TrieNode()
all_trie_nodes.append(root)
def add_word(word_idx: int, word: str) -> None:
parent = root
for letter in map(ord, word):
idx = parent.add_letter(letter)
parent = all_trie_nodes[idx]
parent.match_offset = offsets_array[word_idx]
for i, word in enumerate(word_map):
add_word(i, word)
children_array = [0]
for node in all_trie_nodes:
if node.children:
node.children_offset = len(children_array)
children_array.append(len(node.children))
for letter, child_offset in node.children.items():
children_array.append((child_offset << 8) | (letter & 0xff))
p(f'static const word_trie all_trie_nodes[{len(all_trie_nodes)}] = {{' ' // {{{')
p(',\n'.join(map(str, all_trie_nodes)))
p('\n}; // }}}\n')
p(f'static const uint32_t children_array[{len(children_array)}] = {{' ' // {{{')
p(', '.join(map(str, children_array)))
p('}; // }}}\n')
aliases_map: Dict[int, Set[str]] = {}
for word, codepoints in word_search_map.items():
for cp in codepoints:
aliases_map.setdefault(cp, set()).add(word)
if len(name_map) > 0xffff:
raise Exception('Too many named codepoints')
with open('tools/unicode_names/names.txt', 'w') as f:
print(len(name_map), len(word_search_map), file=f)
for cp in sorted(name_map):
name = name_map[cp]
words = name.lower().split()
aliases = aliases_map.get(cp, set()) - set(words)
end = '\n'
if aliases:
end = '\t' + ' '.join(sorted(aliases)) + end
print(cp, *words, end=end, file=f)
def gen_wcwidth() -> None:
seen: Set[int] = set()
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
def add(p: Callable[..., None], comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
def add(p: Callable[..., None], comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int, for_go: bool = False) -> None:
chars = chars_ - seen
seen.update(chars)
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
for spec in get_ranges(list(chars)):
write_case(spec, p)
write_case(spec, p, for_go)
p(f'\t\t\treturn {ret};')
p('\t\t// }}}\n')
with create_header('kitty/wcwidth-std.h') as p:
p('static inline int\nwcwidth_std(int32_t code) {')
p('\tif (LIKELY(0x20 <= code && code <= 0x7e)) return 1;')
p('\tswitch(code) {')
def add_all(p: Callable[..., None], for_go: bool = False) -> None:
seen.clear()
add(p, 'Flags', flag_codepoints, 2, for_go)
add(p, 'Marks', marks | {0}, 0, for_go)
add(p, 'Non-printing characters', non_printing, -1, for_go)
add(p, 'Private use', class_maps['Co'], -3, for_go)
add(p, 'Text Presentation', narrow_emoji, 1, for_go)
add(p, 'East Asian ambiguous width', ambiguous, -2, for_go)
add(p, 'East Asian double width', doublewidth, 2, for_go)
add(p, 'Emoji Presentation', wide_emoji, 2, for_go)
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
add(p, 'Flags', flag_codepoints, 2)
add(p, 'Marks', marks | {0}, 0)
add(p, 'Non-printing characters', non_printing, -1)
add(p, 'Private use', class_maps['Co'], -3)
add(p, 'Text Presentation', narrow_emoji, 1)
add(p, 'East Asian ambiguous width', ambiguous, -2)
add(p, 'East Asian double width', doublewidth, 2)
add(p, 'Emoji Presentation', wide_emoji, 2)
add(p, 'Not assigned in the unicode character database', not_assigned, -4, for_go)
add(p, 'Not assigned in the unicode character database', not_assigned, -4)
p('\t\tdefault: return 1;')
p('\t\tdefault:\n\t\t\treturn 1;')
p('\t}')
if for_go:
p('\t}')
else:
p('\treturn 1;\n}')
with create_header('kitty/wcwidth-std.h') as p, open('tools/wcswidth/std.go', 'w') as gof:
gop = partial(print, file=gof)
gop('package wcswidth\n\n')
gop('func Runewidth(code rune) int {')
p('static inline int\nwcwidth_std(int32_t code) {')
p('\tif (LIKELY(0x20 <= code && code <= 0x7e)) { return 1; }')
p('\tswitch(code) {')
gop('\tswitch(code) {')
add_all(p)
add_all(gop, True)
p('static inline bool\nis_emoji_presentation_base(uint32_t code) {')
gop('func IsEmojiPresentationBase(code rune) bool {')
p('\tswitch(code) {')
gop('\tswitch(code) {')
for spec in get_ranges(list(emoji_presentation_bases)):
write_case(spec, p)
write_case(spec, gop, for_go=True)
p('\t\t\treturn true;')
gop('\t\t\treturn true;')
p('\t\tdefault: return false;')
p('\t}')
p('\treturn 1;\n}')
gop('\t\tdefault:\n\t\t\treturn false')
gop('\t}')
p('\treturn true;\n}')
gop('\n}')
uv = unicode_version()
p(f'#define UNICODE_MAJOR_VERSION {uv[0]}')
p(f'#define UNICODE_MINOR_VERSION {uv[1]}')
p(f'#define UNICODE_PATCH_VERSION {uv[2]}')
gop('var UnicodeDatabaseVersion [3]int = [3]int{' f'{uv[0]}, {uv[1]}, {uv[2]}' + '}')
subprocess.check_call(['gofmt', '-w', '-s', gof.name])
def gen_rowcolumn_diacritics() -> None:
# codes of all row/column diacritics
codes = []
with open("./rowcolumn-diacritics.txt") as file:
for line in file.readlines():
if line.startswith('#'):
continue
code = int(line.split(";")[0], 16)
codes.append(code)
go_file = 'tools/utils/images/rowcolumn_diacritics.go'
with create_header('kitty/rowcolumn-diacritics.c') as p, create_header(go_file, include_data_types=False) as g:
p('#include "unicode-data.h"')
p('int diacritic_to_num(char_type code) {')
p('\tswitch (code) {')
g('package images')
g(f'var NumberToDiacritic = [{len(codes)}]rune''{')
g(', '.join(f'0x{x:x}' for x in codes) + ',')
g('}')
range_start_num = 1
range_start = 0
range_end = 0
def print_range() -> None:
if range_start >= range_end:
return
write_case((range_start, range_end), p)
p('\t\treturn code - ' + hex(range_start) + ' + ' +
str(range_start_num) + ';')
for code in codes:
if range_end == code:
range_end += 1
else:
print_range()
range_start_num += range_end - range_start
range_start = code
range_end = code + 1
print_range()
p('\t}')
p('\treturn 0;')
p('}')
subprocess.check_call(['gofmt', '-w', '-s', go_file])
parse_ucd()
@ -573,3 +592,4 @@ gen_ucd()
gen_wcwidth()
gen_emoji()
gen_names()
gen_rowcolumn_diacritics()

View File

@ -8,10 +8,9 @@ import shlex
import shutil
import subprocess
cmdline = (
'glad --out-path {dest} --api gl:core=3.3 '
' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug '
'glad --out-path {dest} --api gl:core=3.1 '
' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_ARB_instanced_arrays,GL_KHR_debug '
'c --header-only --debug'
)

View File

@ -1014,7 +1014,7 @@ static pthread_t main_thread;
static NSLock *tick_lock = NULL;
void _glfwDispatchTickCallback() {
void _glfwDispatchTickCallback(void) {
if (tick_lock && tick_callback) {
[tick_lock lock];
while(tick_callback_requested) {
@ -1026,7 +1026,7 @@ void _glfwDispatchTickCallback() {
}
static void
request_tick_callback() {
request_tick_callback(void) {
if (!tick_callback_requested) {
tick_callback_requested = true;
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];

View File

@ -323,7 +323,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void _glfwClearDisplayLinks() {
void _glfwClearDisplayLinks(void) {
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
if (_glfw.ns.displayLinks.entries[i].displayLink) {
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);

View File

@ -1010,6 +1010,18 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputCursorEnter(window, true);
}
- (void)viewDidChangeEffectiveAppearance
{
static int appearance = 0;
if (_glfw.callbacks.system_color_theme_change) {
int new_appearance = glfwGetCurrentSystemColorTheme();
if (new_appearance != appearance) {
appearance = new_appearance;
_glfw.callbacks.system_color_theme_change(appearance);
}
}
}
- (void)viewDidChangeBackingProperties
{
if (!window) return;
@ -1454,15 +1466,11 @@ is_ascii_control_char(char x) {
}
void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
[w->ns.view updateIMEStateFor: ev->type focused:(bool)ev->focused left:(CGFloat)ev->cursor.left top:(CGFloat)ev->cursor.top cellWidth:(CGFloat)ev->cursor.width cellHeight:(CGFloat)ev->cursor.height];
[w->ns.view updateIMEStateFor: ev->type focused:(bool)ev->focused];
}
- (void)updateIMEStateFor:(GLFWIMEUpdateType)which
focused:(bool)focused
left:(CGFloat)left
top:(CGFloat)top
cellWidth:(CGFloat)cellWidth
cellHeight:(CGFloat)cellHeight
{
if (which == GLFW_IME_UPDATE_FOCUS && !focused && [self hasMarkedText] && window) {
[input_context discardMarkedText];
@ -1472,16 +1480,7 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
_glfw.ns.text[0] = 0;
}
if (which != GLFW_IME_UPDATE_CURSOR_POSITION) return;
left /= window->ns.xscale;
top /= window->ns.yscale;
cellWidth /= window->ns.xscale;
cellHeight /= window->ns.yscale;
debug_key("updateIMEPosition: left=%f, top=%f, width=%f, height=%f\n", left, top, cellWidth, cellHeight);
const NSRect frame = [window->ns.view frame];
const NSRect rectInView = NSMakeRect(left,
frame.size.height - top - cellHeight,
cellWidth, cellHeight);
markedRect = [window->ns.object convertRectToScreen: rectInView];
if (_glfwPlatformWindowFocused(window)) [[window->ns.view inputContext] invalidateCharacterCoordinates];
}
@ -1507,6 +1506,21 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
actualRange:(NSRangePointer)actualRange
{
(void)range; (void)actualRange;
if (_glfw.callbacks.get_ime_cursor_position) {
GLFWIMEUpdateEvent ev = { .type = GLFW_IME_UPDATE_CURSOR_POSITION };
if (_glfw.callbacks.get_ime_cursor_position((GLFWwindow*)window, &ev)) {
const CGFloat left = (CGFloat)ev.cursor.left / window->ns.xscale;
const CGFloat top = (CGFloat)ev.cursor.top / window->ns.yscale;
const CGFloat cellWidth = (CGFloat)ev.cursor.width / window->ns.xscale;
const CGFloat cellHeight = (CGFloat)ev.cursor.height / window->ns.yscale;
debug_key("updateIMEPosition: left=%f, top=%f, width=%f, height=%f\n", left, top, cellWidth, cellHeight);
const NSRect frame = [window->ns.view frame];
const NSRect rectInView = NSMakeRect(left,
frame.size.height - top - cellHeight,
cellWidth, cellHeight);
markedRect = [window->ns.object convertRectToScreen: rectInView];
}
}
return markedRect;
}
@ -1576,6 +1590,71 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
return text;
}
// <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/Articles/using.html>
// Support services receiving "public.utf8-plain-text" and "NSStringPboardType"
- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
{
if (
(!sendType || [sendType isEqual:NSPasteboardTypeString] || [sendType isEqual:@"NSStringPboardType"]) &&
(!returnType || [returnType isEqual:NSPasteboardTypeString] || [returnType isEqual:@"NSStringPboardType"])
) {
if (_glfw.callbacks.has_current_selection && _glfw.callbacks.has_current_selection()) return self;
}
return [super validRequestorForSendType:sendType returnType:returnType];
}
// Selected text as input to be sent to Services
// For example, after selecting an absolute path, open the global menu bar kitty->Services and click `Show in Finder`.
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types
{
if (!_glfw.callbacks.get_current_selection) return NO;
char *text = _glfw.callbacks.get_current_selection();
if (!text) return NO;
BOOL ans = NO;
if (text[0]) {
if ([types containsObject:NSPasteboardTypeString] == YES) {
[pboard declareTypes:@[NSPasteboardTypeString] owner:self];
ans = [pboard setString:@(text) forType:NSPasteboardTypeString];
} else if ([types containsObject:@"NSStringPboardType"] == YES) {
[pboard declareTypes:@[@"NSStringPboardType"] owner:self];
ans = [pboard setString:@(text) forType:@"NSStringPboardType"];
}
free(text);
}
return ans;
}
// Service output to be handled
// For example, open System Settings->Keyboard->Keyboard Shortcuts->Services->Text, enable `Convert Text to Full Width`, select some text and execute the service.
- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard
{
NSString* text = nil;
NSArray *types = [pboard types];
if ([types containsObject:NSPasteboardTypeString] == YES) {
text = [pboard stringForType:NSPasteboardTypeString]; // public.utf8-plain-text
} else if ([types containsObject:@"NSStringPboardType"] == YES) {
text = [pboard stringForType:@"NSStringPboardType"]; // for older services (need re-encode?)
} else {
return NO;
}
if (text && [text length] > 0) {
// The service wants us to replace the selection, but we can't replace anything but insert text.
const char *utf8 = polymorphic_string_as_utf8(text);
debug_key("Sending text received in readSelectionFromPasteboard as key event\n");
GLFWkeyevent glfw_keyevent = {.text=utf8, .ime_state=GLFW_IME_COMMIT_TEXT};
_glfwInputKeyboard(window, &glfw_keyevent);
// Restore pre-edit text after inserting the received text
if ([self hasMarkedText]) {
glfw_keyevent.text = [[markedText string] UTF8String];
glfw_keyevent.ime_state = GLFW_IME_PREEDIT_CHANGED;
_glfwInputKeyboard(window, &glfw_keyevent);
}
return YES;
}
return NO;
}
@end
// }}}
@ -1652,6 +1731,18 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
if (glfw_window && !glfw_window->decorated && glfw_window->ns.view) [self makeFirstResponder:glfw_window->ns.view];
}
- (void)zoom:(id)sender
{
if (![self isZoomed]) {
const NSSize original = [self resizeIncrements];
[self setResizeIncrements:NSMakeSize(1.0, 1.0)];
[super zoom:sender];
[self setResizeIncrements:original];
} else {
[super zoom:sender];
}
}
@end
// }}}
@ -1805,8 +1896,9 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
// Do not show the window here until after setting the window size, maximized state, and full screen
// _glfwPlatformShowWindow(window);
// _glfwPlatformFocusWindow(window);
acquireMonitor(window);
}
@ -1998,9 +2090,10 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
if (![window->ns.object isZoomed])
if (![window->ns.object isZoomed]) {
[window->ns.object zoom:nil];
}
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
@ -2505,6 +2598,19 @@ bool _glfwPlatformToggleFullscreen(_GLFWwindow* w, unsigned int flags) {
if (in_fullscreen) made_fullscreen = false;
[window toggleFullScreen: nil];
}
// Update window button visibility
if (w->ns.titlebar_hidden) {
// The hidden buttons might be automatically reset to be visible after going full screen
// to show up in the auto-hide title bar, so they need to be set back to hidden.
BOOL button_hidden = YES;
// When title bar is configured to be hidden, it should be shown with buttons (auto-hide) after going to full screen.
if (!traditional) {
button_hidden = (BOOL) !made_fullscreen;
}
[[window standardWindowButton: NSWindowCloseButton] setHidden:button_hidden];
[[window standardWindowButton: NSWindowMiniaturizeButton] setHidden:button_hidden];
[[window standardWindowButton: NSWindowZoomButton] setHidden:button_hidden];
}
return made_fullscreen;
}
@ -2863,6 +2969,19 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun
requestRenderFrame((_GLFWwindow*)w, callback);
}
GLFWAPI int glfwGetCurrentSystemColorTheme(void) {
int theme_type = 0;
NSAppearance *changedAppearance = NSApp.effectiveAppearance;
NSAppearanceName newAppearance = [changedAppearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
if([newAppearance isEqualToString:NSAppearanceNameDarkAqua]){
theme_type = 1;
} else {
theme_type = 2;
}
return theme_type;
}
GLFWAPI uint32_t
glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int *cocoa_mods) {
*cocoa_mods = 0;

3
glfw/context.c vendored
View File

@ -478,6 +478,9 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
}
window->context.swapBuffers(window);
#ifdef _GLFW_WAYLAND
_glfwWaylandAfterBufferSwap(window);
#endif
}
GLFWAPI void glfwSwapInterval(int interval)

4
glfw/dbus_glfw.c vendored
View File

@ -174,7 +174,7 @@ glfw_dbus_dispatch(DBusConnection *conn) {
}
void
glfw_dbus_session_bus_dispatch() {
glfw_dbus_session_bus_dispatch(void) {
if (session_bus) glfw_dbus_dispatch(session_bus);
}
@ -344,7 +344,7 @@ glfw_dbus_connect_to_session_bus(void) {
}
DBusConnection *
glfw_dbus_session_bus() {
glfw_dbus_session_bus(void) {
if (!session_bus) glfw_dbus_connect_to_session_bus();
return session_bus;
}

1
glfw/egl_context.c vendored
View File

@ -326,6 +326,7 @@ bool _glfwInitEGL(void)
glfw_dlsym(_glfw.egl.SwapBuffers, _glfw.egl.handle, "eglSwapBuffers");
glfw_dlsym(_glfw.egl.SwapInterval, _glfw.egl.handle, "eglSwapInterval");
glfw_dlsym(_glfw.egl.QueryString, _glfw.egl.handle, "eglQueryString");
glfw_dlsym(_glfw.egl.QuerySurface, _glfw.egl.handle, "eglQuerySurface");
glfw_dlsym(_glfw.egl.GetProcAddress, _glfw.egl.handle, "eglGetProcAddress");
if (!_glfw.egl.GetConfigAttrib ||

3
glfw/egl_context.h vendored
View File

@ -132,6 +132,7 @@ typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLS
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFN_eglQuerySurface)(EGLDisplay,EGLSurface,EGLint,EGLint*);
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define eglGetConfigs _glfw.egl.GetConfigs
@ -149,6 +150,7 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglSwapBuffers _glfw.egl.SwapBuffers
#define eglSwapInterval _glfw.egl.SwapInterval
#define eglQueryString _glfw.egl.QueryString
#define eglQuerySurface _glfw.egl.QuerySurface
#define eglGetProcAddress _glfw.egl.GetProcAddress
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
@ -211,6 +213,7 @@ typedef struct _GLFWlibraryEGL
PFN_eglSwapBuffers SwapBuffers;
PFN_eglSwapInterval SwapInterval;
PFN_eglQueryString QueryString;
PFN_eglQuerySurface QuerySurface;
PFN_eglGetProcAddress GetProcAddress;
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;

View File

@ -14,6 +14,10 @@ is_openbsd = 'openbsd' in _plat
base = os.path.dirname(os.path.abspath(__file__))
def null_func() -> None:
return None
class CompileKey(NamedTuple):
src: str
dest: str
@ -23,7 +27,7 @@ class Command(NamedTuple):
desc: str
cmd: Sequence[str]
is_newer_func: Callable[[], bool]
on_success: Callable[[], None] = lambda: None
on_success: Callable[[], None] = null_func
key: Optional[CompileKey] = None
keyfile: Optional[str] = None
@ -37,6 +41,7 @@ class Env:
library_paths: Dict[str, List[str]] = {}
ldpaths: List[str] = []
ccver: Tuple[int, int]
vcs_rev: str = ''
# glfw stuff
all_headers: List[str] = []
@ -48,11 +53,13 @@ class Env:
def __init__(
self, cc: List[str] = [], cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0),
vcs_rev: str = ''
):
self.cc, self.cppflags, self.cflags, self.ldflags, self.library_paths = cc, cppflags, cflags, ldflags, library_paths
self.ldpaths = ldpaths or []
self.ccver = ccver
self.vcs_rev = vcs_rev
def copy(self) -> 'Env':
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), dict(self.library_paths), list(self.ldpaths), self.ccver)
@ -62,6 +69,7 @@ class Env:
ans.wayland_scanner = self.wayland_scanner
ans.wayland_scanner_code = self.wayland_scanner_code
ans.wayland_protocols = self.wayland_protocols
ans.vcs_rev = self.vcs_rev
return ans
@ -172,6 +180,8 @@ class Arg:
while self.name.startswith('*'):
self.name = self.name[1:]
self.type = self.type + '*'
if '[' in self.name:
self.type += '[' + self.name.partition('[')[-1]
def __repr__(self) -> str:
return f'Arg({self.type}, {self.name})'
@ -252,6 +262,8 @@ def generate_wrappers(glfw_header: str) -> None:
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
void glfwSetX11WindowAsDock(int32_t x11_window_id)
void glfwSetX11WindowStrut(int32_t x11_window_id, uint32_t dimensions[12])
'''.splitlines():
if line:
functions.append(Function(line.strip(), check_fail=False))

22
glfw/glfw3.h vendored
View File

@ -1368,6 +1368,22 @@ typedef void (* GLFWwindowclosefun)(GLFWwindow*);
*/
typedef void (* GLFWapplicationclosefun)(int);
/*! @brief The function pointer type for system color theme change callbacks.
*
* This is the function pointer type for system color theme changes.
* @code
* void function_name(int theme_type)
* @endcode
*
* @param[in] theme_type 0 for unknown, 1 for dark and 2 for light
*
* @sa @ref glfwSetSystemColorThemeChangeCallback
*
* @ingroup window
*/
typedef void (* GLFWsystemcolorthemechangefun)(int);
/*! @brief The function pointer type for window content refresh callbacks.
*
* This is the function pointer type for window content refresh callbacks.
@ -1719,6 +1735,7 @@ typedef void (* GLFWtickcallback)(void*);
typedef void (* GLFWactivationcallback)(GLFWwindow *window, const char *token, void *data);
typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin);
typedef char* (* GLFWcurrentselectionfun)(void);
typedef bool (* GLFWhascurrentselectionfun)(void);
typedef void (* GLFWclipboarddatafreefun)(void* data);
typedef struct GLFWDataChunk {
const char *data;
@ -1731,6 +1748,7 @@ typedef enum {
} GLFWClipboardType;
typedef GLFWDataChunk (* GLFWclipboarditerfun)(const char *mime_type, void *iter, GLFWClipboardType ctype);
typedef bool (* GLFWclipboardwritedatafun)(void *object, const char *data, size_t sz);
typedef bool (* GLFWimecursorpositionfun)(GLFWwindow *window, GLFWIMEUpdateEvent *ev);
/*! @brief Video mode type.
*
@ -1889,6 +1907,8 @@ GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval,
GLFWAPI void glfwRemoveTimer(unsigned long long);
GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function);
GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun callback);
GLFWAPI GLFWhascurrentselectionfun glfwSetHasCurrentSelectionCallback(GLFWhascurrentselectionfun callback);
GLFWAPI GLFWimecursorpositionfun glfwSetIMECursorPositionCallback(GLFWimecursorpositionfun callback);
/*! @brief Terminates the GLFW library.
*
@ -3902,6 +3922,8 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
*/
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback);
GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback);
GLFWAPI GLFWsystemcolorthemechangefun glfwSetSystemColorThemeChangeCallback(GLFWsystemcolorthemechangefun callback);
GLFWAPI int glfwGetCurrentSystemColorTheme(void);
/*! @brief Sets the refresh callback for the specified window.
*

34
glfw/ibus_glfw.c vendored
View File

@ -283,29 +283,35 @@ static const char*
get_ibus_address_file_name(void) {
const char *addr;
static char ans[PATH_MAX];
static char display[64] = {0};
addr = getenv("IBUS_ADDRESS");
int offset = 0;
if (addr && addr[0]) {
memcpy(ans, addr, GLFW_MIN(strlen(addr), sizeof(ans)));
return ans;
}
const char* disp_num = NULL;
const char *host = "unix";
// See https://github.com/ibus/ibus/commit/8ce25208c3f4adfd290a032c6aa739d2b7580eb1 for why we need this dance.
const char *de = getenv("WAYLAND_DISPLAY");
if (de) {
disp_num = de;
} else {
const char *de = getenv("DISPLAY");
if (!de || !de[0]) de = ":0.0";
char *display = _glfw_strdup(de);
const char *host = display;
char *disp_num = strrchr(display, ':');
char *screen_num = strrchr(display, '.');
if (!disp_num) {
strncpy(display, de, sizeof(display) - 1);
char *dnum = strrchr(display, ':');
if (!dnum) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Could not get IBUS address file name as DISPLAY env var has no colon");
free(display);
return NULL;
}
*disp_num = 0;
disp_num++;
char *screen_num = strrchr(display, '.');
*dnum = 0;
dnum++;
if (screen_num) *screen_num = 0;
if (!*host) host = "unix";
if (*display) host = display;
disp_num = dnum;
}
memset(ans, 0, sizeof(ans));
const char *conf_env = getenv("XDG_CONFIG_HOME");
@ -315,7 +321,6 @@ get_ibus_address_file_name(void) {
conf_env = getenv("HOME");
if (!conf_env || !conf_env[0]) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Could not get IBUS address file name as no HOME env var is set");
free(display);
return NULL;
}
offset = snprintf(ans, sizeof(ans), "%s/.config", conf_env);
@ -323,7 +328,6 @@ get_ibus_address_file_name(void) {
char *key = dbus_get_local_machine_id();
snprintf(ans + offset, sizeof(ans) - offset, "/ibus/bus/%s-%s-%s", key, host, disp_num);
dbus_free(key);
free(display);
return ans;
}
@ -383,12 +387,12 @@ input_context_created(DBusMessage *msg, const char* errmsg, void *data) {
enum Capabilities caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
if (!glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return;
ibus->ok = true;
glfw_ibus_set_focused(ibus, false);
glfw_ibus_set_focused(ibus, _glfwFocusedWindow() != NULL);
glfw_ibus_set_cursor_geometry(ibus, 0, 0, 0, 0);
debug("Connected to IBUS daemon for IME input management\n");
}
bool
static bool
setup_connection(_GLFWIBUSData *ibus) {
const char *client_name = "GLFW_Application";
const char *address_file_name = get_ibus_address_file_name();

22
glfw/init.c vendored
View File

@ -382,6 +382,14 @@ GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationc
return cbfun;
}
GLFWAPI GLFWapplicationclosefun glfwSetSystemColorThemeChangeCallback(GLFWsystemcolorthemechangefun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.system_color_theme_change, cbfun);
return cbfun;
}
GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -395,3 +403,17 @@ GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselec
_GLFW_SWAP_POINTERS(_glfw.callbacks.get_current_selection, cbfun);
return cbfun;
}
GLFWAPI GLFWhascurrentselectionfun glfwSetHasCurrentSelectionCallback(GLFWhascurrentselectionfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.has_current_selection, cbfun);
return cbfun;
}
GLFWAPI GLFWimecursorpositionfun glfwSetIMECursorPositionCallback(GLFWimecursorpositionfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.get_ime_cursor_position, cbfun);
return cbfun;
}

4
glfw/internal.h vendored
View File

@ -632,11 +632,13 @@ struct _GLFWlibrary
GLFWmonitorfun monitor;
GLFWjoystickfun joystick;
GLFWapplicationclosefun application_close;
GLFWsystemcolorthemechangefun system_color_theme_change;
GLFWdrawtextfun draw_text;
GLFWcurrentselectionfun get_current_selection;
GLFWhascurrentselectionfun has_current_selection;
GLFWimecursorpositionfun get_ime_cursor_position;
} callbacks;
// This is defined in the window API's platform.h
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
// This is defined in the context API's context.h

View File

@ -24,6 +24,11 @@ static uint32_t appearance = 0;
static bool is_gnome = false;
static bool cursor_theme_changed = false;
int
glfw_current_system_color_theme(void) {
return appearance;
}
#define HANDLER(name) static void name(DBusMessage *msg, const char* errmsg, void *data) { \
(void)data; \
if (errmsg) { \
@ -155,6 +160,9 @@ on_color_scheme_change(DBusMessage *message) {
if (val > 2) val = 0;
if (val != appearance) {
appearance = val;
if (_glfw.callbacks.system_color_theme_change) {
_glfw.callbacks.system_color_theme_change(appearance);
}
}
}
break;

View File

@ -12,3 +12,4 @@
void glfw_initialize_desktop_settings(void);
void glfw_current_cursor_theme(const char **theme, int *size);
int glfw_current_system_color_theme(void);

View File

@ -104,9 +104,10 @@ init_buffer_pair(_GLFWWaylandBufferPair *pair, size_t width, size_t height, unsi
static bool
window_has_buffer(_GLFWwindow *window, struct wl_buffer *q) {
#define Q(which) decs.which.buffer.a == q || decs.which.buffer.b == q
return Q(left) || Q(top) || Q(right) || Q(bottom);
#define Q(which) if (decs.which.buffer.a == q) { decs.which.buffer.a_needs_to_be_destroyed = false; return true; } if (decs.which.buffer.b == q) { decs.which.buffer.b_needs_to_be_destroyed = false; return true; }
Q(left); Q(top); Q(right); Q(bottom);
#undef Q
return false;
}
static void
@ -122,10 +123,12 @@ static void
alloc_buffer_pair(uintptr_t window_id, _GLFWWaylandBufferPair *pair, struct wl_shm_pool *pool, uint8_t *data, size_t *offset) {
pair->data.a = data + *offset;
pair->a = wl_shm_pool_create_buffer(pool, *offset, pair->width, pair->height, pair->stride, WL_SHM_FORMAT_ARGB8888);
pair->a_needs_to_be_destroyed = true;
wl_buffer_add_listener(pair->a, &handle_buffer_events, (void*)window_id);
*offset += pair->size_in_bytes;
pair->data.b = data + *offset;
pair->b = wl_shm_pool_create_buffer(pool, *offset, pair->width, pair->height, pair->stride, WL_SHM_FORMAT_ARGB8888);
pair->b_needs_to_be_destroyed = true;
wl_buffer_add_listener(pair->b, &handle_buffer_events, (void*)window_id);
*offset += pair->size_in_bytes;
pair->front = pair->a; pair->back = pair->b;
@ -331,6 +334,8 @@ free_csd_surfaces(_GLFWwindow *window) {
static void
free_csd_buffers(_GLFWwindow *window) {
#define d(which) { \
if (decs.which.buffer.a_needs_to_be_destroyed && decs.which.buffer.a) wl_buffer_destroy(decs.which.buffer.a); \
if (decs.which.buffer.b_needs_to_be_destroyed && decs.which.buffer.b) wl_buffer_destroy(decs.which.buffer.b); \
memset(&decs.which.buffer, 0, sizeof(_GLFWWaylandBufferPair)); \
}
d(left); d(top); d(right); d(bottom);
@ -353,9 +358,10 @@ create_csd_surfaces(_GLFWwindow *window, _GLFWWaylandCSDEdge *s) {
}
#define damage_csd(which, xbuffer) \
wl_surface_attach(decs.which.surface, xbuffer, 0, 0); \
wl_surface_attach(decs.which.surface, (xbuffer), 0, 0); \
wl_surface_damage(decs.which.surface, 0, 0, decs.which.buffer.width, decs.which.buffer.height); \
wl_surface_commit(decs.which.surface)
wl_surface_commit(decs.which.surface); \
if (decs.which.buffer.a == (xbuffer)) { decs.which.buffer.a_needs_to_be_destroyed = false; } else { decs.which.buffer.b_needs_to_be_destroyed = false; }
bool
ensure_csd_resources(_GLFWwindow *window) {
@ -450,8 +456,5 @@ set_titlebar_color(_GLFWwindow *window, uint32_t color, bool use_system_color) {
decs.use_custom_titlebar_color = use_custom_color;
decs.titlebar_color = color;
}
if (window->decorated && decs.top.surface) {
update_title_bar(window);
damage_csd(top, decs.top.buffer.front);
}
change_csd_title(window);
}

4
glfw/wl_init.c vendored
View File

@ -789,6 +789,10 @@ glfwWaylandCheckForServerSideDecorations(void) {
return has_ssd ? "YES" : "NO";
}
GLFWAPI int glfwGetCurrentSystemColorTheme(void) {
return glfw_current_system_color_theme();
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////

3
glfw/wl_platform.h vendored
View File

@ -104,6 +104,7 @@ typedef struct _GLFWWaylandBufferPair {
struct { uint8_t *a, *b, *front, *back; } data;
bool has_pending_update;
size_t size_in_bytes, width, height, stride;
bool a_needs_to_be_destroyed, b_needs_to_be_destroyed;
} _GLFWWaylandBufferPair;
typedef struct _GLFWWaylandCSDEdge {
@ -151,6 +152,7 @@ typedef struct _GLFWwindowWayland
bool hovered;
bool transparent;
struct wl_surface* surface;
bool waiting_for_swap_to_commit;
struct wl_egl_window* native;
struct wl_callback* callback;
@ -368,6 +370,7 @@ typedef struct _GLFWcursorWayland
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
void _glfwWaylandAfterBufferSwap(_GLFWwindow *window);
void _glfwSetupWaylandDataDevice(void);
void _glfwSetupWaylandPrimarySelectionDevice(void);
void animateCursorImage(id_type timer_id, void *data);

27
glfw/wl_text_input.c vendored
View File

@ -9,12 +9,15 @@
#include "internal.h"
#include "wayland-text-input-unstable-v3-client-protocol.h"
#include <stdlib.h>
#include <string.h>
#define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__);
static struct zwp_text_input_v3* text_input;
static struct zwp_text_input_manager_v3* text_input_manager;
static char *pending_pre_edit = NULL;
static char *current_pre_edit = NULL;
static char *pending_commit = NULL;
static int last_cursor_left = 0, last_cursor_top = 0, last_cursor_width = 0, last_cursor_height = 0;
uint32_t commit_serial = 0;
static void commit(void) {
@ -90,13 +93,21 @@ text_input_done(void *data UNUSED, struct zwp_text_input_v3 *txt_input UNUSED, u
if (serial > commit_serial) _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: text_input_done serial mismatch, expected=%u got=%u\n", commit_serial, serial);
return;
}
if (pending_pre_edit) {
send_text(pending_pre_edit, GLFW_IME_PREEDIT_CHANGED);
if ((pending_pre_edit == NULL && current_pre_edit == NULL) ||
(pending_pre_edit && current_pre_edit && strcmp(pending_pre_edit, current_pre_edit) == 0)) {
free(pending_pre_edit); pending_pre_edit = NULL;
} else {
free(current_pre_edit);
current_pre_edit = pending_pre_edit;
pending_pre_edit = NULL;
if (current_pre_edit) {
send_text(current_pre_edit, GLFW_IME_PREEDIT_CHANGED);
} else {
// Clear pre-edit text
send_text(NULL, GLFW_IME_WAYLAND_DONE_EVENT);
}
}
if (pending_commit) {
send_text(pending_commit, GLFW_IME_COMMIT_TEXT);
free(pending_commit); pending_commit = NULL;
@ -133,6 +144,7 @@ _glfwWaylandDestroyTextInput(void) {
if (text_input_manager) zwp_text_input_manager_v3_destroy(text_input_manager);
text_input = NULL; text_input_manager = NULL;
free(pending_pre_edit); pending_pre_edit = NULL;
free(current_pre_edit); current_pre_edit = NULL;
free(pending_commit); pending_commit = NULL;
}
@ -146,10 +158,11 @@ _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
zwp_text_input_v3_enable(text_input);
zwp_text_input_v3_set_content_type(text_input, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL);
} else {
if (pending_pre_edit) {
free(pending_pre_edit); pending_pre_edit = NULL;
if (current_pre_edit) {
// Clear pre-edit text
send_text(NULL, GLFW_IME_PREEDIT_CHANGED);
free(pending_pre_edit); pending_pre_edit = NULL;
free(current_pre_edit); current_pre_edit = NULL;
}
if (pending_commit) {
free(pending_commit); pending_commit = NULL;
@ -161,10 +174,16 @@ _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
case GLFW_IME_UPDATE_CURSOR_POSITION: {
const int scale = w->wl.scale;
const int left = ev->cursor.left / scale, top = ev->cursor.top / scale, width = ev->cursor.width / scale, height = ev->cursor.height / scale;
if (left != last_cursor_left || top != last_cursor_top || width != last_cursor_width || height != last_cursor_height) {
last_cursor_left = left;
last_cursor_top = top;
last_cursor_width = width;
last_cursor_height = height;
debug("\ntext-input: updating cursor position: left=%d top=%d width=%d height=%d\n", left, top, width, height);
zwp_text_input_v3_set_cursor_rectangle(text_input, left, top, width, height);
commit();
}
}
break;
}
}

103
glfw/wl_window.c vendored
View File

@ -75,7 +75,7 @@ get_activation_token(
if (token == NULL) fail("Wayland: failed to create activation request token");
if (_glfw.wl.activation_requests.capacity < _glfw.wl.activation_requests.sz + 1) {
_glfw.wl.activation_requests.capacity = MAX(64u, _glfw.wl.activation_requests.capacity * 2);
_glfw.wl.activation_requests.array = realloc(_glfw.wl.activation_requests.array, _glfw.wl.activation_requests.capacity);
_glfw.wl.activation_requests.array = realloc(_glfw.wl.activation_requests.array, _glfw.wl.activation_requests.capacity * sizeof(_glfw.wl.activation_requests.array[0]));
if (!_glfw.wl.activation_requests.array) {
_glfw.wl.activation_requests.capacity = 0;
fail("Wayland: Out of memory while allocation activation request");
@ -251,6 +251,15 @@ static bool checkScaleChange(_GLFWwindow* window)
return false;
}
static void
commit_window_surface_if_safe(_GLFWwindow *window) {
// we only commit if the buffer attached to the surface is the correct size,
// which means that at least one frame is drawn after resizeFramebuffer()
if (!window->wl.waiting_for_swap_to_commit) {
wl_surface_commit(window->wl.surface);
}
}
// Makes the surface considered as XRGB instead of ARGB.
static void setOpaqueRegion(_GLFWwindow* window, bool commit_surface)
{
@ -262,22 +271,10 @@ static void setOpaqueRegion(_GLFWwindow* window, bool commit_surface)
wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
wl_surface_set_opaque_region(window->wl.surface, region);
if (commit_surface) wl_surface_commit(window->wl.surface);
if (commit_surface) commit_window_surface_if_safe(window);
wl_region_destroy(region);
}
static void
swap_buffers(_GLFWwindow *window) {
// this will attach the buffer to the surface,
// the client is responsible for clearing the buffer to an appropriate blank
window->swaps_disallowed = false;
GLFWwindow *current = glfwGetCurrentContext();
bool context_is_current = ((_GLFWwindow*)current)->id == window->id;
if (!context_is_current) glfwMakeContextCurrent((GLFWwindow*)window);
window->context.swapBuffers(window);
if (!context_is_current) glfwMakeContextCurrent(current);
}
static void
resizeFramebuffer(_GLFWwindow* window) {
@ -287,9 +284,20 @@ resizeFramebuffer(_GLFWwindow* window) {
debug("Resizing framebuffer to: %dx%d at scale: %d\n", window->wl.width, window->wl.height, scale);
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
if (!window->wl.transparent) setOpaqueRegion(window, false);
window->wl.waiting_for_swap_to_commit = true;
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
}
void
_glfwWaylandAfterBufferSwap(_GLFWwindow* window) {
if (window->wl.waiting_for_swap_to_commit) {
debug("Waiting for swap to commit: swap has happened\n");
window->wl.waiting_for_swap_to_commit = false;
// this is not really needed, since I think eglSwapBuffers() calls wl_surface_commit()
// but lets be safe. See https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/egl/drivers/dri2/platform_wayland.c#L1510
wl_surface_commit(window->wl.surface);
}
}
static const char*
clipboard_mime(void) {
@ -301,9 +309,9 @@ clipboard_mime(void) {
}
static bool
dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height, bool *scale_changed) {
dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height) {
bool size_changed = width != window->wl.width || height != window->wl.height;
*scale_changed = checkScaleChange(window);
bool scale_changed = checkScaleChange(window);
if (size_changed) {
_glfwInputWindowSize(window, width, height);
@ -311,7 +319,7 @@ dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height
resizeFramebuffer(window);
}
if (*scale_changed) {
if (scale_changed) {
debug("Scale changed to %d in dispatchChangesAfterConfigure\n", window->wl.scale);
if (!size_changed) resizeFramebuffer(window);
_glfwInputWindowContentScale(window, window->wl.scale, window->wl.scale);
@ -319,7 +327,7 @@ dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height
_glfwInputWindowDamage(window);
return size_changed || *scale_changed;
return size_changed || scale_changed;
}
static void
@ -568,6 +576,15 @@ static void xdgSurfaceHandleConfigure(void* data,
struct xdg_surface* surface,
uint32_t serial)
{
// The poorly documented pattern Wayland requires is:
// 1) ack the configure,
// 2) set the window geometry
// 3) attach a new buffer of the correct size to the surface
// 4) only then commit the surface.
// buffer is attached only by eglSwapBuffers,
// so we set a flag to not commit the surface till the next swapbuffers. Note that
// wl_egl_window_resize() does not actually resize the buffer until the next draw call
// or buffer state query.
_GLFWwindow* window = data;
xdg_surface_ack_configure(surface, serial);
if (window->wl.pending_state & PENDING_STATE_TOPLEVEL) {
@ -575,8 +592,9 @@ static void xdgSurfaceHandleConfigure(void* data,
int width = window->wl.pending.width;
int height = window->wl.pending.height;
if (!window->wl.surface_configured_once) {
window->swaps_disallowed = false;
window->wl.waiting_for_swap_to_commit = true;
window->wl.surface_configured_once = true;
swap_buffers(window);
}
if (new_states != window->wl.current.toplevel_states ||
@ -599,13 +617,11 @@ static void xdgSurfaceHandleConfigure(void* data,
window->wl.current.decoration_mode = mode;
}
bool resized = false;
bool scale_changed = false;
if (window->wl.pending_state) {
int width = window->wl.pending.width, height = window->wl.pending.height;
set_csd_window_geometry(window, &width, &height);
resized = dispatchChangesAfterConfigure(window, width, height, &scale_changed);
if (window->wl.decorations.serverSide) {
bool resized = dispatchChangesAfterConfigure(window, width, height);
if (window->wl.decorations.serverSide || window->monitor || window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN) {
free_csd_surfaces(window);
} else {
ensure_csd_resources(window);
@ -614,14 +630,7 @@ static void xdgSurfaceHandleConfigure(void* data,
}
inform_compositor_of_window_geometry(window, "configure");
// we need to swap buffers here to ensure the buffer attached to the surface is a multiple
// of the new scale. See https://github.com/kovidgoyal/kitty/issues/5467
if (scale_changed) swap_buffers(window);
// if a resize happened there will be a commit at the next render frame so
// dont commit here, GNOME doesnt like it and its not really needed anyway
if (!resized) wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
window->wl.pending_state = 0;
}
@ -1021,7 +1030,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
window->wl.width = w; window->wl.height = h;
resizeFramebuffer(window);
ensure_csd_resources(window);
wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
inform_compositor_of_window_geometry(window, "SetWindowSize");
}
}
@ -1038,7 +1047,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
maxwidth = maxheight = 0;
xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
}
}
@ -1273,7 +1282,7 @@ void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, bool enabled)
}
else
wl_surface_set_input_region(window->wl.surface, 0);
wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
@ -1337,7 +1346,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
zwp_locked_pointer_v1_set_cursor_position_hint(
window->wl.pointerLock.lockedPointer,
wl_fixed_from_double(x), wl_fixed_from_double(y));
wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
}
}
@ -1629,7 +1638,7 @@ write_chunk(void *object, const char *data, size_t sz) {
chunked_writer *cw = object;
if (cw->cap < cw->sz + sz) {
cw->cap = MAX(cw->cap * 2, cw->sz + 8*sz);
cw->buf = realloc(cw->buf, cw->cap);
cw->buf = realloc(cw->buf, cw->cap * sizeof(cw->buf[0]));
}
memcpy(cw->buf + cw->sz, data, sz);
cw->sz += sz;
@ -1691,9 +1700,18 @@ static void primary_selection_source_canceled(void *data UNUSED, struct zwp_prim
zwp_primary_selection_source_v1_destroy(primary_selection_source);
}
// KWin aborts if we don't define these even though they are not used for copy/paste
static void dummy_data_source_target(void* data UNUSED, struct wl_data_source* wl_data_source UNUSED, const char* mime_type UNUSED) {
}
static void dummy_data_source_action(void* data UNUSED, struct wl_data_source* wl_data_source UNUSED, uint dnd_action UNUSED) {
}
static const struct wl_data_source_listener data_source_listener = {
.send = _glfwSendClipboardText,
.cancelled = data_source_canceled,
.target = dummy_data_source_target,
.action = dummy_data_source_action,
};
static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
@ -1934,12 +1952,12 @@ primary_selection_copy_callback_done(void *data, struct wl_callback *callback, u
wl_callback_destroy(callback);
}
void _glfwSetupWaylandDataDevice() {
void _glfwSetupWaylandDataDevice(void) {
_glfw.wl.dataDevice = wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, _glfw.wl.seat);
if (_glfw.wl.dataDevice) wl_data_device_add_listener(_glfw.wl.dataDevice, &data_device_listener, NULL);
}
void _glfwSetupWaylandPrimarySelectionDevice() {
void _glfwSetupWaylandPrimarySelectionDevice(void) {
_glfw.wl.primarySelectionDevice = zwp_primary_selection_device_manager_v1_get_device(_glfw.wl.primarySelectionDeviceManager, _glfw.wl.seat);
if (_glfw.wl.primarySelectionDevice) zwp_primary_selection_device_v1_add_listener(_glfw.wl.primarySelectionDevice, &primary_selection_device_listener, NULL);
}
@ -2232,12 +2250,19 @@ GLFWAPI void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long
_GLFWwindow* window = (_GLFWwindow*) handle;
static const struct wl_callback_listener frame_listener = { .done = frame_handle_redraw };
if (window->wl.frameCallbackData.current_wl_callback) wl_callback_destroy(window->wl.frameCallbackData.current_wl_callback);
if (window->wl.waiting_for_swap_to_commit) {
callback(id);
window->wl.frameCallbackData.id = 0;
window->wl.frameCallbackData.callback = NULL;
window->wl.frameCallbackData.current_wl_callback = NULL;
} else {
window->wl.frameCallbackData.id = id;
window->wl.frameCallbackData.callback = callback;
window->wl.frameCallbackData.current_wl_callback = wl_surface_frame(window->wl.surface);
if (window->wl.frameCallbackData.current_wl_callback) {
wl_callback_add_listener(window->wl.frameCallbackData.current_wl_callback, &frame_listener, window);
wl_surface_commit(window->wl.surface);
commit_window_surface_if_safe(window);
}
}
}

8
glfw/x11_init.c vendored
View File

@ -137,6 +137,8 @@ static void detectEWMH(void)
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
_glfw.x11.NET_WM_WINDOW_TYPE_DOCK =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_DOCK");
_glfw.x11.NET_WORKAREA =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");
_glfw.x11.NET_CURRENT_DESKTOP =
@ -147,6 +149,8 @@ static void detectEWMH(void)
getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
_glfw.x11.NET_WM_STRUT_PARTIAL =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STRUT_PARTIAL");
XFree(supportedAtoms);
}
@ -610,6 +614,10 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetCurrentSystemColorTheme(void) {
return 0;
}
int _glfwPlatformInit(void)
{
XInitThreads();

2
glfw/x11_platform.h vendored
View File

@ -253,6 +253,7 @@ typedef struct _GLFWlibraryX11
Atom NET_WM_PING;
Atom NET_WM_WINDOW_TYPE;
Atom NET_WM_WINDOW_TYPE_NORMAL;
Atom NET_WM_WINDOW_TYPE_DOCK;
Atom NET_WM_STATE;
Atom NET_WM_STATE_ABOVE;
Atom NET_WM_STATE_FULLSCREEN;
@ -268,6 +269,7 @@ typedef struct _GLFWlibraryX11
Atom NET_ACTIVE_WINDOW;
Atom NET_FRAME_EXTENTS;
Atom NET_REQUEST_FRAME_EXTENTS;
Atom NET_WM_STRUT_PARTIAL;
Atom MOTIF_WM_HINTS;
// Xdnd (drag and drop) atoms

44
glfw/x11_window.c vendored
View File

@ -719,6 +719,7 @@ static bool createNativeWindow(_GLFWwindow* window,
static size_t
get_clipboard_data(const _GLFWClipboardData *cd, const char *mime, char **data) {
*data = NULL;
if (cd->get_data == NULL) { return 0; }
GLFWDataChunk chunk = cd->get_data(mime, NULL, cd->ctype);
char *buf = NULL;
size_t sz = 0, cap = 0;
@ -729,7 +730,7 @@ get_clipboard_data(const _GLFWClipboardData *cd, const char *mime, char **data)
if (!chunk.sz) break;
if (cap < sz + chunk.sz) {
cap = MAX(cap * 2, sz + 4 * chunk.sz);
buf = realloc(buf, cap);
buf = realloc(buf, cap * sizeof(buf[0]));
}
memcpy(buf + sz, chunk.data, chunk.sz);
sz += chunk.sz;
@ -793,7 +794,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
32,
PropModeReplace,
(unsigned char*) targets,
sizeof(targets[0]) * (aa->sz + 2));
aa->sz + 2);
free(targets);
return request->property;
}
@ -1033,7 +1034,7 @@ getSelectionString(Atom selection, Atom *targets, size_t num_targets, GLFWclipbo
}
else if (actualType == XA_ATOM && targets[i] == _glfw.x11.TARGETS) {
found = true;
write_data(object, data, itemCount);
write_data(object, data, sizeof(Atom) * itemCount);
}
XFREE(data);
@ -2861,7 +2862,7 @@ static MimeAtom atom_for_mime(const char *mime) {
MimeAtom ma = {.mime=_glfw_strdup(mime), .atom=XInternAtom(_glfw.x11.display, mime, 0)};
if (_glfw.x11.mime_atoms.capacity < _glfw.x11.mime_atoms.sz + 1) {
_glfw.x11.mime_atoms.capacity += 32;
_glfw.x11.mime_atoms.array = realloc(_glfw.x11.mime_atoms.array, _glfw.x11.mime_atoms.capacity);
_glfw.x11.mime_atoms.array = realloc(_glfw.x11.mime_atoms.array, _glfw.x11.mime_atoms.capacity * sizeof(_glfw.x11.mime_atoms.array[0]));
}
_glfw.x11.mime_atoms.array[_glfw.x11.mime_atoms.sz++] = ma;
return ma;
@ -2881,7 +2882,7 @@ void _glfwPlatformSetClipboard(GLFWClipboardType t) {
}
if (aa->capacity < cd->num_mime_types + 32) {
aa->capacity = cd->num_mime_types + 32;
aa->array = malloc(sizeof(aa->array[0]) * aa->capacity);
aa->array = reallocarray(aa->array, aa->capacity, sizeof(aa->array[0]));
}
aa->sz = 0;
for (size_t i = 0; i < cd->num_mime_types; i++) {
@ -2897,17 +2898,20 @@ void _glfwPlatformSetClipboard(GLFWClipboardType t) {
typedef struct chunked_writer {
char *buf; size_t sz, cap;
bool is_self_offer;
} chunked_writer;
static bool
write_chunk(void *object, const char *data, size_t sz) {
chunked_writer *cw = object;
if (data) {
if (cw->cap < cw->sz + sz) {
cw->cap = MAX(cw->cap * 2, cw->sz + 8*sz);
cw->buf = realloc(cw->buf, cw->cap);
cw->buf = realloc(cw->buf, cw->cap * sizeof(cw->buf[0]));
}
memcpy(cw->buf + cw->sz, data, sz);
cw->sz += sz;
} else if (sz == 1) cw->is_self_offer = true;
return true;
}
@ -2915,6 +2919,10 @@ static void
get_available_mime_types(Atom which_clipboard, GLFWclipboardwritedatafun write_data, void *object) {
chunked_writer cw = {0};
getSelectionString(which_clipboard, &_glfw.x11.TARGETS, 1, write_chunk, &cw, false);
if (cw.is_self_offer) {
write_data(object, NULL, 1);
return;
}
size_t count = 0;
bool ok = true;
if (cw.buf) {
@ -2945,10 +2953,17 @@ _glfwPlatformGetClipboard(GLFWClipboardType clipboard_type, const char* mime_typ
return;
}
size_t count = 0;
atoms[count++] = atom_for_mime(mime_type).atom;
if (strcmp(mime_type, "text/plain") == 0) {
// UTF8_STRING is what xclip uses by default, and there are people out there that expect to be able to paste from it with a single read operation. See https://github.com/kovidgoyal/kitty/issues/5842
// Also ancient versions of GNOME use DOS line endings even for text/plain;charset=utf-8. See https://github.com/kovidgoyal/kitty/issues/5528#issuecomment-1325348218
atoms[count++] = _glfw.x11.UTF8_STRING;
// we need to do this because GTK/GNOME is moronic they convert text/plain to DOS line endings, see
// https://gitlab.gnome.org/GNOME/gtk/-/issues/2307
atoms[count++] = atom_for_mime("text/plain;charset=utf-8").atom;
atoms[count++] = atom_for_mime("text/plain").atom;
atoms[count++] = XA_STRING;
} else {
atoms[count++] = atom_for_mime(mime_type).atom;
}
getSelectionString(which, atoms, count, write_data, object, true);
}
@ -3191,3 +3206,18 @@ GLFWAPI int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
_GLFWwindow* window = (_GLFWwindow*) handle;
return XSetCommand(_glfw.x11.display, window->x11.handle, argv, argc);
}
GLFWAPI void glfwSetX11WindowAsDock(int32_t x11_window_id) {
_GLFW_REQUIRE_INIT();
Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_DOCK;
XChangeProperty(_glfw.x11.display, x11_window_id,
_glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &type, 1);
}
GLFWAPI void glfwSetX11WindowStrut(int32_t x11_window_id, uint32_t dimensions[12]) {
_GLFW_REQUIRE_INIT();
XChangeProperty(_glfw.x11.display, x11_window_id,
_glfw.x11.NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) dimensions, 12);
}

30
go.mod Normal file
View File

@ -0,0 +1,30 @@
module kitty
go 1.20
require (
github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924
github.com/alecthomas/chroma/v2 v2.7.0
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/disintegration/imaging v1.6.2
github.com/dlclark/regexp2 v1.9.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f
github.com/seancfoley/ipaddress-go v1.5.4
github.com/shirou/gopsutil/v3 v3.23.3
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/image v0.7.0
golang.org/x/sys v0.7.0
)
require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/seancfoley/bintree v1.2.1 // indirect
github.com/shoenig/go-m1cpu v0.1.5 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
)

104
go.sum Normal file
View File

@ -0,0 +1,104 @@
github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 h1:DG4UyTVIujioxwJc8Zj8Nabz1L1wTgQ/xNBSQDfdP3I=
github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4=
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
github.com/alecthomas/chroma/v2 v2.7.0 h1:hm1rY6c/Ob4eGclpQ7X/A3yhqBOZNUTk9q+yhyLIViI=
github.com/alecthomas/chroma/v2 v2.7.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.9.0 h1:pTK/l/3qYIKaRXuHnEnIf7Y5NxfRPfpb7dis6/gdlVI=
github.com/dlclark/regexp2 v1.9.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f h1:Ko4+g6K16vSyUrtd/pPXuQnWsiHe5BYptEtTxfwYwCc=
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f/go.mod h1:eHzfhOKbTGJEGPSdMHzU6jft192tHHt2Bu2vIZArvC0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik=
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/seancfoley/bintree v1.2.1 h1:Z/iNjRKkXnn0CTW7jDQYtjW5fz2GH1yWvOTJ4MrMvdo=
github.com/seancfoley/bintree v1.2.1/go.mod h1:hIUabL8OFYyFVTQ6azeajbopogQc2l5C/hiXMcemWNU=
github.com/seancfoley/ipaddress-go v1.5.4 h1:ZdjewWC1J2y5ruQjWHwK6rA1tInWB6mz1ftz6uTm+Uw=
github.com/seancfoley/ipaddress-go v1.5.4/go.mod h1:fpvVPC+Jso+YEhNcNiww8HQmBgKP8T4T6BTp1SLxxIo=
github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ=
github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

433
kittens/ask/choices.go Normal file
View File

@ -0,0 +1,433 @@
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
package ask
import (
"fmt"
"io"
"kitty/tools/cli/markup"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/style"
"kitty/tools/wcswidth"
"os"
"regexp"
"strings"
"unicode"
)
var _ = fmt.Print
type Choice struct {
text string
idx int
color, letter string
}
func (self Choice) prefix() string {
return string([]rune(self.text)[:self.idx])
}
func (self Choice) display_letter() string {
return string([]rune(self.text)[self.idx])
}
func (self Choice) suffix() string {
return string([]rune(self.text)[self.idx+1:])
}
type Range struct {
start, end, y int
}
func (self *Range) has_point(x, y int) bool {
return y == self.y && self.start <= x && x <= self.end
}
func truncate_at_space(text string, width int) (string, string) {
truncated, p := wcswidth.TruncateToVisualLengthWithWidth(text, width)
if len(truncated) == len(text) {
return text, ""
}
i := strings.LastIndexByte(truncated, ' ')
if i > 0 && p-i < 12 {
p = i + 1
}
return text[:p], text[p:]
}
func extra_for(width, screen_width int) int {
return utils.Max(0, screen_width-width)/2 + 1
}
func GetChoices(o *Options) (response string, err error) {
response = ""
lp, err := loop.New()
if err != nil {
return "", err
}
lp.MouseTrackingMode(loop.BUTTONS_ONLY_MOUSE_TRACKING)
prefix_style_pat := regexp.MustCompile("^(?:\x1b\\[[^m]*?m)+")
choice_order := make([]Choice, 0, len(o.Choices))
clickable_ranges := make(map[string][]Range, 16)
allowed := utils.NewSet[string](utils.Max(2, len(o.Choices)))
response_on_accept := o.Default
switch o.Type {
case "yesno":
allowed.AddItems("y", "n")
if !allowed.Has(response_on_accept) {
response_on_accept = "y"
}
case "choices":
first_choice := ""
for i, x := range o.Choices {
letter, text, _ := strings.Cut(x, ":")
color := ""
if strings.Contains(letter, ";") {
letter, color, _ = strings.Cut(letter, ";")
}
letter = strings.ToLower(letter)
idx := strings.Index(strings.ToLower(text), letter)
idx = len([]rune(strings.ToLower(text)[:idx]))
allowed.Add(letter)
c := Choice{text: text, idx: idx, color: color, letter: letter}
choice_order = append(choice_order, c)
if i == 0 {
first_choice = letter
}
}
if !allowed.Has(response_on_accept) {
response_on_accept = first_choice
}
}
message := o.Message
hidden_text_start_pos := -1
hidden_text_end_pos := -1
hidden_text := ""
m := markup.New(true)
replacement_text := fmt.Sprintf("Press %s or click to show", m.Green(o.UnhideKey))
replacement_range := Range{-1, -1, -1}
if message != "" && o.HiddenTextPlaceholder != "" {
hidden_text_start_pos = strings.Index(message, o.HiddenTextPlaceholder)
if hidden_text_start_pos > -1 {
raw, err := io.ReadAll(os.Stdin)
if err != nil {
return "", fmt.Errorf("Failed to read hidden text from STDIN: %w", err)
}
hidden_text = strings.TrimRightFunc(utils.UnsafeBytesToString(raw), unicode.IsSpace)
hidden_text_end_pos = hidden_text_start_pos + len(replacement_text)
suffix := message[hidden_text_start_pos+len(o.HiddenTextPlaceholder):]
message = message[:hidden_text_start_pos] + replacement_text + suffix
}
}
draw_long_text := func(screen_width int, text string, msg_lines []string) []string {
if text == "" {
msg_lines = append(msg_lines, "")
} else {
width := screen_width - 2
prefix := prefix_style_pat.FindString(text)
for text != "" {
var t string
t, text = truncate_at_space(text, width)
t = strings.TrimSpace(t)
msg_lines = append(msg_lines, strings.Repeat(" ", extra_for(wcswidth.Stringwidth(t), width))+m.Bold(prefix+t))
}
}
return msg_lines
}
ctx := style.Context{AllowEscapeCodes: true}
draw_choice_boxes := func(y, screen_width, screen_height int, choices ...Choice) {
clickable_ranges = map[string][]Range{}
width := screen_width - 2
current_line_length := 0
type Item struct{ letter, text string }
type Line = []Item
var current_line Line
lines := make([]Line, 0, 32)
sep := " "
sep_sz := len(sep) + 2 // for the borders
for _, choice := range choices {
clickable_ranges[choice.letter] = make([]Range, 0, 4)
text := " " + choice.prefix()
color := choice.color
if choice.color == "" {
color = "green"
}
text += ctx.SprintFunc("fg=" + color)(choice.display_letter())
text += choice.suffix() + " "
sz := wcswidth.Stringwidth(text)
if sz+sep_sz+current_line_length > width {
lines = append(lines, current_line)
current_line = nil
current_line_length = 0
}
current_line = append(current_line, Item{choice.letter, text})
current_line_length += sz + sep_sz
}
if len(current_line) > 0 {
lines = append(lines, current_line)
}
highlight := func(text string) string {
return m.Yellow(text)
}
top := func(text string, highlight_frame bool) (ans string) {
ans = "╭" + strings.Repeat("─", wcswidth.Stringwidth(text)) + "╮"
if highlight_frame {
ans = highlight(ans)
}
return
}
middle := func(text string, highlight_frame bool) (ans string) {
f := "│"
if highlight_frame {
f = highlight(f)
}
return f + text + f
}
bottom := func(text string, highlight_frame bool) (ans string) {
ans = "╰" + strings.Repeat("─", wcswidth.Stringwidth(text)) + "╯"
if highlight_frame {
ans = highlight(ans)
}
return
}
print_line := func(add_borders func(string, bool) string, is_last bool, items ...Item) {
type Position struct {
letter string
x, size int
}
texts := make([]string, 0, 8)
positions := make([]Position, 0, 8)
x := 0
for _, item := range items {
text := item.text
positions = append(positions, Position{item.letter, x, wcswidth.Stringwidth(text) + 2})
text = add_borders(text, item.letter == response_on_accept)
text += sep
x += wcswidth.Stringwidth(text)
texts = append(texts, text)
}
line := strings.TrimRightFunc(strings.Join(texts, ""), unicode.IsSpace)
offset := extra_for(wcswidth.Stringwidth(line), width)
for _, pos := range positions {
x = pos.x
x += offset
clickable_ranges[pos.letter] = append(clickable_ranges[pos.letter], Range{x, x + pos.size - 1, y})
}
end := "\r\n"
if is_last {
end = ""
}
lp.QueueWriteString(strings.Repeat(" ", offset) + line + end)
y++
}
lp.AllowLineWrapping(false)
defer func() { lp.AllowLineWrapping(true) }()
for i, boxed_line := range lines {
print_line(top, false, boxed_line...)
print_line(middle, false, boxed_line...)
is_last := i == len(lines)-1
print_line(bottom, is_last, boxed_line...)
}
}
draw_yesno := func(y, screen_width, screen_height int) {
yes := m.Green("Y") + "es"
no := m.BrightRed("N") + "o"
if y+3 <= screen_height {
draw_choice_boxes(y, screen_width, screen_height, Choice{"Yes", 0, "green", "y"}, Choice{"No", 0, "red", "n"})
} else {
sep := strings.Repeat(" ", 3)
text := yes + sep + no
w := wcswidth.Stringwidth(text)
x := extra_for(w, screen_width-2)
nx := x + wcswidth.Stringwidth(yes) + len(sep)
clickable_ranges = map[string][]Range{
"y": {{x, x + wcswidth.Stringwidth(yes) - 1, y}},
"n": {{nx, nx + wcswidth.Stringwidth(no) - 1, y}},
}
lp.QueueWriteString(strings.Repeat(" ", x) + text)
}
}
draw_choice := func(y, screen_width, screen_height int) {
if y+3 <= screen_height {
draw_choice_boxes(y, screen_width, screen_height, choice_order...)
return
}
clickable_ranges = map[string][]Range{}
current_line := ""
current_ranges := map[string]int{}
width := screen_width - 2
commit_line := func(add_newline bool) {
x := extra_for(wcswidth.Stringwidth(current_line), width)
text := strings.Repeat(" ", x) + current_line
if add_newline {
lp.Println(text)
} else {
lp.QueueWriteString(text)
}
for letter, sz := range current_ranges {
clickable_ranges[letter] = []Range{{x, x + sz - 3, y}}
x += sz
}
current_ranges = map[string]int{}
y++
current_line = ""
}
for _, choice := range choice_order {
text := choice.prefix()
spec := ""
if choice.color != "" {
spec = "fg=" + choice.color
} else {
spec = "fg=green"
}
if choice.letter == response_on_accept {
spec += " u=straight"
}
text += ctx.SprintFunc(spec)(choice.display_letter())
text += choice.suffix()
text += " "
sz := wcswidth.Stringwidth(text)
if sz+wcswidth.Stringwidth(current_line) >= width {
commit_line(true)
}
current_line += text
current_ranges[choice.letter] = sz
}
if current_line != "" {
commit_line(false)
}
}
draw_screen := func() error {
lp.StartAtomicUpdate()
defer lp.EndAtomicUpdate()
lp.ClearScreen()
msg_lines := make([]string, 0, 8)
sz, err := lp.ScreenSize()
if err != nil {
return err
}
if message != "" {
scanner := utils.NewLineScanner(message)
for scanner.Scan() {
msg_lines = draw_long_text(int(sz.WidthCells), scanner.Text(), msg_lines)
}
}
y := int(sz.HeightCells) - len(msg_lines)
y = utils.Max(0, (y/2)-2)
lp.QueueWriteString(strings.Repeat("\r\n", y))
for _, line := range msg_lines {
if replacement_text != "" {
idx := strings.Index(line, replacement_text)
if idx > -1 {
x := wcswidth.Stringwidth(line[:idx])
replacement_range = Range{x, x + wcswidth.Stringwidth(replacement_text), y}
}
}
lp.Println(line)
y++
}
if sz.HeightCells > 2 {
lp.Println()
y++
}
switch o.Type {
case "yesno":
draw_yesno(y, int(sz.WidthCells), int(sz.HeightCells))
case "choices":
draw_choice(y, int(sz.WidthCells), int(sz.HeightCells))
}
return nil
}
unhide := func() {
if hidden_text != "" && message != "" {
message = message[:hidden_text_start_pos] + hidden_text + message[hidden_text_end_pos:]
hidden_text = ""
draw_screen()
}
}
lp.OnInitialize = func() (string, error) {
lp.SetCursorVisible(false)
return "", draw_screen()
}
lp.OnFinalize = func() string {
lp.SetCursorVisible(true)
return ""
}
lp.OnText = func(text string, from_key_event, in_bracketed_paste bool) error {
text = strings.ToLower(text)
if allowed.Has(text) {
response = text
lp.Quit(0)
} else if hidden_text != "" && text == o.UnhideKey {
unhide()
} else if o.Type == "yesno" {
lp.Quit(1)
}
return nil
}
lp.OnKeyEvent = func(ev *loop.KeyEvent) error {
if ev.MatchesPressOrRepeat("esc") || ev.MatchesPressOrRepeat("ctrl+c") {
ev.Handled = true
lp.Quit(1)
} else if ev.MatchesPressOrRepeat("enter") {
ev.Handled = true
response = response_on_accept
lp.Quit(0)
}
return nil
}
lp.OnMouseEvent = func(ev *loop.MouseEvent) error {
if ev.Event_type == loop.MOUSE_CLICK {
for letter, ranges := range clickable_ranges {
for _, r := range ranges {
if r.has_point(ev.Cell.X, ev.Cell.Y) {
response = letter
lp.Quit(0)
return nil
}
}
}
if hidden_text != "" && replacement_range.has_point(ev.Cell.X, ev.Cell.Y) {
unhide()
}
}
return nil
}
lp.OnResize = func(old, news loop.ScreenSize) error {
return draw_screen()
}
err = lp.Run()
if err != nil {
return "", err
}
ds := lp.DeathSignalName()
if ds != "" {
fmt.Println("Killed by signal: ", ds)
lp.KillIfSignalled()
return "", fmt.Errorf("Filled by signal: %s", ds)
}
return response, nil
}

92
kittens/ask/get_line.go Normal file
View File

@ -0,0 +1,92 @@
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
package ask
import (
"fmt"
"io"
"os"
"path/filepath"
"time"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
)
var _ = fmt.Print
func get_line(o *Options) (result string, err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors)
if err != nil {
return
}
cwd, _ := os.Getwd()
ropts := readline.RlInit{Prompt: o.Prompt}
if o.Name != "" {
base := filepath.Join(utils.CacheDir(), "ask")
ropts.HistoryPath = filepath.Join(base, o.Name+".history.json")
os.MkdirAll(base, 0o755)
}
rl := readline.New(lp, ropts)
if o.Default != "" {
rl.SetText(o.Default)
}
lp.OnInitialize = func() (string, error) {
rl.Start()
return "", nil
}
lp.OnFinalize = func() string { rl.End(); return "" }
lp.OnResumeFromStop = func() error {
rl.Start()
return nil
}
lp.OnResize = rl.OnResize
lp.OnKeyEvent = func(event *loop.KeyEvent) error {
if event.MatchesPressOrRepeat("ctrl+c") {
return fmt.Errorf("Canceled by user")
}
err := rl.OnKeyEvent(event)
if err != nil {
if err == io.EOF {
lp.Quit(0)
return nil
}
if err == readline.ErrAcceptInput {
hi := readline.HistoryItem{Timestamp: time.Now(), Cmd: rl.AllText(), ExitCode: 0, Cwd: cwd}
rl.AddHistoryItem(hi)
result = rl.AllText()
lp.Quit(0)
return nil
}
return err
}
if event.Handled {
rl.Redraw()
return nil
}
return nil
}
lp.OnText = func(text string, from_key_event, in_bracketed_paste bool) error {
err := rl.OnText(text, from_key_event, in_bracketed_paste)
if err == nil {
rl.Redraw()
}
return err
}
err = lp.Run()
rl.Shutdown()
if err != nil {
return "", err
}
ds := lp.DeathSignalName()
if ds != "" {
return "", fmt.Errorf("Killed by signal: %s", ds)
}
return
}

73
kittens/ask/main.go Normal file
View File

@ -0,0 +1,73 @@
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
package ask
import (
"errors"
"fmt"
"kitty/tools/cli"
"kitty/tools/cli/markup"
"kitty/tools/tui"
)
var _ = fmt.Print
type Response struct {
Items []string `json:"items"`
Response string `json:"response"`
}
func show_message(msg string) {
if msg != "" {
m := markup.New(true)
fmt.Println(m.Bold(msg))
}
}
func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
output := tui.KittenOutputSerializer()
result := &Response{Items: args}
if len(o.Prompt) > 2 && o.Prompt[0] == o.Prompt[len(o.Prompt)-1] && (o.Prompt[0] == '"' || o.Prompt[0] == '\'') {
o.Prompt = o.Prompt[1 : len(o.Prompt)-1]
}
switch o.Type {
case "yesno", "choices":
result.Response, err = GetChoices(o)
if err != nil {
return 1, err
}
case "password":
show_message(o.Message)
pw, err := tui.ReadPassword(o.Prompt, false)
if err != nil {
if errors.Is(err, tui.Canceled) {
pw = ""
} else {
return 1, err
}
}
result.Response = pw
case "line":
show_message(o.Message)
result.Response, err = get_line(o)
if err != nil {
return 1, err
}
default:
return 1, fmt.Errorf("Unknown type: %s", o.Type)
}
s, err := output(result)
if err != nil {
return 1, err
}
_, err = fmt.Println(s)
if err != nil {
return 1, err
}
return
}
func EntryPoint(parent *cli.Command) {
create_cmd(parent, main)
}

View File

@ -1,76 +1,15 @@
#!/usr/bin/env python3
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os
import re
import sys
from contextlib import suppress
from typing import (
TYPE_CHECKING, Callable, Dict, Iterator, List, NamedTuple, Optional, Tuple
List,
Optional,
)
from kitty.cli import parse_args
from kitty.cli_stub import AskCLIOptions
from kitty.constants import cache_dir
from kitty.fast_data_types import truncate_point_for_length, wcswidth
from kitty.typing import BossType, KeyEventType, TypedDict
from kitty.utils import ScreenSize
from kitty.typing import BossType, TypedDict
from ..tui.handler import Handler, result_handler
from ..tui.loop import Loop, MouseEvent, debug
from ..tui.operations import MouseTracking, alternate_screen, styled
if TYPE_CHECKING:
import readline
debug
else:
readline = None
def get_history_items() -> List[str]:
return list(map(readline.get_history_item, range(1, readline.get_current_history_length() + 1)))
def sort_key(item: str) -> Tuple[int, str]:
return len(item), item.lower()
class HistoryCompleter:
def __init__(self, name: Optional[str] = None):
self.matches: List[str] = []
self.history_path = None
if name:
ddir = os.path.join(cache_dir(), 'ask')
with suppress(FileExistsError):
os.makedirs(ddir)
self.history_path = os.path.join(ddir, name)
def complete(self, text: str, state: int) -> Optional[str]:
response = None
if state == 0:
history_values = get_history_items()
if text:
self.matches = sorted(
(h for h in history_values if h and h.startswith(text)), key=sort_key)
else:
self.matches = []
try:
response = self.matches[state]
except IndexError:
response = None
return response
def __enter__(self) -> 'HistoryCompleter':
if self.history_path:
with suppress(Exception):
readline.read_history_file(self.history_path)
readline.set_completer(self.complete)
return self
def __exit__(self, *a: object) -> None:
if self.history_path:
readline.write_history_file(self.history_path)
from ..tui.handler import result_handler
def option_text() -> str:
@ -126,377 +65,8 @@ class Response(TypedDict):
items: List[str]
response: Optional[str]
class Choice(NamedTuple):
text: str
idx: int
color: str
letter: str
class Range(NamedTuple):
start: int
end: int
y: int
def has_point(self, x: int, y: int) -> bool:
return y == self.y and self.start <= x <= self.end
def truncate_at_space(text: str, width: int) -> Tuple[str, str]:
p = truncate_point_for_length(text, width)
if p < len(text):
i = text.rfind(' ', 0, p + 1)
if i > 0 and p - i < 12:
p = i + 1
return text[:p], text[p:]
def extra_for(width: int, screen_width: int) -> int:
return max(0, screen_width - width) // 2 + 1
class Password(Handler):
def __init__(self, cli_opts: AskCLIOptions, prompt: str, is_password: bool = True, initial_text: str = '') -> None:
self.cli_opts = cli_opts
self.prompt = prompt
self.initial_text = initial_text
from kittens.tui.line_edit import LineEdit
self.line_edit = LineEdit(is_password=is_password)
def initialize(self) -> None:
self.cmd.set_cursor_shape('beam')
if self.initial_text:
self.line_edit.on_text(self.initial_text, True)
self.draw_screen()
@Handler.atomic_update
def draw_screen(self) -> None:
self.cmd.clear_screen()
if self.cli_opts.message:
for line in self.cli_opts.message.splitlines():
self.print(line)
self.print()
self.line_edit.write(self.write, self.prompt)
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
self.line_edit.on_text(text, in_bracketed_paste)
self.draw_screen()
def on_key(self, key_event: KeyEventType) -> None:
if self.line_edit.on_key(key_event):
self.draw_screen()
return
if key_event.matches('enter'):
self.quit_loop(0)
if key_event.matches('esc'):
self.quit_loop(1)
def on_resize(self, screen_size: ScreenSize) -> None:
self.screen_size = screen_size
self.draw_screen()
def on_interrupt(self) -> None:
self.quit_loop(1)
on_eot = on_interrupt
@property
def response(self) -> str:
if self._tui_loop.return_code == 0:
return self.line_edit.current_input
return ''
class Choose(Handler): # {{{
mouse_tracking = MouseTracking.buttons_only
def __init__(self, cli_opts: AskCLIOptions) -> None:
self.prefix_style_pat = re.compile(r'(?:\x1b\[[^m]*?m)+')
self.cli_opts = cli_opts
self.choices: Dict[str, Choice] = {}
self.clickable_ranges: Dict[str, List[Range]] = {}
if cli_opts.type == 'yesno':
self.allowed = frozenset('yn')
else:
allowed = []
for choice in cli_opts.choices:
letter, text = choice.split(':', maxsplit=1)
color = ''
if ';' in letter:
letter, color = letter.split(';', maxsplit=1)
letter = letter.lower()
idx = text.lower().index(letter)
allowed.append(letter)
self.choices[letter] = Choice(text, idx, color, letter)
self.allowed = frozenset(allowed)
self.response = ''
self.response_on_accept = cli_opts.default or ''
if cli_opts.type in ('yesno', 'choices') and self.response_on_accept not in self.allowed:
self.response_on_accept = 'y' if cli_opts.type == 'yesno' else tuple(self.choices.keys())[0]
self.message = cli_opts.message
self.hidden_text_start_pos = self.hidden_text_end_pos = -1
self.hidden_text = ''
self.replacement_text = t = f'Press {styled(self.cli_opts.unhide_key, fg="green")} or click to show'
self.replacement_range = Range(-1, -1, -1)
if self.message and self.cli_opts.hidden_text_placeholder:
self.hidden_text_start_pos = self.message.find(self.cli_opts.hidden_text_placeholder)
if self.hidden_text_start_pos > -1:
self.hidden_text = sys.stdin.read().rstrip()
self.hidden_text_end_pos = self.hidden_text_start_pos + len(t)
suffix = self.message[self.hidden_text_start_pos + len(self.cli_opts.hidden_text_placeholder):]
self.message = self.message[:self.hidden_text_start_pos] + t + suffix
def initialize(self) -> None:
self.cmd.set_cursor_visible(False)
self.draw_screen()
def finalize(self) -> None:
self.cmd.set_cursor_visible(True)
def draw_long_text(self, text: str) -> Iterator[str]:
if not text:
yield ''
return
width = self.screen_size.cols - 2
m = self.prefix_style_pat.match(text)
prefix = m.group() if m else ''
while text:
t, text = truncate_at_space(text, width)
t = t.strip()
yield ' ' * extra_for(wcswidth(t), width) + styled(prefix + t, bold=True)
@Handler.atomic_update
def draw_screen(self) -> None:
self.cmd.clear_screen()
msg_lines: List[str] = []
if self.message:
for line in self.message.splitlines():
msg_lines.extend(self.draw_long_text(line))
y = self.screen_size.rows - len(msg_lines)
y = max(0, (y // 2) - 2)
self.print(end='\r\n'*y)
for line in msg_lines:
if self.replacement_text in line:
idx = line.find(self.replacement_text)
x = wcswidth(line[:idx])
self.replacement_range = Range(x, x + wcswidth(self.replacement_text), y)
self.print(line)
y += 1
if self.screen_size.rows > 2:
self.print()
y += 1
if self.cli_opts.type == 'yesno':
self.draw_yesno(y)
else:
self.draw_choice(y)
def draw_choice_boxes(self, y: int, *choices: Choice) -> None:
self.clickable_ranges.clear()
width = self.screen_size.cols - 2
current_line_length = 0
current_line: List[Tuple[str, str]] = []
lines: List[List[Tuple[str, str]]] = []
sep = ' '
sep_sz = len(sep) + 2 # for the borders
for choice in choices:
self.clickable_ranges[choice.letter] = []
text = ' ' + choice.text[:choice.idx]
text += styled(choice.text[choice.idx], fg=choice.color or 'green')
text += choice.text[choice.idx + 1:] + ' '
sz = wcswidth(text)
if sz + sep_sz + current_line_length > width:
lines.append(current_line)
current_line = []
current_line_length = 0
current_line.append((choice.letter, text))
current_line_length += sz + sep_sz
if current_line:
lines.append(current_line)
def top(text: str) -> str:
return '' + '' * wcswidth(text) + ''
def middle(text: str) -> str:
return f'{text}'
def bottom(text: str) -> str:
return '' + '' * wcswidth(text) + ''
def highlight(text: str, only_edges: bool = False) -> str:
if only_edges:
return styled(text[0], fg='yellow') + text[1:-1] + styled(text[-1], fg='yellow')
return styled(text, fg='yellow')
def print_line(add_borders: Callable[[str], str], *items: Tuple[str, str], is_last: bool = False) -> None:
nonlocal y
texts = []
positions = []
x = 0
for (letter, text) in items:
positions.append((letter, x, wcswidth(text) + 2))
text = add_borders(text)
if letter == self.response_on_accept:
text = highlight(text, only_edges=add_borders is middle)
text += sep
x += wcswidth(text)
texts.append(text)
line = ''.join(texts).rstrip()
offset = extra_for(wcswidth(line), width)
for (letter, x, sz) in positions:
x += offset
self.clickable_ranges[letter].append(Range(x, x + sz - 1, y))
self.print(' ' * offset, line, sep='', end='' if is_last else '\r\n')
y += 1
self.cmd.set_line_wrapping(False)
for boxed_line in lines:
print_line(top, *boxed_line)
print_line(middle, *boxed_line)
print_line(bottom, *boxed_line, is_last=boxed_line is lines[-1])
self.cmd.set_line_wrapping(True)
def draw_choice(self, y: int) -> None:
if y + 3 <= self.screen_size.rows:
self.draw_choice_boxes(y, *self.choices.values())
return
self.clickable_ranges.clear()
current_line = ''
current_ranges: Dict[str, int] = {}
width = self.screen_size.cols - 2
def commit_line(end: str = '\r\n') -> None:
nonlocal current_line, y
x = extra_for(wcswidth(current_line), width)
self.print(' ' * x + current_line, end=end)
for letter, sz in current_ranges.items():
self.clickable_ranges[letter] = [Range(x, x + sz - 3, y)]
x += sz
current_ranges.clear()
y += 1
current_line = ''
for letter, choice in self.choices.items():
text = choice.text[:choice.idx]
text += styled(choice.text[choice.idx], fg=choice.color or 'green', underline='straight' if letter == self.response_on_accept else None)
text += choice.text[choice.idx + 1:]
text += ' '
sz = wcswidth(text)
if sz + wcswidth(current_line) >= width:
commit_line()
current_line += text
current_ranges[letter] = sz
if current_line:
commit_line(end='')
def draw_yesno(self, y: int) -> None:
yes = styled('Y', fg='green') + 'es'
no = styled('N', fg='red') + 'o'
if y + 3 <= self.screen_size.rows:
self.draw_choice_boxes(y, Choice('Yes', 0, 'green', 'y'), Choice('No', 0, 'red', 'n'))
return
sep = ' ' * 3
text = yes + sep + no
w = wcswidth(text)
x = extra_for(w, self.screen_size.cols - 2)
nx = x + wcswidth(yes) + len(sep)
self.clickable_ranges = {'y': [Range(x, x + wcswidth(yes) - 1, y)], 'n': [Range(nx, nx + wcswidth(no) - 1, y)]}
self.print(' ' * x + text, end='')
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
text = text.lower()
if text in self.allowed:
self.response = text
self.quit_loop(0)
elif self.cli_opts.type == 'yesno':
self.on_interrupt()
elif self.hidden_text and text == self.cli_opts.unhide_key:
self.unhide()
def unhide(self) -> None:
if self.hidden_text and self.message:
self.message = self.message[:self.hidden_text_start_pos] + self.hidden_text + self.message[self.hidden_text_end_pos:]
self.hidden_text = ''
self.draw_screen()
def on_key(self, key_event: KeyEventType) -> None:
if key_event.matches('esc'):
self.on_interrupt()
elif key_event.matches('enter'):
self.response = self.response_on_accept
self.quit_loop(0)
def on_click(self, ev: MouseEvent) -> None:
for letter, ranges in self.clickable_ranges.items():
for r in ranges:
if r.has_point(ev.cell_x, ev.cell_y):
self.response = letter
self.quit_loop(0)
return
if self.hidden_text and self.replacement_range.has_point(ev.cell_x, ev.cell_y):
self.unhide()
def on_resize(self, screen_size: ScreenSize) -> None:
self.screen_size = screen_size
self.draw_screen()
def on_interrupt(self) -> None:
self.quit_loop(1)
on_eot = on_interrupt
# }}}
def main(args: List[str]) -> Response:
# For some reason importing readline in a key handler in the main kitty process
# causes a crash of the python interpreter, probably because of some global
# lock
global readline
msg = 'Ask the user for input'
try:
cli_opts, items = parse_args(args[1:], option_text, '', msg, 'kitty ask', result_class=AskCLIOptions)
except SystemExit as e:
if e.code != 0:
print(e.args[0])
input('Press Enter to quit')
raise SystemExit(e.code)
if cli_opts.type in ('yesno', 'choices'):
loop = Loop()
handler = Choose(cli_opts)
loop.loop(handler)
return {'items': items, 'response': handler.response}
prompt = cli_opts.prompt
if prompt[0] == prompt[-1] and prompt[0] in '\'"':
prompt = prompt[1:-1]
if cli_opts.type == 'password':
loop = Loop()
phandler = Password(cli_opts, prompt)
loop.loop(phandler)
return {'items': items, 'response': phandler.response}
import readline as rl
readline = rl
from kitty.shell import init_readline
init_readline()
response = None
with alternate_screen(), HistoryCompleter(cli_opts.name):
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
with suppress(KeyboardInterrupt, EOFError):
if cli_opts.default:
def prefill_text() -> None:
readline.insert_text(cli_opts.default or '')
readline.redisplay()
readline.set_pre_input_hook(prefill_text)
response = input(prompt)
readline.set_pre_input_hook()
else:
response = input(prompt)
return {'items': items, 'response': response}
raise SystemExit('This must be run as kitten ask')
@result_handler()
@ -507,6 +77,10 @@ def handle_result(args: List[str], data: Response, target_window_id: int, boss:
if __name__ == '__main__':
ans = main(sys.argv)
if ans:
print(ans)
main(sys.argv)
elif __name__ == '__doc__':
cd = sys.cli_docs # type: ignore
cd['usage'] = ''
cd['options'] = option_text
cd['help_text'] = 'Ask the user for input'
cd['short_desc'] = 'Ask the user for input'

View File

@ -31,6 +31,7 @@ class Broadcast(Handler):
def __init__(self, opts: BroadcastCLIOptions, initial_strings: List[str]) -> None:
self.opts = opts
self.hide_input = False
self.initial_strings = initial_strings
self.payload = {'exclude_active': True, 'data': '', 'match': opts.match, 'match_tab': opts.match_tab, 'session_id': uuid4()}
self.line_edit = LineEdit()
@ -40,7 +41,7 @@ class Broadcast(Handler):
def initialize(self) -> None:
self.write_broadcast_session()
self.print('Type the text to broadcast below, press', styled('Ctrl+Esc', fg='yellow'), 'to quit:')
self.print('Type the text to broadcast below, press', styled(self.opts.end_session, fg='yellow'), 'to quit:')
for x in self.initial_strings:
self.write_broadcast_text(x)
self.write(SAVE_CURSOR)
@ -56,6 +57,7 @@ class Broadcast(Handler):
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
self.write_broadcast_text(text)
if not self.hide_input:
self.line_edit.on_text(text, in_bracketed_paste)
self.commit_line()
@ -68,22 +70,33 @@ class Broadcast(Handler):
self.write_broadcast_text('\x04')
def on_key(self, key_event: KeyEventType) -> None:
if self.line_edit.on_key(key_event):
if key_event.matches(self.opts.hide_input_toggle):
self.hide_input ^= True
self.cmd.set_cursor_visible(not self.hide_input)
if self.hide_input:
self.end_line()
self.print('Input hidden, press', styled(self.opts.hide_input_toggle, fg='yellow'), 'to unhide:')
self.end_line()
return
if key_event.matches(self.opts.end_session):
self.quit_loop(0)
return
if not self.hide_input and self.line_edit.on_key(key_event):
self.commit_line()
if key_event.matches('enter'):
self.write_broadcast_text('\r')
self.print('')
self.line_edit.clear()
self.write(SAVE_CURSOR)
return
if key_event.matches('ctrl+esc'):
self.quit_loop(0)
self.end_line()
return
ek = encode_key_event(key_event)
ek = standard_b64encode(ek.encode('utf-8')).decode('ascii')
self.write_broadcast_data('kitty-key:' + ek)
def end_line(self) -> None:
self.print('')
self.line_edit.clear()
self.write(SAVE_CURSOR)
def write_broadcast_text(self, text: str) -> None:
self.write_broadcast_data('base64:' + standard_b64encode(text.encode('utf-8')).decode('ascii'))
@ -98,7 +111,19 @@ class Broadcast(Handler):
self.write(session_command(self.payload, start))
OPTIONS = (MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')).format
OPTIONS = ('''
--hide-input-toggle
default=Ctrl+Alt+Esc
Key to press that will toggle hiding of the input in the broadcast window itself.
Useful while typing a password, prevents the password from being visible on the screen.
--end-session
default=Ctrl+Esc
Key to press to end the broadcast session.
''' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')).format
help_text = 'Broadcast typed text to kitty windows. By default text is sent to all windows, unless one of the matching options is specified'
usage = '[initial text to send ...]'

View File

@ -1,86 +0,0 @@
/*
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#pragma once
#include "data-types.h"
#if defined(_MSC_VER)
#define ISWINDOWS
#define STDCALL __stdcall
#ifndef ssize_t
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#ifndef SSIZE_MAX
#if defined(_WIN64)
#define SSIZE_MAX _I64_MAX
#else
#define SSIZE_MAX LONG_MAX
#endif
#endif
#endif
#else
#define STDCALL
#endif
#include "vector.h"
typedef uint8_t len_t;
typedef uint32_t text_t;
#define LEN_MAX UINT8_MAX
#define IS_LOWERCASE(x) (x) >= 'a' && (x) <= 'z'
#define IS_UPPERCASE(x) (x) >= 'A' && (x) <= 'Z'
#define LOWERCASE(x) ((IS_UPPERCASE(x)) ? (x) + 32 : (x))
#define arraysz(x) (sizeof(x)/sizeof(x[0]))
typedef struct {
text_t* src;
ssize_t src_sz;
len_t haystack_len;
len_t *positions;
double score;
ssize_t idx;
} Candidate;
typedef struct {
Candidate *haystack;
size_t haystack_count;
text_t level1[LEN_MAX], level2[LEN_MAX], level3[LEN_MAX], needle[LEN_MAX];
len_t level1_len, level2_len, level3_len, needle_len;
size_t haystack_size;
text_t *output;
size_t output_sz, output_pos;
int oom;
} GlobalData;
typedef struct {
bool output_positions;
size_t limit;
int num_threads;
text_t mark_before[128], mark_after[128], delimiter[128];
size_t mark_before_sz, mark_after_sz, delimiter_sz;
} Options;
VECTOR_OF(len_t, Positions)
VECTOR_OF(text_t, Chars)
VECTOR_OF(Candidate, Candidates)
void output_results(GlobalData *, Candidate *haystack, size_t count, Options *opts, len_t needle_len);
void* alloc_workspace(len_t max_haystack_len, GlobalData*);
void* free_workspace(void *v);
double score_item(void *v, text_t *haystack, len_t haystack_len, len_t *match_positions);
unsigned int encode_codepoint(text_t ch, char* dest);
size_t unescape(const char *src, char *dest, size_t destlen);
int cpu_count(void);
void* alloc_threads(size_t num_threads);
#ifdef ISWINDOWS
bool start_thread(void* threads, size_t i, unsigned int (STDCALL *start_routine) (void *), void *arg);
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
#else
bool start_thread(void* threads, size_t i, void *(*start_routine) (void *), void *arg);
#endif
void wait_for_thread(void *threads, size_t i);
void free_threads(void *threads);

View File

@ -1,244 +0,0 @@
/*
* main.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "choose-data-types.h"
#include "charsets.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#ifndef ISWINDOWS
#include <unistd.h>
#endif
typedef struct {
size_t start, count;
void *workspace;
len_t max_haystack_len;
bool started;
GlobalData *global;
} JobData;
static unsigned int STDCALL
run_scoring(JobData *job_data) {
GlobalData *global = job_data->global;
for (size_t i = job_data->start; i < job_data->start + job_data->count; i++) {
global->haystack[i].score = score_item(job_data->workspace, global->haystack[i].src, global->haystack[i].haystack_len, global->haystack[i].positions);
}
return 0;
}
static void*
run_scoring_pthreads(void *job_data) {
run_scoring((JobData*)job_data);
return NULL;
}
#ifdef ISWINDOWS
#define START_FUNC run_scoring
#else
#define START_FUNC run_scoring_pthreads
#endif
static JobData*
create_job(size_t i, size_t blocksz, GlobalData *global) {
JobData *ans = (JobData*)calloc(1, sizeof(JobData));
if (ans == NULL) return NULL;
ans->start = i * blocksz;
if (ans->start >= global->haystack_count) ans->count = 0;
else ans->count = global->haystack_count - ans->start;
ans->max_haystack_len = 0;
for (size_t j = ans->start; j < ans->start + ans->count; j++) ans->max_haystack_len = MAX(ans->max_haystack_len, global->haystack[j].haystack_len);
if (ans->count > 0) {
ans->workspace = alloc_workspace(ans->max_haystack_len, global);
if (!ans->workspace) { free(ans); return NULL; }
}
ans->global = global;
return ans;
}
static JobData*
free_job(JobData *job) {
if (job) {
if (job->workspace) free_workspace(job->workspace);
free(job);
}
return NULL;
}
static int
run_threaded(int num_threads_asked, GlobalData *global) {
int ret = 0;
size_t i, blocksz;
size_t num_threads = MAX(1, num_threads_asked > 0 ? num_threads_asked : cpu_count());
if (global->haystack_size < 10000) num_threads = 1;
/* printf("num_threads: %lu asked: %d sysconf: %ld\n", num_threads, num_threads_asked, sysconf(_SC_NPROCESSORS_ONLN)); */
void *threads = alloc_threads(num_threads);
JobData **job_data = calloc(num_threads, sizeof(JobData*));
if (threads == NULL || job_data == NULL) { ret = 1; goto end; }
blocksz = global->haystack_count / num_threads + global->haystack_count % num_threads;
for (i = 0; i < num_threads; i++) {
job_data[i] = create_job(i, blocksz, global);
if (job_data[i] == NULL) { ret = 1; goto end; }
}
if (num_threads == 1) {
run_scoring(job_data[0]);
} else {
for (i = 0; i < num_threads; i++) {
job_data[i]->started = false;
if (job_data[i]->count > 0) {
if (!start_thread(threads, i, START_FUNC, job_data[i])) ret = 1;
else job_data[i]->started = true;
}
}
}
end:
if (num_threads > 1 && job_data) {
for (i = 0; i < num_threads; i++) {
if (job_data[i] && job_data[i]->started) wait_for_thread(threads, i);
}
}
if (job_data) { for (i = 0; i < num_threads; i++) job_data[i] = free_job(job_data[i]); }
free(job_data);
free_threads(threads);
return ret;
}
static int
run_search(Options *opts, GlobalData *global, const char * const *lines, const size_t* sizes, size_t num_lines) {
const char *linebuf = NULL;
size_t idx = 0;
ssize_t sz = 0;
int ret = 0;
Candidates candidates = {0};
Chars chars = {0};
ALLOC_VEC(text_t, chars, 8192 * 20);
if (chars.data == NULL) return 1;
ALLOC_VEC(Candidate, candidates, 8192);
if (candidates.data == NULL) { FREE_VEC(chars); return 1; }
for (size_t i = 0; i < num_lines; i++) {
sz = sizes[i];
linebuf = lines[i];
if (sz > 0) {
ENSURE_SPACE(text_t, chars, sz);
ENSURE_SPACE(Candidate, candidates, 1);
sz = decode_utf8_string(linebuf, sz, &(NEXT(chars)));
NEXT(candidates).src_sz = sz;
NEXT(candidates).haystack_len = (len_t)(MIN(LEN_MAX, sz));
global->haystack_size += NEXT(candidates).haystack_len;
NEXT(candidates).idx = idx++;
INC(candidates, 1); INC(chars, sz);
}
}
// Prepare the haystack allocating space for positions arrays and settings
// up the src pointers to point to the correct locations
Candidate *haystack = &ITEM(candidates, 0);
len_t *positions = (len_t*)calloc(SIZE(candidates), sizeof(len_t) * global->needle_len);
if (positions) {
text_t *cdata = &ITEM(chars, 0);
for (size_t i = 0, off = 0; i < SIZE(candidates); i++) {
haystack[i].positions = positions + (i * global->needle_len);
haystack[i].src = cdata + off;
off += haystack[i].src_sz;
}
global->haystack = haystack;
global->haystack_count = SIZE(candidates);
ret = run_threaded(opts->num_threads, global);
if (ret == 0) output_results(global, haystack, SIZE(candidates), opts, global->needle_len);
else { REPORT_OOM; }
} else { ret = 1; REPORT_OOM; }
FREE_VEC(chars); free(positions); FREE_VEC(candidates);
return ret;
}
static size_t
copy_unicode_object(PyObject *src, text_t *dest, size_t dest_sz) {
PyUnicode_READY(src);
int kind = PyUnicode_KIND(src);
void *data = PyUnicode_DATA(src);
size_t len = PyUnicode_GetLength(src);
for (size_t i = 0; i < len && i < dest_sz; i++) {
dest[i] = PyUnicode_READ(kind, data, i);
}
return len;
}
static PyObject*
match(PyObject *self, PyObject *args) {
(void)(self);
int output_positions;
unsigned long limit;
PyObject *lines, *levels, *needle, *mark_before, *mark_after, *delimiter;
Options opts = {0};
GlobalData global = {0};
if (!PyArg_ParseTuple(args, "O!O!UpkiUUU",
&PyList_Type, &lines, &PyTuple_Type, &levels, &needle,
&output_positions, &limit, &opts.num_threads,
&mark_before, &mark_after, &delimiter
)) return NULL;
opts.output_positions = output_positions ? true : false;
opts.limit = limit;
global.level1_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 0), global.level1, arraysz(global.level1));
global.level2_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 1), global.level2, arraysz(global.level2));
global.level3_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 2), global.level3, arraysz(global.level3));
global.needle_len = copy_unicode_object(needle, global.needle, arraysz(global.needle));
opts.mark_before_sz = copy_unicode_object(mark_before, opts.mark_before, arraysz(opts.mark_before));
opts.mark_after_sz = copy_unicode_object(mark_after, opts.mark_after, arraysz(opts.mark_after));
opts.delimiter_sz = copy_unicode_object(delimiter, opts.delimiter, arraysz(opts.delimiter));
size_t num_lines = PyList_GET_SIZE(lines);
char **clines = malloc(sizeof(char*) * num_lines);
if (!clines) { return PyErr_NoMemory(); }
size_t *sizes = malloc(sizeof(size_t) * num_lines);
if (!sizes) { free(clines); clines = NULL; return PyErr_NoMemory(); }
for (size_t i = 0; i < num_lines; i++) {
clines[i] = PyBytes_AS_STRING(PyList_GET_ITEM(lines, i));
sizes[i] = PyBytes_GET_SIZE(PyList_GET_ITEM(lines, i));
}
Py_BEGIN_ALLOW_THREADS;
run_search(&opts, &global, (const char* const *)clines, sizes, num_lines);
Py_END_ALLOW_THREADS;
free(clines); free(sizes);
if (global.oom) { free(global.output); return PyErr_NoMemory(); }
if (global.output) {
PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, global.output, global.output_pos);
free(global.output);
return ans;
}
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{"match", match, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "subseq_matcher", /* name of module */
.m_doc = NULL,
.m_size = -1,
.m_methods = module_methods
};
EXPORTED PyMODINIT_FUNC
PyInit_subseq_matcher(void) {
return PyModule_Create(&module);
}

View File

@ -1,39 +0,0 @@
#!/usr/bin/env python3
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import sys
from typing import List
from kitty.key_encoding import KeyEvent
from ..tui.handler import Handler
from ..tui.loop import Loop
class ChooseHandler(Handler):
def initialize(self) -> None:
pass
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
pass
def on_key(self, key_event: KeyEvent) -> None:
pass
def on_interrupt(self) -> None:
self.quit_loop(1)
def on_eot(self) -> None:
self.quit_loop(1)
def main(args: List[str]) -> None:
loop = Loop()
handler = ChooseHandler()
loop.loop(handler)
raise SystemExit(loop.return_code)
if __name__ == '__main__':
main(sys.argv)

View File

@ -1,38 +0,0 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
from typing import Iterable, List, Union
from . import subseq_matcher
def match(
input_data: Union[str, bytes, Iterable[Union[str, bytes]]],
query: str,
threads: int = 0,
positions: bool = False,
level1: str = '/',
level2: str = '-_0123456789',
level3: str = '.',
limit: int = 0,
mark_before: str = '',
mark_after: str = '',
delimiter: str = '\n'
) -> List[str]:
if isinstance(input_data, str):
idata = [x.encode('utf-8') for x in input_data.split(delimiter)]
elif isinstance(input_data, bytes):
idata = input_data.split(delimiter.encode('utf-8'))
else:
idata = [x.encode('utf-8') if isinstance(x, str) else x for x in input_data]
query = query.lower()
level1 = level1.lower()
level2 = level2.lower()
level3 = level3.lower()
data = subseq_matcher.match(
idata, (level1, level2, level3), query,
positions, limit, threads,
mark_before, mark_after, delimiter)
if data is None:
return []
return list(filter(None, data.split(delimiter or '\n')))

View File

@ -1,101 +0,0 @@
/*
* output.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "choose-data-types.h"
#include "../../kitty/iqsort.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef ISWINDOWS
#include <io.h>
#define STDOUT_FILENO 1
static ssize_t ms_write(int fd, const void* buf, size_t count) { return _write(fd, buf, (unsigned int)count); }
#define write ms_write
#else
#include <unistd.h>
#endif
#include <errno.h>
#define FIELD(x, which) (((Candidate*)(x))->which)
static bool
ensure_space(GlobalData *global, size_t sz) {
if (global->output_sz < sz + global->output_pos || !global->output) {
size_t before = global->output_sz;
global->output_sz += MAX(sz, (64u * 1024u));
global->output = realloc(global->output, sizeof(text_t) * global->output_sz);
if (!global->output) {
global->output_sz = before;
return false;
}
}
return true;
}
static void
output_text(GlobalData *global, const text_t *data, size_t sz) {
if (ensure_space(global, sz)) {
memcpy(global->output + global->output_pos, data, sizeof(text_t) * sz);
global->output_pos += sz;
}
}
static void
output_with_marks(GlobalData *global, Options *opts, text_t *src, size_t src_sz, len_t *positions, len_t poslen) {
size_t pos, i = 0;
for (pos = 0; pos < poslen; pos++, i++) {
output_text(global, src + i, MIN(src_sz, positions[pos]) - i);
i = positions[pos];
if (i < src_sz) {
if (opts->mark_before_sz > 0) output_text(global, opts->mark_before, opts->mark_before_sz);
output_text(global, src + i, 1);
if (opts->mark_after_sz > 0) output_text(global, opts->mark_after, opts->mark_after_sz);
}
}
i = positions[poslen - 1];
if (i + 1 < src_sz) output_text(global, src + i + 1, src_sz - i - 1);
}
static void
output_positions(GlobalData *global, len_t *positions, len_t num) {
wchar_t buf[128];
for (len_t i = 0; i < num; i++) {
int pnum = swprintf(buf, arraysz(buf), L"%u", positions[i]);
if (pnum > 0 && ensure_space(global, pnum + 1)) {
for (int k = 0; k < pnum; k++) global->output[global->output_pos++] = buf[k];
global->output[global->output_pos++] = (i == num - 1) ? ':' : ',';
}
}
}
static void
output_result(GlobalData *global, Candidate *c, Options *opts, len_t needle_len) {
if (opts->output_positions) output_positions(global, c->positions, needle_len);
if (opts->mark_before_sz > 0 || opts->mark_after_sz > 0) {
output_with_marks(global, opts, c->src, c->src_sz, c->positions, needle_len);
} else {
output_text(global, c->src, c->src_sz);
}
output_text(global, opts->delimiter, opts->delimiter_sz);
}
void
output_results(GlobalData *global, Candidate *haystack, size_t count, Options *opts, len_t needle_len) {
Candidate *c;
#define lt(b, a) ( (a)->score < (b)->score || ((a)->score == (b)->score && (a->idx < b->idx)) )
QSORT(Candidate, haystack, count, lt);
#undef lt
size_t left = opts->limit > 0 ? opts->limit : count;
for (size_t i = 0; i < left; i++) {
c = haystack + i;
if (c->score > 0) output_result(global, c, opts, needle_len);
}
}

View File

@ -1,182 +0,0 @@
/*
* score.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "choose-data-types.h"
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <stdio.h>
typedef struct {
len_t *positions_buf; // buffer to store positions for every char in needle
len_t **positions; // Array of pointers into positions_buf
len_t *positions_count; // Array of counts for positions
len_t needle_len; // Length of the needle
len_t max_haystack_len; // Max length of a string in the haystack
len_t haystack_len; // Length of the current string in the haystack
len_t *address; // Array of offsets into the positions array
double max_score_per_char;
uint8_t *level_factors; // Array of score factors for every character in the current haystack that matches a character in the needle
text_t *level1, *level2, *level3; // The characters in the levels
len_t level1_len, level2_len, level3_len;
text_t *needle; // The current needle
text_t *haystack; //The current haystack
} WorkSpace;
void*
alloc_workspace(len_t max_haystack_len, GlobalData *global) {
WorkSpace *ans = calloc(1, sizeof(WorkSpace));
if (ans == NULL) return NULL;
ans->positions_buf = (len_t*) calloc(global->needle_len, sizeof(len_t) * max_haystack_len);
ans->positions = (len_t**)calloc(global->needle_len, sizeof(len_t*));
ans->positions_count = (len_t*)calloc(2*global->needle_len, sizeof(len_t));
ans->level_factors = (uint8_t*)calloc(max_haystack_len, sizeof(uint8_t));
if (ans->positions == NULL || ans->positions_buf == NULL || ans->positions_count == NULL || ans->level_factors == NULL) { free_workspace(ans); return NULL; }
ans->needle = global->needle;
ans->needle_len = global->needle_len;
ans->max_haystack_len = max_haystack_len;
ans->level1 = global->level1; ans->level2 = global->level2; ans->level3 = global->level3;
ans->level1_len = global->level1_len; ans->level2_len = global->level2_len; ans->level3_len = global->level3_len;
ans->address = ans->positions_count + sizeof(len_t) * global->needle_len;
for (len_t i = 0; i < global->needle_len; i++) ans->positions[i] = ans->positions_buf + i * max_haystack_len;
return ans;
}
#define NUKE(x) free(x); x = NULL;
void*
free_workspace(void *v) {
WorkSpace *w = (WorkSpace*)v;
NUKE(w->positions_buf);
NUKE(w->positions);
NUKE(w->positions_count);
NUKE(w->level_factors);
free(w);
return NULL;
}
static bool
has_char(text_t *text, len_t sz, text_t ch) {
for(len_t i = 0; i < sz; i++) {
if(text[i] == ch) return true;
}
return false;
}
static uint8_t
level_factor_for(text_t current, text_t last, WorkSpace *w) {
text_t lch = LOWERCASE(last);
if (has_char(w->level1, w->level1_len, lch)) return 90;
if (has_char(w->level2, w->level2_len, lch)) return 80;
if (IS_LOWERCASE(last) && IS_UPPERCASE(current)) return 80; // CamelCase
if (has_char(w->level3, w->level3_len, lch)) return 70;
return 0;
}
static void
init_workspace(WorkSpace *w, text_t *haystack, len_t haystack_len) {
// Calculate the positions and level_factors arrays for the specified haystack
bool level_factor_calculated = false;
memset(w->positions_count, 0, sizeof(*(w->positions_count)) * 2 * w->needle_len);
memset(w->level_factors, 0, sizeof(*(w->level_factors)) * w->max_haystack_len);
for (len_t i = 0; i < haystack_len; i++) {
level_factor_calculated = false;
for (len_t j = 0; j < w->needle_len; j++) {
if (w->needle[j] == LOWERCASE(haystack[i])) {
if (!level_factor_calculated) {
level_factor_calculated = true;
w->level_factors[i] = i > 0 ? level_factor_for(haystack[i], haystack[i-1], w) : 0;
}
w->positions[j][w->positions_count[j]++] = i;
}
}
}
w->haystack = haystack;
w->haystack_len = haystack_len;
w->max_score_per_char = (1.0 / haystack_len + 1.0 / w->needle_len) / 2.0;
}
static bool
has_atleast_one_match(WorkSpace *w) {
int p = -1;
bool found;
for (len_t i = 0; i < w->needle_len; i++) {
if (w->positions_count[i] == 0) return false; // All characters of the needle are not present in the haystack
found = false;
for (len_t j = 0; j < w->positions_count[i]; j++) {
if (w->positions[i][j] > p) { p = w->positions[i][j]; found = true; break; }
}
if (!found) return false; // Characters of needle not present in sequence in haystack
}
return true;
}
#define POSITION(x) w->positions[x][w->address[x]]
static bool
increment_address(WorkSpace *w) {
len_t pos = w->needle_len - 1;
while(true) {
w->address[pos]++;
if (w->address[pos] < w->positions_count[pos]) return true;
if (pos == 0) break;
w->address[pos--] = 0;
}
return false;
}
static bool
address_is_monotonic(WorkSpace *w) {
// Check if the character positions pointed to by the current address are monotonic
for (len_t i = 1; i < w->needle_len; i++) {
if (POSITION(i) <= POSITION(i-1)) return false;
}
return true;
}
static double
calc_score(WorkSpace *w) {
double ans = 0;
len_t distance, pos;
for (len_t i = 0; i < w->needle_len; i++) {
pos = POSITION(i);
if (i == 0) distance = pos < LEN_MAX ? pos + 1 : LEN_MAX;
else {
distance = pos - POSITION(i-1);
if (distance < 2) {
ans += w->max_score_per_char; // consecutive characters
continue;
}
}
if (w->level_factors[pos]) ans += (100 * w->max_score_per_char) / w->level_factors[pos]; // at a special location
else ans += (0.75 * w->max_score_per_char) / distance;
}
return ans;
}
static double
process_item(WorkSpace *w, len_t *match_positions) {
double highscore = 0, score;
do {
if (!address_is_monotonic(w)) continue;
score = calc_score(w);
if (score > highscore) {
highscore = score;
for (len_t i = 0; i < w->needle_len; i++) match_positions[i] = POSITION(i);
}
} while(increment_address(w));
return highscore;
}
double
score_item(void *v, text_t *haystack, len_t haystack_len, len_t *match_positions) {
WorkSpace *w = (WorkSpace*)v;
init_workspace(w, haystack, haystack_len);
if (!has_atleast_one_match(w)) return 0;
return process_item(w, match_positions);
}

View File

@ -1,9 +0,0 @@
from typing import List, Optional, Tuple
def match(
lines: List[bytes], levels: Tuple[str, str, str], needle: str,
output_positions: bool, limit: int, num_threads: int, mark_before: str,
mark_after: str, delimiter: str
) -> Optional[str]:
pass

View File

@ -1,50 +0,0 @@
/*
* unix_compat.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "choose-data-types.h"
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef __APPLE__
#ifndef _SC_NPROCESSORS_ONLN
#define _SC_NPROCESSORS_ONLN 58
#endif
#endif
int
cpu_count() {
return sysconf(_SC_NPROCESSORS_ONLN);
}
void*
alloc_threads(size_t num_threads) {
return calloc(num_threads, sizeof(pthread_t));
}
bool
start_thread(void* threads, size_t i, void *(*start_routine) (void *), void *arg) {
int rc;
if ((rc = pthread_create(((pthread_t*)threads) + i, NULL, start_routine, arg))) {
fprintf(stderr, "Failed to create thread, with error: %s\n", strerror(rc));
return false;
}
return true;
}
void
wait_for_thread(void *threads, size_t i) {
pthread_join(((pthread_t*)(threads))[i], NULL);
}
void
free_threads(void *threads) {
free(threads);
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#pragma once
#include "data-types.h"
#define REPORT_OOM global->oom = 1;
#define VECTOR_OF(TYPE, NAME) typedef struct { \
TYPE *data; \
size_t size; \
size_t capacity; \
} NAME;
#define ALLOC_VEC(TYPE, vec, cap) \
vec.size = 0; vec.capacity = cap; \
vec.data = (TYPE*)malloc(vec.capacity * sizeof(TYPE)); \
if (vec.data == NULL) { REPORT_OOM; }
#define FREE_VEC(vec) \
if (vec.data) { free(vec.data); vec.data = NULL; } \
vec.size = 0; vec.capacity = 0;
#define ENSURE_SPACE(TYPE, vec, amt) \
if (vec.size + amt >= vec.capacity) { \
vec.capacity = MAX(vec.capacity * 2, vec.size + amt); \
void *temp = realloc(vec.data, sizeof(TYPE) * vec.capacity); \
if (temp == NULL) { REPORT_OOM; ret = 1; free(vec.data); vec.data = NULL; vec.size = 0; vec.capacity = 0; break; } \
else vec.data = temp; \
}
#define NEXT(vec) (vec.data[vec.size])
#define INC(vec, amt) vec.size += amt;
#define SIZE(vec) (vec.size)
#define ITEM(vec, n) (vec.data[n])

View File

@ -1,107 +0,0 @@
/*
* windows_compat.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "choose-data-types.h"
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <errno.h>
int
cpu_count() {
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
}
void*
alloc_threads(size_t num_threads) {
return calloc(num_threads, sizeof(uintptr_t));
}
bool
start_thread(void* vt, size_t i, unsigned int (STDCALL *start_routine) (void *), void *arg) {
uintptr_t *threads = (uintptr_t*)vt;
errno = 0;
threads[i] = _beginthreadex(NULL, 0, start_routine, arg, 0, NULL);
if (threads[i] == 0) {
perror("Failed to create thread, with error");
return false;
}
return true;
}
void
wait_for_thread(void *vt, size_t i) {
uintptr_t *threads = vt;
WaitForSingleObject((HANDLE)threads[i], INFINITE);
CloseHandle((HANDLE)threads[i]);
threads[i] = 0;
}
void
free_threads(void *threads) {
free(threads);
}
ssize_t
getdelim(char **lineptr, size_t *n, int delim, FILE *stream) {
char c, *cur_pos, *new_lineptr;
size_t new_lineptr_len;
if (lineptr == NULL || n == NULL || stream == NULL) {
errno = EINVAL;
return -1;
}
if (*lineptr == NULL) {
*n = 8192; /* init len */
if ((*lineptr = (char *)malloc(*n)) == NULL) {
errno = ENOMEM;
return -1;
}
}
cur_pos = *lineptr;
for (;;) {
c = getc(stream);
if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
return -1;
if (c == EOF)
break;
if ((*lineptr + *n - cur_pos) < 2) {
if (SSIZE_MAX / 2 < *n) {
#ifdef EOVERFLOW
errno = EOVERFLOW;
#else
errno = ERANGE; /* no EOVERFLOW defined */
#endif
return -1;
}
new_lineptr_len = *n * 2;
if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL) {
errno = ENOMEM;
return -1;
}
*lineptr = new_lineptr;
*n = new_lineptr_len;
}
*cur_pos++ = c;
if (c == delim)
break;
}
*cur_pos = '\0';
return (ssize_t)(cur_pos - *lineptr);
}

237
kittens/clipboard/legacy.go Normal file
View File

@ -0,0 +1,237 @@
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package clipboard
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"os"
"strings"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print
var _ = fmt.Print
func encode_read_from_clipboard(use_primary bool) string {
dest := "c"
if use_primary {
dest = "p"
}
return fmt.Sprintf("\x1b]52;%s;?\x1b\\", dest)
}
type base64_streaming_enc struct {
output func(string) loop.IdType
last_written_id loop.IdType
}
func (self *base64_streaming_enc) Write(p []byte) (int, error) {
if len(p) > 0 {
self.last_written_id = self.output(string(p))
}
return len(p), nil
}
var ErrTooMuchPipedData = errors.New("Too much piped data")
func read_all_with_max_size(r io.Reader, max_size int) ([]byte, error) {
b := make([]byte, 0, utils.Min(8192, max_size))
for {
if len(b) == cap(b) {
new_size := utils.Min(2*cap(b), max_size)
if new_size <= cap(b) {
return b, ErrTooMuchPipedData
}
b = append(make([]byte, 0, new_size), b...)
}
n, err := r.Read(b[len(b):cap(b)])
b = b[:len(b)+n]
if err != nil {
if err == io.EOF {
err = nil
}
return b, err
}
}
}
func preread_stdin() (data_src io.Reader, tempfile *os.File, err error) {
// we pre-read STDIN because otherwise if the output of a command is being piped in
// and that command itself transmits on the tty we will break. For example
// kitten @ ls | kitten clipboard
var stdin_data []byte
stdin_data, err = read_all_with_max_size(os.Stdin, 2*1024*1024)
if err == nil {
os.Stdin.Close()
} else if err != ErrTooMuchPipedData {
os.Stdin.Close()
err = fmt.Errorf("Failed to read from STDIN pipe with error: %w", err)
return
}
if err == ErrTooMuchPipedData {
tempfile, err = utils.CreateAnonymousTemp("")
if err != nil {
return nil, nil, fmt.Errorf("Failed to create a temporary from STDIN pipe with error: %w", err)
}
tempfile.Write(stdin_data)
_, err = io.Copy(tempfile, os.Stdin)
os.Stdin.Close()
if err != nil {
return nil, nil, fmt.Errorf("Failed to copy data from STDIN pipe to temp file with error: %w", err)
}
tempfile.Seek(0, os.SEEK_SET)
data_src = tempfile
} else if stdin_data != nil {
data_src = bytes.NewBuffer(stdin_data)
}
return
}
func run_plain_text_loop(opts *Options) (err error) {
stdin_is_tty := tty.IsTerminal(os.Stdin.Fd())
var data_src io.Reader
var tempfile *os.File
if !stdin_is_tty {
data_src, tempfile, err = preread_stdin()
if err != nil {
return err
}
if tempfile != nil {
defer tempfile.Close()
}
}
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
if err != nil {
return
}
dest := "c"
if opts.UsePrimary {
dest = "p"
}
send_to_loop := func(data string) loop.IdType {
return lp.QueueWriteString(data)
}
enc_writer := base64_streaming_enc{output: send_to_loop}
enc := base64.NewEncoder(base64.StdEncoding, &enc_writer)
transmitting := true
after_read_from_stdin := func() {
transmitting = false
if opts.GetClipboard {
lp.QueueWriteString(encode_read_from_clipboard(opts.UsePrimary))
} else if opts.WaitForCompletion {
lp.QueueWriteString("\x1bP+q544e\x1b\\")
} else {
lp.Quit(0)
}
}
buf := make([]byte, 8192)
write_one_chunk := func() error {
n, err := data_src.Read(buf[:cap(buf)])
if err != nil && !errors.Is(err, io.EOF) {
send_to_loop("\x1b\\")
return err
}
if n > 0 {
enc.Write(buf[:n])
}
if errors.Is(err, io.EOF) {
enc.Close()
send_to_loop("\x1b\\")
after_read_from_stdin()
}
return nil
}
lp.OnInitialize = func() (string, error) {
if data_src != nil {
send_to_loop(fmt.Sprintf("\x1b]52;%s;", dest))
return "", write_one_chunk()
}
after_read_from_stdin()
return "", nil
}
lp.OnWriteComplete = func(id loop.IdType) error {
if id == enc_writer.last_written_id {
return write_one_chunk()
}
return nil
}
var clipboard_contents []byte
lp.OnEscapeCode = func(etype loop.EscapeCodeType, data []byte) (err error) {
switch etype {
case loop.DCS:
if strings.HasPrefix(utils.UnsafeBytesToString(data), "1+r") {
lp.Quit(0)
}
case loop.OSC:
q := utils.UnsafeBytesToString(data)
if strings.HasPrefix(q, "52;") {
parts := strings.SplitN(q, ";", 3)
if len(parts) < 3 {
lp.Quit(0)
return
}
data, err := base64.StdEncoding.DecodeString(parts[2])
if err != nil {
return fmt.Errorf("Invalid base64 encoded data from terminal with error: %w", err)
}
clipboard_contents = data
lp.Quit(0)
}
}
return
}
esc_count := 0
lp.OnKeyEvent = func(event *loop.KeyEvent) error {
if event.MatchesPressOrRepeat("ctrl+c") || event.MatchesPressOrRepeat("esc") {
if transmitting {
return nil
}
event.Handled = true
esc_count++
if esc_count < 2 {
key := "Esc"
if event.MatchesPressOrRepeat("ctrl+c") {
key = "Ctrl+C"
}
lp.QueueWriteString(fmt.Sprintf("Waiting for response from terminal, press %s again to abort. This could cause garbage to be spewed to the screen.\r\n", key))
} else {
return fmt.Errorf("Aborted by user!")
}
}
return nil
}
err = lp.Run()
if err != nil {
return
}
ds := lp.DeathSignalName()
if ds != "" {
fmt.Println("Killed by signal: ", ds)
lp.KillIfSignalled()
return
}
if len(clipboard_contents) > 0 {
_, err = os.Stdout.Write(clipboard_contents)
if err != nil {
err = fmt.Errorf("Failed to write to STDOUT with error: %w", err)
}
}
return
}

32
kittens/clipboard/main.go Normal file
View File

@ -0,0 +1,32 @@
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package clipboard
import (
"os"
"kitty/tools/cli"
)
func run_mime_loop(opts *Options, args []string) (err error) {
cwd, err = os.Getwd()
if err != nil {
return err
}
if opts.GetClipboard {
return run_get_loop(opts, args)
}
return run_set_loop(opts, args)
}
func clipboard_main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) {
if len(args) > 0 {
return 0, run_mime_loop(opts, args)
}
return 0, run_plain_text_loop(opts)
}
func EntryPoint(parent *cli.Command) {
create_cmd(parent, clipboard_main)
}

View File

@ -1,152 +1,91 @@
#!/usr/bin/env python3
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import codecs
import io
import os
import select
import sys
from typing import List, NoReturn, Optional
from kitty.cli import parse_args
from kitty.cli_stub import ClipboardCLIOptions
from kitty.fast_data_types import parse_input_from_terminal
from ..tui.operations import (
raw_mode, request_from_clipboard, write_to_clipboard
)
OPTIONS = r'''
--get-clipboard
default=False
--get-clipboard -g
type=bool-set
Output the current contents of the clipboard to STDOUT. Note that by default
kitty will prompt for permission to access the clipboard. Can be controlled
by :opt:`clipboard_control`.
--use-primary
default=False
--use-primary -p
type=bool-set
Use the primary selection rather than the clipboard on systems that support it,
such as X11.
such as Linux.
--mime -m
type=list
The mimetype of the specified file. Useful when the auto-detected mimetype is
likely to be incorrect or the filename has no extension and therefore no mimetype
can be detected. If more than one file is specified, this option should be specified multiple
times, once for each specified file. When copying data from the clipboard, you can use wildcards
to match MIME types. For example: :code:`--mime 'text/*'` will match any textual MIME type
available on the clipboard, usually the first matching MIME type is copied. The special MIME
type :code:`.` will return the list of available MIME types currently on the system clipboard.
--alias -a
type=list
Specify aliases for MIME types. Aliased MIME types are considered equivalent.
When copying to clipboard both the original and alias are made available on the
clipboard. When copying from clipboard if the original is not found, the alias
is used, as a fallback. Can be specified multiple times to create multiple
aliases. For example: :code:`--alias text/plain=text/x-rst` makes :code:`text/plain` an alias
of :code:`text/rst`. Aliases are not used in filter mode. An alias for
:code:`text/plain` is automatically created if :code:`text/plain` is not present in the input data, but some
other :code:`text/*` MIME is present.
--wait-for-completion
default=False
type=bool-set
Wait till the copy to clipboard is complete before exiting. Useful if running
the kitten in a dedicated, ephemeral window.
the kitten in a dedicated, ephemeral window. Only needed in filter mode.
'''.format
help_text = '''\
Read or write to the system clipboard.
To set the clipboard text, pipe in the new text on STDIN. Use the
:option:`--get-clipboard` option to output the current clipboard contents to
:file:`stdout`. Note that reading the clipboard will cause a permission
This kitten operates most simply in :italic:`filter mode`.
To set the clipboard text, pipe in the new text on :file:`STDIN`. Use the
:option:`--get-clipboard` option to output the current clipboard text content to
:file:`STDOUT`. Note that copying from the clipboard will cause a permission
popup, see :opt:`clipboard_control` for details.
For more control, specify filename arguments. Then, different MIME types can be copied to/from
the clipboard. Some examples:
.. code:: sh
# Copy an image to the clipboard:
kitty +kitten clipboard picture.png
# Copy an image and some text to the clipboard:
kitty +kitten clipboard picture.jpg text.txt
# Copy text from STDIN and an image to the clipboard:
echo hello | kitty +kitten clipboard picture.png /dev/stdin
# Copy any raster image available on the clipboard to a PNG file:
kitty +kitten clipboard -g picture.png
# Copy an image to a file and text to STDOUT:
kitty +kitten clipboard -g picture.png /dev/stdout
# List the formats available on the system clipboard
kitty +kitten clipboard -g -m . /dev/stdout
'''
usage = ''
got_capability_response = False
got_clipboard_response = False
clipboard_contents = ''
clipboard_from_primary = False
def ignore(x: str) -> None:
pass
def on_text(x: str) -> None:
if '\x03' in x:
raise KeyboardInterrupt()
if '\x04' in x:
raise EOFError()
def on_dcs(dcs: str) -> None:
global got_capability_response
if dcs.startswith('1+r'):
got_capability_response = True
def on_osc(osc: str) -> None:
global clipboard_contents, clipboard_from_primary, got_clipboard_response
idx = osc.find(';')
if idx <= 0:
return
q = osc[:idx]
if q == '52':
got_clipboard_response = True
widx = osc.find(';', idx + 1)
if widx < idx:
clipboard_from_primary = osc.find('p', idx + 1) > -1
clipboard_contents = ''
else:
from base64 import standard_b64decode
clipboard_from_primary = osc.find('p', idx+1, widx) > -1
data = memoryview(osc.encode('ascii'))
clipboard_contents = standard_b64decode(data[widx+1:]).decode('utf-8')
def wait_loop(tty_fd: int) -> None:
os.set_blocking(tty_fd, False)
decoder = codecs.getincrementaldecoder('utf-8')('ignore')
with raw_mode(tty_fd):
buf = ''
while not got_capability_response and not got_clipboard_response:
rd = select.select([tty_fd], [], [])[0]
if rd:
raw = os.read(tty_fd, io.DEFAULT_BUFFER_SIZE)
if not raw:
raise EOFError()
data = decoder.decode(raw)
buf = (buf + data) if buf else data
buf = parse_input_from_terminal(on_text, on_dcs, ignore, on_osc, ignore, ignore, buf, False)
def main(args: List[str]) -> NoReturn:
cli_opts, items = parse_args(args[1:], OPTIONS, usage, help_text, 'kitty +kitten clipboard', result_class=ClipboardCLIOptions)
if items:
raise SystemExit('Unrecognized extra command line arguments')
data: Optional[bytes] = None
if not sys.stdin.isatty():
data = sys.stdin.buffer.read()
wait_for_capability_response = False
data_to_write = []
if data:
data_to_write.append(write_to_clipboard(data, cli_opts.use_primary).encode('ascii'))
if not cli_opts.get_clipboard and cli_opts.wait_for_completion:
data_to_write.append(b'\x1bP+q544e\x1b\\')
wait_for_capability_response = True
if cli_opts.get_clipboard:
data_to_write.append(request_from_clipboard(cli_opts.use_primary).encode('ascii'))
wait_for_capability_response = True
tty_fd = os.open(os.ctermid(), os.O_RDWR | os.O_CLOEXEC)
retcode = 0
with open(tty_fd, 'wb', closefd=True) as ttyf:
for x in data_to_write:
ttyf.write(x)
ttyf.flush()
if wait_for_capability_response:
try:
wait_loop(tty_fd)
except KeyboardInterrupt:
sys.excepthook = lambda *a: None
raise
except EOFError:
retcode = 1
if clipboard_contents:
print(end=clipboard_contents)
raise SystemExit(retcode)
usage = '[files to copy to/from]'
if __name__ == '__main__':
main(sys.argv)
raise SystemExit('This should be run as kitten clipboard')
elif __name__ == '__doc__':
from kitty.cli import CompletionSpec
cd = sys.cli_docs # type: ignore
cd['usage'] = usage
cd['options'] = OPTIONS
cd['help_text'] = help_text
cd['short_desc'] = 'Copy/paste with the system clipboard, even over SSH'
cd['args_completion'] = CompletionSpec.from_string('type:file mime:* group:Files')

456
kittens/clipboard/read.go Normal file
View File

@ -0,0 +1,456 @@
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package clipboard
import (
"bytes"
"encoding/base64"
"fmt"
"image"
"os"
"path/filepath"
"strings"
"sync"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/images"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
var _ = fmt.Print
var cwd string
const OSC_NUMBER = "5522"
type Output struct {
arg string
ext string
arg_is_stream bool
mime_type string
remote_mime_type string
image_needs_conversion bool
is_stream bool
dest_is_tty bool
dest *os.File
err error
started bool
all_data_received bool
}
func (self *Output) cleanup() {
if self.dest != nil {
self.dest.Close()
if !self.is_stream {
os.Remove(self.dest.Name())
}
self.dest = nil
}
}
func (self *Output) add_data(data []byte) {
if self.err != nil {
return
}
if self.dest == nil {
if !self.image_needs_conversion && self.arg_is_stream {
self.is_stream = true
self.dest = os.Stdout
if self.arg == "/dev/stderr" {
self.dest = os.Stderr
}
self.dest_is_tty = tty.IsTerminal(self.dest.Fd())
} else {
d := cwd
if strings.ContainsRune(self.arg, os.PathSeparator) && !self.arg_is_stream {
d = filepath.Dir(self.arg)
}
f, err := os.CreateTemp(d, "."+filepath.Base(self.arg))
if err != nil {
self.err = err
return
}
self.dest = f
}
self.started = true
}
if self.dest_is_tty {
data = bytes.ReplaceAll(data, utils.UnsafeStringToBytes("\n"), utils.UnsafeStringToBytes("\r\n"))
}
_, self.err = self.dest.Write(data)
}
func (self *Output) write_image(img image.Image) (err error) {
var output *os.File
if self.arg_is_stream {
output = os.Stdout
if self.arg == "/dev/stderr" {
output = os.Stderr
}
} else {
output, err = os.Create(self.arg)
if err != nil {
return err
}
}
defer func() {
output.Close()
if err != nil && !self.arg_is_stream {
os.Remove(output.Name())
}
}()
return images.Encode(output, img, self.mime_type)
}
func (self *Output) commit() {
if self.err != nil {
return
}
if self.image_needs_conversion {
self.dest.Seek(0, os.SEEK_SET)
img, _, err := image.Decode(self.dest)
self.dest.Close()
os.Remove(self.dest.Name())
if err == nil {
err = self.write_image(img)
}
if err != nil {
self.err = fmt.Errorf("Failed to encode image data to %s with error: %w", self.mime_type, err)
}
} else {
self.dest.Close()
if !self.is_stream {
f, err := os.OpenFile(self.arg, os.O_CREATE|os.O_RDONLY, 0666)
if err == nil {
fi, err := f.Stat()
if err == nil {
self.dest.Chmod(fi.Mode().Perm())
}
f.Close()
os.Remove(f.Name())
}
self.err = os.Rename(self.dest.Name(), self.arg)
if self.err != nil {
os.Remove(self.dest.Name())
self.err = fmt.Errorf("Failed to rename temporary file used for downloading to destination: %s with error: %w", self.arg, self.err)
}
}
}
self.dest = nil
}
func (self *Output) assign_mime_type(available_mimes []string, aliases map[string][]string) (err error) {
if self.mime_type == "." {
self.remote_mime_type = "."
return
}
if slices.Contains(available_mimes, self.mime_type) {
self.remote_mime_type = self.mime_type
return
}
if len(aliases[self.mime_type]) > 0 {
for _, alias := range aliases[self.mime_type] {
if slices.Contains(available_mimes, alias) {
self.remote_mime_type = alias
return
}
}
}
for _, mt := range available_mimes {
if matched, _ := filepath.Match(self.mime_type, mt); matched {
self.remote_mime_type = mt
return
}
}
if images.EncodableImageTypes[self.mime_type] {
for _, mt := range available_mimes {
if images.DecodableImageTypes[mt] {
self.remote_mime_type = mt
self.image_needs_conversion = true
return
}
}
}
if is_textual_mime(self.mime_type) {
for _, mt := range available_mimes {
if mt == "text/plain" {
self.remote_mime_type = mt
return
}
}
}
return fmt.Errorf("The MIME type %s for %s not available on the clipboard", self.mime_type, self.arg)
}
func escape_metadata_value(k, x string) (ans string) {
if k == "mime" {
x = base64.StdEncoding.EncodeToString(utils.UnsafeStringToBytes(x))
}
return x
}
func unescape_metadata_value(k, x string) (ans string) {
if k == "mime" {
b, err := base64.StdEncoding.DecodeString(x)
if err == nil {
x = string(b)
}
}
return x
}
func encode_bytes(metadata map[string]string, payload []byte) string {
ans := strings.Builder{}
ans.Grow(2048)
ans.WriteString("\x1b]")
ans.WriteString(OSC_NUMBER)
ans.WriteString(";")
for k, v := range metadata {
if !strings.HasSuffix(ans.String(), ";") {
ans.WriteString(":")
}
ans.WriteString(k)
ans.WriteString("=")
ans.WriteString(escape_metadata_value(k, v))
}
if len(payload) > 0 {
ans.WriteString(";")
ans.WriteString(base64.StdEncoding.EncodeToString(payload))
}
ans.WriteString("\x1b\\")
return ans.String()
}
func encode(metadata map[string]string, payload string) string {
return encode_bytes(metadata, utils.UnsafeStringToBytes(payload))
}
func error_from_status(status string) error {
switch status {
case "ENOSYS":
return fmt.Errorf("no primary selection available on this system")
case "EPERM":
return fmt.Errorf("permission denied")
case "EBUSY":
return fmt.Errorf("a temporary error occurred, try again later.")
default:
return fmt.Errorf("%s", status)
}
}
func parse_escape_code(etype loop.EscapeCodeType, data []byte) (metadata map[string]string, payload []byte, err error) {
if etype != loop.OSC || !bytes.HasPrefix(data, utils.UnsafeStringToBytes(OSC_NUMBER+";")) {
return
}
parts := bytes.SplitN(data, utils.UnsafeStringToBytes(";"), 3)
metadata = make(map[string]string)
if len(parts) > 2 && len(parts[2]) > 0 {
payload, err = base64.StdEncoding.DecodeString(utils.UnsafeBytesToString(parts[2]))
if err != nil {
err = fmt.Errorf("Received OSC %s packet from terminal with invalid base64 encoded payload", OSC_NUMBER)
return
}
}
if len(parts) > 1 {
for _, record := range bytes.Split(parts[1], utils.UnsafeStringToBytes(":")) {
rp := bytes.SplitN(record, utils.UnsafeStringToBytes("="), 2)
v := ""
if len(rp) == 2 {
v = string(rp[1])
}
k := string(rp[0])
metadata[k] = unescape_metadata_value(k, v)
}
}
return
}
func parse_aliases(raw []string) (map[string][]string, error) {
ans := make(map[string][]string, len(raw))
for _, x := range raw {
k, v, found := strings.Cut(x, "=")
if !found {
return nil, fmt.Errorf("%s is not valid MIME alias specification", x)
}
ans[k] = append(ans[k], v)
ans[v] = append(ans[v], k)
}
return ans, nil
}
func run_get_loop(opts *Options, args []string) (err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
if err != nil {
return err
}
var available_mimes []string
var wg sync.WaitGroup
var getting_data_for string
requested_mimes := make(map[string]*Output)
reading_available_mimes := true
outputs := make([]*Output, len(args))
aliases, merr := parse_aliases(opts.Alias)
if merr != nil {
return merr
}
for i, arg := range args {
outputs[i] = &Output{arg: arg, arg_is_stream: arg == "/dev/stdout" || arg == "/dev/stderr", ext: filepath.Ext(arg)}
if len(opts.Mime) > i {
outputs[i].mime_type = opts.Mime[i]
} else {
if outputs[i].arg_is_stream {
outputs[i].mime_type = "text/plain"
} else {
outputs[i].mime_type = utils.GuessMimeType(outputs[i].arg)
}
}
if outputs[i].mime_type == "" {
return fmt.Errorf("Could not detect the MIME type for: %s use --mime to specify it manually", arg)
}
}
defer func() {
for _, o := range outputs {
if o.dest != nil {
o.cleanup()
}
}
}()
basic_metadata := map[string]string{"type": "read"}
if opts.UsePrimary {
basic_metadata["loc"] = "primary"
}
lp.OnInitialize = func() (string, error) {
lp.QueueWriteString(encode(basic_metadata, "."))
return "", nil
}
lp.OnEscapeCode = func(etype loop.EscapeCodeType, data []byte) (err error) {
metadata, payload, err := parse_escape_code(etype, data)
if err != nil {
return err
}
if metadata == nil {
return nil
}
if reading_available_mimes {
switch metadata["status"] {
case "DATA":
available_mimes = utils.Map(strings.TrimSpace, strings.Split(utils.UnsafeBytesToString(payload), " "))
case "OK":
case "DONE":
reading_available_mimes = false
if len(available_mimes) == 0 {
return fmt.Errorf("The clipboard is empty")
}
for _, o := range outputs {
err = o.assign_mime_type(available_mimes, aliases)
if err != nil {
return err
}
if o.remote_mime_type == "." {
o.started = true
o.add_data(utils.UnsafeStringToBytes(strings.Join(available_mimes, "\n")))
o.all_data_received = true
} else {
requested_mimes[o.remote_mime_type] = o
}
}
if len(requested_mimes) > 0 {
lp.QueueWriteString(encode(basic_metadata, strings.Join(maps.Keys(requested_mimes), " ")))
} else {
lp.Quit(0)
}
default:
return fmt.Errorf("Failed to read list of available data types in the clipboard with error: %w", error_from_status(metadata["status"]))
}
} else {
switch metadata["status"] {
case "DATA":
current_mime := metadata["mime"]
o := requested_mimes[current_mime]
if o != nil {
if getting_data_for != current_mime {
if prev := requested_mimes[getting_data_for]; prev != nil && !prev.all_data_received {
prev.all_data_received = true
wg.Add(1)
go func() {
prev.commit()
wg.Done()
}()
}
getting_data_for = current_mime
}
if !o.all_data_received {
o.add_data(payload)
}
}
case "OK":
case "DONE":
if prev := requested_mimes[getting_data_for]; getting_data_for != "" && prev != nil && !prev.all_data_received {
prev.all_data_received = true
wg.Add(1)
go func() {
prev.commit()
wg.Done()
}()
getting_data_for = ""
}
lp.Quit(0)
default:
return fmt.Errorf("Failed to read data from the clipboard with error: %w", error_from_status(metadata["status"]))
}
}
return
}
esc_count := 0
lp.OnKeyEvent = func(event *loop.KeyEvent) error {
if event.MatchesPressOrRepeat("ctrl+c") || event.MatchesPressOrRepeat("esc") {
event.Handled = true
esc_count++
if esc_count < 2 {
key := "Esc"
if event.MatchesPressOrRepeat("ctrl+c") {
key = "Ctrl+C"
}
lp.QueueWriteString(fmt.Sprintf("Waiting for response from terminal, press %s again to abort. This could cause garbage to be spewed to the screen.\r\n", key))
} else {
return fmt.Errorf("Aborted by user!")
}
}
return nil
}
err = lp.Run()
wg.Wait()
if err != nil {
return
}
ds := lp.DeathSignalName()
if ds != "" {
fmt.Println("Killed by signal: ", ds)
lp.KillIfSignalled()
return
}
for _, o := range outputs {
if o.err != nil {
err = fmt.Errorf("Failed to get %s with error: %w", o.arg, o.err)
return
}
if !o.started {
err = fmt.Errorf("No data for %s with MIME type: %s", o.arg, o.mime_type)
return
}
}
return
}

229
kittens/clipboard/write.go Normal file
View File

@ -0,0 +1,229 @@
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package clipboard
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print
type Input struct {
src io.Reader
arg string
ext string
is_stream bool
mime_type string
extra_mime_types []string
}
func is_textual_mime(x string) bool {
return strings.HasPrefix(x, "text/") || utils.KnownTextualMimes[x]
}
func is_text_plain_mime(x string) bool {
return x == "text/plain"
}
func (self *Input) has_mime_matching(predicate func(string) bool) bool {
if predicate(self.mime_type) {
return true
}
for _, i := range self.extra_mime_types {
if predicate(i) {
return true
}
}
return false
}
func write_loop(inputs []*Input, opts *Options) (err error) {
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
if err != nil {
return err
}
var waiting_for_write loop.IdType
var buf [4096]byte
aliases, aerr := parse_aliases(opts.Alias)
if aerr != nil {
return aerr
}
num_text_mimes := 0
has_text_plain := false
for _, i := range inputs {
i.extra_mime_types = aliases[i.mime_type]
if i.has_mime_matching(is_textual_mime) {
num_text_mimes++
if !has_text_plain && i.has_mime_matching(is_text_plain_mime) {
has_text_plain = true
}
}
}
if num_text_mimes > 0 && !has_text_plain {
for _, i := range inputs {
if i.has_mime_matching(is_textual_mime) {
i.extra_mime_types = append(i.extra_mime_types, "text/plain")
break
}
}
}
make_metadata := func(ptype, mime string) map[string]string {
ans := map[string]string{"type": ptype}
if opts.UsePrimary {
ans["loc"] = "primary"
}
if mime != "" {
ans["mime"] = mime
}
return ans
}
lp.OnInitialize = func() (string, error) {
waiting_for_write = lp.QueueWriteString(encode(make_metadata("write", ""), ""))
return "", nil
}
write_chunk := func() error {
if len(inputs) == 0 {
return nil
}
i := inputs[0]
n, err := i.src.Read(buf[:])
if n > 0 {
waiting_for_write = lp.QueueWriteString(encode_bytes(make_metadata("wdata", i.mime_type), buf[:n]))
}
if err != nil {
if errors.Is(err, io.EOF) {
if len(i.extra_mime_types) > 0 {
lp.QueueWriteString(encode(make_metadata("walias", i.mime_type), strings.Join(i.extra_mime_types, " ")))
}
inputs = inputs[1:]
if len(inputs) == 0 {
lp.QueueWriteString(encode(make_metadata("wdata", ""), ""))
waiting_for_write = 0
}
return lp.OnWriteComplete(waiting_for_write)
}
return fmt.Errorf("Failed to read from %s with error: %w", i.arg, err)
}
return nil
}
lp.OnWriteComplete = func(msg_id loop.IdType) error {
if waiting_for_write == msg_id {
return write_chunk()
}
return nil
}
lp.OnEscapeCode = func(etype loop.EscapeCodeType, data []byte) (err error) {
metadata, _, err := parse_escape_code(etype, data)
if err != nil {
return err
}
if metadata != nil && metadata["type"] == "write" {
switch metadata["status"] {
case "DONE":
lp.Quit(0)
case "EIO":
return fmt.Errorf("Could not write to clipboard an I/O error occurred while the terminal was processing the data")
case "EINVAL":
return fmt.Errorf("Could not write to clipboard base64 encoding invalid")
case "ENOSYS":
return fmt.Errorf("Could not write to primary selection as the system does not support it")
case "EPERM":
return fmt.Errorf("Could not write to clipboard as permission was denied")
case "EBUSY":
return fmt.Errorf("Could not write to clipboard, a temporary error occurred, try again later.")
default:
return fmt.Errorf("Could not write to clipboard unknowns status returned from terminal: %#v", metadata["status"])
}
}
return
}
esc_count := 0
lp.OnKeyEvent = func(event *loop.KeyEvent) error {
if event.MatchesPressOrRepeat("ctrl+c") || event.MatchesPressOrRepeat("esc") {
event.Handled = true
esc_count++
if esc_count < 2 {
key := "Esc"
if event.MatchesPressOrRepeat("ctrl+c") {
key = "Ctrl+C"
}
lp.QueueWriteString(fmt.Sprintf("Waiting for response from terminal, press %s again to abort. This could cause garbage to be spewed to the screen.\r\n", key))
} else {
return fmt.Errorf("Aborted by user!")
}
}
return nil
}
err = lp.Run()
if err != nil {
return
}
ds := lp.DeathSignalName()
if ds != "" {
fmt.Println("Killed by signal: ", ds)
lp.KillIfSignalled()
return
}
return
}
func run_set_loop(opts *Options, args []string) (err error) {
inputs := make([]*Input, len(args))
to_process := make([]*Input, len(args))
defer func() {
for _, i := range inputs {
if i.src != nil {
rc, ok := i.src.(io.Closer)
if ok {
rc.Close()
}
}
}
}()
for i, arg := range args {
if arg == "/dev/stdin" {
f, _, err := preread_stdin()
if err != nil {
return err
}
inputs[i] = &Input{arg: arg, src: f, is_stream: true}
} else {
f, err := os.Open(arg)
if err != nil {
return fmt.Errorf("Failed to open %s with error: %w", arg, err)
}
inputs[i] = &Input{arg: arg, src: f, ext: filepath.Ext(arg)}
}
if i < len(opts.Mime) {
inputs[i].mime_type = opts.Mime[i]
} else if inputs[i].is_stream {
inputs[i].mime_type = "text/plain"
} else if inputs[i].ext != "" {
inputs[i].mime_type = utils.GuessMimeType(inputs[i].arg)
}
if inputs[i].mime_type == "" {
return fmt.Errorf("Could not guess MIME type for %s use the --mime option to specify a MIME type", arg)
}
to_process[i] = inputs[i]
if to_process[i].is_stream {
}
}
return write_loop(to_process, opts)
}

View File

@ -1 +0,0 @@
See https://sw.kovidgoyal.net/kitty/kittens/diff/

Some files were not shown because too many files have changed in this diff Show More