Compare commits

..

25 Commits

Author SHA1 Message Date
Kovid Goyal
73db717a0c version 0.19.1 2020-10-06 14:03:25 +05:30
Kovid Goyal
f1552c8354 Avoid alias related complications with completion delegation for hyperlinked_grep 2020-10-06 13:53:41 +05:30
Kovid Goyal
fb87fc32f0 Fix a regression that caused a segfault when using scrollback_pager_history_size
Fixes #3011
2020-10-06 13:28:48 +05:30
Kovid Goyal
b04b0c670d Fix #3010
Probably ancient version of Python
2020-10-06 12:09:47 +05:30
Kovid Goyal
b33845df8a Update Changelog 2020-10-06 06:50:29 +05:30
Kovid Goyal
12c9d8d8f8 Delay load the ipaddress module 2020-10-06 06:50:17 +05:30
Kovid Goyal
fe97bbcbbf Merge branch 'master' of https://github.com/Sighery/kitty into master 2020-10-06 06:45:05 +05:30
Sighery
10533c3eba Hints kitten: validate IPs with ipaddress
On the initial commit of this feature, IPs were just matched with a
very simple regex that prioritised simplicity/readability over
accuracy.

This commit adds a postprocessor for ip matches that makes use of
Python's `ipaddress` in the standard library to validate all the IP
matches.

This way we don't need huge and complex regex patterns to match _and_
validate the IPs, and we can just use `ipaddress` to abstract us from
implementing all the validation logic into the regex pattern.
2020-10-05 20:11:25 +02:00
Sighery
b4415c90f9 Hints kitten: add support for IPs (v4 and v6)
It selects v4 and v6 IPs with a simple regex that doesn't actually
check for the validity of the IPs.
2020-10-05 20:11:22 +02:00
Kovid Goyal
2970bbdf6f Update GA tags
Also auto gen docs if running publish only for website
2020-10-05 20:04:32 +05:30
Kovid Goyal
95a420534d Remove the old asciidoc files
By now hopefully the kitty website is well established
2020-10-05 19:34:02 +05:30
Kovid Goyal
be56a21574 ... 2020-10-05 19:33:09 +05:30
Kovid Goyal
3741a235fe Merge branch 'patch-1' of https://github.com/Nudin/kitty into master 2020-10-05 19:28:22 +05:30
Michael F. Schönitzer
523b6c4c2d Fix wrong kittenname in documentation
It's called `hyperlinked_grep` not `hyperlink_grep`.
2020-10-05 15:54:11 +02:00
Kovid Goyal
c3b2300310 Merge branch 'remove-outdated-check' of https://github.com/Luflosi/kitty into master 2020-10-05 18:16:06 +05:30
Luflosi
1c4a20d86f Remove outdated Python version check
The Python version is already checked at the top of the file. That check was added in 81a58186c6.
2020-10-05 14:41:07 +02:00
Kovid Goyal
f5af475012 Merge branch 'notification_fix' of https://github.com/nertpinx/kitty into master 2020-10-05 18:09:35 +05:30
Martin Kletzander
f149b74332 Fix repeated version notifications
Without this fix the file with the list of notifications looks like this:
```
0.19.0,1601899026.4373078,<built-in method count of Notification object at 0x7f8c582193b0>
```
which ends up notifying about a new version all the time.
2020-10-05 14:27:47 +02:00
Kovid Goyal
8cd51386cb Fix some typos in the OSC 99 spec 2020-10-05 17:27:41 +05:30
Kovid Goyal
fb2cca88df Merge branch 'pip3-in-ci' of https://github.com/Luflosi/kitty into master 2020-10-04 21:23:29 +05:30
Luflosi
031d4dc85a Use pip3 instead of pip for CI
There was a warning when the CI executed the "macOS Brew" job:
```
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
```
To fix this, use pip3 instead of pip.
2020-10-04 17:47:41 +02:00
Kovid Goyal
bf66d1c0f5 Merge branch 'glfw_upstream' of https://github.com/Luflosi/kitty into master 2020-10-04 21:13:48 +05:30
Luflosi
0edfa88755 Reduce the difference of GLFW to upstream 2020-10-04 17:34:51 +02:00
Kovid Goyal
dba1f3bcbc Merge branch 'add-comment' of https://github.com/Luflosi/kitty into master 2020-10-04 21:01:12 +05:30
Luflosi
e204cc8f12 Add comment on how to call send_test_notification() 2020-10-04 17:23:50 +02:00
18 changed files with 119 additions and 36 deletions

View File

@@ -40,7 +40,7 @@ def install_deps():
if is_bundle:
install_bundle()
else:
run('pip install Pillow pygments')
run('pip3 install Pillow pygments')
def build_kitty():

View File

@@ -4,6 +4,18 @@ Changelog
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
To update |kitty|, :doc:`follow the instructions <binary>`.
0.19.1 [2020-10-06]
-------------------
- hints kitten: Add an ``ip`` type for easy selection of IP addresses
(:pull:`3009`)
- Fix a regression that caused a segfault when using
:opt:`scrollback_pager_history_size` and it needs to be expanded (:iss:`3011`)
- Fix update available notifications repeating (:pull:`3006`)
0.19.0 [2020-10-04]
-------------------

View File

@@ -34,7 +34,7 @@ you use some editor other than vim, you should adjust the
Finally, add an alias to your shell's rc files to invoke the kitten as ``hg``::
alias hg='kitty +kitten hyperlink_grep'
alias hg='kitty +kitten hyperlinked_grep'
You can now run searches with::
@@ -42,10 +42,17 @@ You can now run searches with::
hg some-search-term
If you want to enable completion, for the kitten, you can delegate completion
to rg. For ZSH, you do that with::
to rg. For that, instead of using an alias create a simple wrapper script named
:file:`hg` somewhere in your ``PATH``:
compdef _rg kitty +kitten hyperlinked_grep
.. code-block:: sh
#!/bin/sh
exec kitty +kitten hyperlinked_grep "$@"
Then, for example, for ZSH, add the following to :file:`.zshrc`::
compdef _rg hg
To learn more about kitty's powerful framework for customizing URL click
actions, :doc:`see here <../open_actions>`.

View File

@@ -250,12 +250,13 @@ The escape code has the form::
<OSC> 99 ; metadata ; payload <terminator>
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is :code:`<ESC><backslash>`. The
metadata is a section of colon separated :code:`key=value` pairs. Every key
must be a single character from the set :code:`[a-zA-Z]` and every value must
be a character from the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The
payload must be interpreted based on the metadata section. The two semi-colons
*must* always be present even when no metadata is present.
Here ``<OSC>`` is :code:`<ESC>]` and ``<terminator>`` is
:code:`<ESC><backslash>`. The metadata is a section of colon separated
:code:`key=value` pairs. Every key must be a single character from the set
:code:`a-zA-Z` and every value must be a word consisting of characters from
the set :code:`a-zA-Z0-9-_/\+.,(){}[]*&^%$#@!`~`. The payload must be
interpreted based on the metadata section. The two semi-colons *must* always be
present even when no metadata is present.
Before going into details, lets see how one can display a simple, single line
notification from a shell script::
@@ -297,7 +298,7 @@ was activated. This is controlled by the ``a`` key which takes a comma
separated set of values, ``report`` and ``focus``. The value ``focus`` means
focus the window from which the notification was issued and is the default.
``report`` means send an escape code back to the application. The format of the
escape code is::
returned escape code is::
<OSC> 99 ; i=identifier ; <terminator>
@@ -322,7 +323,7 @@ to display it based on what it does understand.
allow displaying custom icons on a notification, at all, it was decided to
leave it out of the spec for the time being.
Similarly, features such a scheduled notifications could be added in future
Similarly, features such as scheduled notifications could be added in future
revisions.

View File

@@ -529,7 +529,6 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
*width = (int)frameRect.size.width;
if (height)
*height = (int)frameRect.size.height;
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)

View File

@@ -1595,10 +1595,10 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
else
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
[window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
else
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
}
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window, int widthincr, int heightincr)

View File

@@ -1 +0,0 @@
See https://sw.kovidgoyal.net/kitty/graphics-protocol.html

View File

@@ -1 +0,0 @@
See https://sw.kovidgoyal.net/kitty/key-encoding.html

View File

@@ -236,6 +236,11 @@ def postprocessor(func: PostprocessorFunc) -> PostprocessorFunc:
return func
class InvalidMatch(Exception):
"""Raised when a match turns out to be invalid."""
pass
@postprocessor
def url(text: str, s: int, e: int) -> Tuple[int, int]:
if s > 4 and text[s - 5:s] == 'link:': # asciidoc URLs
@@ -280,11 +285,29 @@ def quotes(text: str, s: int, e: int) -> Tuple[int, int]:
return s, e
@postprocessor
def ip(text: str, s: int, e: int) -> Tuple[int, int]:
from ipaddress import ip_address
# Check validity of IPs (or raise InvalidMatch)
ip = text[s:e]
try:
ip_address(ip)
except Exception:
raise InvalidMatch("Invalid IP")
return s, e
def mark(pattern: str, post_processors: Iterable[PostprocessorFunc], text: str, args: HintsCLIOptions) -> Generator[Mark, None, None]:
pat = re.compile(pattern)
for idx, (s, e, groupdict) in enumerate(regex_finditer(pat, args.minimum_match_length, text)):
for func in post_processors:
s, e = func(text, s, e)
try:
for func in post_processors:
s, e = func(text, s, e)
except InvalidMatch:
continue
mark_text = text[s:e].replace('\n', '').replace('\0', '')
yield Mark(idx, s, e, mark_text, groupdict)
@@ -325,6 +348,15 @@ def functions_for(args: HintsCLIOptions) -> Tuple[str, List[PostprocessorFunc]]:
pattern = '(?m)^\\s*(.+)[\\s\0]*$'
elif args.type == 'hash':
pattern = '[0-9a-f]{7,128}'
elif args.type == 'ip':
pattern = (
# # IPv4 with no validation
r"((?:\d{1,3}\.){3}\d{1,3}"
r"|"
# # IPv6 with no validation
r"(?:[a-fA-F0-9]{0,4}:){2,7}[a-fA-F0-9]{1,4})"
)
post_processors.append(ip)
elif args.type == 'word':
chars = args.word_characters
if chars is None:
@@ -402,7 +434,7 @@ def process_hyperlinks(text: str) -> Tuple[str, Tuple[Mark, ...]]:
active_hyperlink_start_offset = 0
idx += 1
def process_hyperlink(m: re.Match) -> str:
def process_hyperlink(m: 're.Match') -> str:
nonlocal removed_size, active_hyperlink_url, active_hyperlink_id, active_hyperlink_start_offset
raw = m.group()
start = m.start() - removed_size
@@ -482,7 +514,7 @@ programs.
--type
default=url
choices=url,regex,path,line,hash,word,linenum,hyperlink
choices=url,regex,path,line,hash,word,linenum,hyperlink,ip
The type of text to search for. A value of :code:`linenum` is special, it looks
for error messages using the pattern specified with :option:`--regex`, which
must have the named groups, :code:`path` and :code:`line`. If not specified,

View File

@@ -1563,6 +1563,7 @@ class Boss:
for os_window_id in os_windows:
self.default_bg_changed_for(os_window_id)
# Can be called with kitty -o "map f1 send_test_notification"
def send_test_notification(self) -> None:
from time import monotonic

View File

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

View File

@@ -78,8 +78,8 @@ free_pagerhist(HistoryBuf *self) {
static inline bool
pagerhist_extend(PagerHistoryBuf *ph, size_t minsz) {
if (ph->buffer_size >= ph->max_sz) return false;
size_t newsz = ph->buffer_size + MAX(1024u * 1024u, minsz);
uint8_t *newbuf = PyMem_Malloc(MIN(ph->buffer_size + minsz, ph->max_sz));
size_t newsz = MIN(ph->max_sz, ph->buffer_size + MAX(1024u * 1024u, minsz));
uint8_t *newbuf = PyMem_Malloc(newsz);
if (!newbuf) return false;
size_t copied = MIN(ph->length, ph->buffer_size - ph->start);
if (copied) memcpy(newbuf, ph->buffer + ph->start, copied);

View File

@@ -90,7 +90,9 @@ def save_notification(version: Version) -> None:
for version in sorted(notified_versions):
n = notified_versions[version]
lines.append('{},{},{}'.format(
'.'.join(map(str, n.version)), n.time_of_last_notification, n.count))
'.'.join(map(str, n.version)),
n.time_of_last_notification,
n.notification_count))
atomic_save('\n'.join(lines).encode('utf-8'), version_notification_log())

View File

@@ -30,3 +30,31 @@ class TestHints(BaseTest):
t('link:{}[xxx]'.format(u), u)
t('`xyz <{}>`_.'.format(u), u)
t('<a href="{}">moo'.format(u), u)
def test_ip_hints(self):
from kittens.hints.main import parse_hints_args, functions_for, mark, convert_text
args = parse_hints_args(['--type', 'ip'])[0]
pattern, post_processors = functions_for(args)
def create_marks(text, cols=60):
text = convert_text(text, cols)
return tuple(mark(pattern, post_processors, text, args))
testcases = (
('100.64.0.0', ['100.64.0.0']),
('2001:0db8:0000:0000:0000:ff00:0042:8329', ['2001:0db8:0000:0000:0000:ff00:0042:8329']),
('2001:db8:0:0:0:ff00:42:8329', ['2001:db8:0:0:0:ff00:42:8329']),
('2001:db8::ff00:42:8329', ['2001:db8::ff00:42:8329']),
('2001:DB8::FF00:42:8329', ['2001:DB8::FF00:42:8329']),
('0000:0000:0000:0000:0000:0000:0000:0001', ['0000:0000:0000:0000:0000:0000:0000:0001']),
('::1', ['::1']),
# Invalid IPs won't match
('255.255.255.256', []),
(':1', []),
)
for testcase, expected in testcases:
with self.subTest(testcase=testcase, expected=expected):
marks = create_marks(testcase)
ips = [m.text for m in marks]
self.ae(ips, expected)

View File

@@ -1 +0,0 @@
See https://sw.kovidgoyal.net/kitty/protocol-extensions.html

View File

@@ -68,14 +68,15 @@ def run_html(args: Any) -> None:
def add_analytics() -> None:
analytics = '''
<!-- Google Analytics -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-20736318-2"></script>
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-20736318-2', 'auto');
ga('send', 'pageview');
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-20736318-2');
</script>
<script async="async" src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->\
'''
for dirpath, firnames, filenames in os.walk(publish_dir):
for fname in filenames:
@@ -87,6 +88,10 @@ ga('send', 'pageview');
f.write(html.encode('utf-8'))
def run_docs(args: Any) -> None:
subprocess.check_call(['make', 'docs'])
def run_website(args: Any) -> None:
if os.path.exists(publish_dir):
shutil.rmtree(publish_dir)
@@ -384,6 +389,8 @@ def main() -> None:
ans = 'n'
if ans.lower() != 'y':
return
if actions == ['website']:
actions.insert(0, 'docs')
for action in actions:
print('Running', action)
cwd = os.getcwd()

View File

@@ -1 +0,0 @@
See https://sw.kovidgoyal.net/kitty/remote-control.html

View File

@@ -1176,8 +1176,6 @@ def option_parser() -> argparse.ArgumentParser: # {{{
def main() -> None:
global verbose
if sys.version_info < (3, 5):
raise SystemExit('python >= 3.5 required')
args = option_parser().parse_args(namespace=Options())
verbose = args.verbose > 0
args.prefix = os.path.abspath(args.prefix)