Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
268d687814 | ||
|
|
71f8e50460 | ||
|
|
22fbdbca40 | ||
|
|
6253ee2a74 | ||
|
|
5b28aed0b1 | ||
|
|
9eabc9ecf1 | ||
|
|
a77852466c | ||
|
|
c68b82e4d0 |
@@ -35,6 +35,15 @@ mouse anywhere in the current command to move the cursor there. See
|
|||||||
Detailed list of changes
|
Detailed list of changes
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
0.26.1 [2022-08-30]
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- ssh kitten: Fix executable permission missing from kitty bootstrap script (:iss:`5438`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.26.0 that caused kitty to no longer set the ``LANG`` environment variable on macOS (:iss:`5439`)
|
||||||
|
|
||||||
|
- Allow specifying a title when using the :ac:`set_tab_title` action (:iss:`5441`)
|
||||||
|
|
||||||
0.26.0 [2022-08-29]
|
0.26.0 [2022-08-29]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -1579,10 +1579,28 @@ class Boss:
|
|||||||
def input_unicode_character(self) -> None:
|
def input_unicode_character(self) -> None:
|
||||||
self.run_kitten_with_metadata('unicode_input')
|
self.run_kitten_with_metadata('unicode_input')
|
||||||
|
|
||||||
@ac('tab', 'Change the title of the active tab')
|
@ac(
|
||||||
def set_tab_title(self) -> None:
|
'tab', '''
|
||||||
|
Change the title of the active tab interactively, by typing in the new title.
|
||||||
|
If you specify an argument to this action then that is used as the title instead of asking for it.
|
||||||
|
Use the empty string ("") to reset the title to default. For example::
|
||||||
|
|
||||||
|
# interactive usage
|
||||||
|
map f1 set_tab_title
|
||||||
|
# set a specific title
|
||||||
|
map f2 set_tab_title some title
|
||||||
|
# reset to default
|
||||||
|
map f3 set_tab_title ""
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
def set_tab_title(self, title: Optional[str] = None) -> None:
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
if tab:
|
if tab:
|
||||||
|
if title is not None:
|
||||||
|
if title in ('""', "''"):
|
||||||
|
title = ''
|
||||||
|
tab.set_title(title)
|
||||||
|
return
|
||||||
args = [
|
args = [
|
||||||
'--name=tab-title', '--message', _('Enter the new title for this tab below.'),
|
'--name=tab-title', '--message', _('Enter the new title for this tab below.'),
|
||||||
'--default', tab.name or tab.title, 'do_set_tab_title', str(tab.id)]
|
'--default', tab.name or tab.title, 'do_set_tab_title', str(tab.id)]
|
||||||
|
|||||||
@@ -168,6 +168,10 @@ def set_default_env(val: Optional[Dict[str, str]] = None) -> None:
|
|||||||
setattr(default_env, 'lc_ctype_set_by_user', has_lctype)
|
setattr(default_env, 'lc_ctype_set_by_user', has_lctype)
|
||||||
|
|
||||||
|
|
||||||
|
def set_LANG_in_default_env(val: str) -> None:
|
||||||
|
default_env()['LANG'] = val
|
||||||
|
|
||||||
|
|
||||||
def openpty() -> Tuple[int, int]:
|
def openpty() -> Tuple[int, int]:
|
||||||
master, slave = os.openpty() # Note that master and slave are in blocking mode
|
master, slave = os.openpty() # Note that master and slave are in blocking mode
|
||||||
os.set_inheritable(slave, True)
|
os.set_inheritable(slave, True)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class Version(NamedTuple):
|
|||||||
|
|
||||||
appname: str = 'kitty'
|
appname: str = 'kitty'
|
||||||
kitty_face = '🐱'
|
kitty_face = '🐱'
|
||||||
version: Version = Version(0, 26, 0)
|
version: Version = Version(0, 26, 1)
|
||||||
str_version: str = '.'.join(map(str, version))
|
str_version: str = '.'.join(map(str, version))
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos: bool = 'darwin' in _plat
|
is_macos: bool = 'darwin' in _plat
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from typing import Dict, Generator, List, Optional, Sequence, Tuple
|
|||||||
|
|
||||||
from .borders import load_borders_program
|
from .borders import load_borders_program
|
||||||
from .boss import Boss
|
from .boss import Boss
|
||||||
from .child import set_default_env
|
from .child import set_default_env, set_LANG_in_default_env
|
||||||
from .cli import create_opts, parse_args
|
from .cli import create_opts, parse_args
|
||||||
from .cli_stub import CLIOptions
|
from .cli_stub import CLIOptions
|
||||||
from .conf.utils import BadLine
|
from .conf.utils import BadLine
|
||||||
@@ -229,6 +229,7 @@ def ensure_macos_locale() -> None:
|
|||||||
else:
|
else:
|
||||||
log_error(f'Could not set LANG Cocoa returns language as: {lang}')
|
log_error(f'Could not set LANG Cocoa returns language as: {lang}')
|
||||||
os.environ['LANG'] = f'{lang}.UTF-8'
|
os.environ['LANG'] = f'{lang}.UTF-8'
|
||||||
|
set_LANG_in_default_env(os.environ['LANG'])
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
@@ -368,6 +369,7 @@ def set_locale() -> None:
|
|||||||
except Exception:
|
except Exception:
|
||||||
log_error('Failed to set locale with no LANG')
|
log_error('Failed to set locale with no LANG')
|
||||||
os.environ['LANG'] = old_lang
|
os.environ['LANG'] = old_lang
|
||||||
|
set_LANG_in_default_env(old_lang)
|
||||||
|
|
||||||
|
|
||||||
def _main() -> None:
|
def _main() -> None:
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ def detach_tab_parse(func: str, rest: str) -> FuncArgsType:
|
|||||||
return func, (rest,)
|
return func, (rest,)
|
||||||
|
|
||||||
|
|
||||||
@func_with_args('set_background_opacity', 'goto_layout', 'toggle_layout', 'kitty_shell', 'show_kitty_doc')
|
@func_with_args('set_background_opacity', 'goto_layout', 'toggle_layout', 'kitty_shell', 'show_kitty_doc', 'set_tab_title')
|
||||||
def simple_parse(func: str, rest: str) -> FuncArgsType:
|
def simple_parse(func: str, rest: str) -> FuncArgsType:
|
||||||
return func, [rest]
|
return func, [rest]
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import stat
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@@ -58,7 +59,15 @@ class TestBuild(BaseTest):
|
|||||||
self.assertTrue(os.path.isdir(terminfo_dir), f'Terminfo dir: {terminfo_dir}')
|
self.assertTrue(os.path.isdir(terminfo_dir), f'Terminfo dir: {terminfo_dir}')
|
||||||
self.assertTrue(os.path.exists(logo_png_file), f'Logo file: {logo_png_file}')
|
self.assertTrue(os.path.exists(logo_png_file), f'Logo file: {logo_png_file}')
|
||||||
self.assertTrue(os.path.exists(zsh), f'Shell integration: {zsh}')
|
self.assertTrue(os.path.exists(zsh), f'Shell integration: {zsh}')
|
||||||
self.assertTrue(os.access(os.path.join(shell_integration_dir, 'ssh', 'askpass.py'), os.X_OK))
|
|
||||||
|
def is_executable(x):
|
||||||
|
mode = os.stat(x).st_mode
|
||||||
|
q = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
|
||||||
|
return mode & q == q
|
||||||
|
|
||||||
|
for x in ('kitty', 'askpass.py'):
|
||||||
|
x = os.path.join(shell_integration_dir, 'ssh', x)
|
||||||
|
self.assertTrue(is_executable(x), f'{x} is not executable')
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
self.assertTrue(os.path.isdir(local_docs()), f'Local docs: {local_docs()}')
|
self.assertTrue(os.path.isdir(local_docs()), f'Local docs: {local_docs()}')
|
||||||
|
|
||||||
@@ -76,8 +85,8 @@ class TestBuild(BaseTest):
|
|||||||
del pygments
|
del pygments
|
||||||
|
|
||||||
def test_docs_url(self):
|
def test_docs_url(self):
|
||||||
from kitty.utils import docs_url
|
|
||||||
from kitty.constants import website_url
|
from kitty.constants import website_url
|
||||||
|
from kitty.utils import docs_url
|
||||||
|
|
||||||
def run_tests(p, base, suffix='.html'):
|
def run_tests(p, base, suffix='.html'):
|
||||||
def t(x, e):
|
def t(x, e):
|
||||||
|
|||||||
11
setup.py
11
setup.py
@@ -1363,10 +1363,19 @@ def package(args: Options, bundle_type: str) -> None:
|
|||||||
f.seek(0), f.truncate(), f.write(raw)
|
f.seek(0), f.truncate(), f.write(raw)
|
||||||
|
|
||||||
compile_python(libdir)
|
compile_python(libdir)
|
||||||
|
|
||||||
|
def should_be_executable(path: str) -> bool:
|
||||||
|
if path.endswith('.so'):
|
||||||
|
return True
|
||||||
|
q = path.split(os.sep)[-2:]
|
||||||
|
if len(q) == 2 and q[0] == 'ssh' and q[1] in ('askpass.py', 'kitty'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
for root, dirs, files in os.walk(libdir):
|
for root, dirs, files in os.walk(libdir):
|
||||||
for f_ in files:
|
for f_ in files:
|
||||||
path = os.path.join(root, f_)
|
path = os.path.join(root, f_)
|
||||||
os.chmod(path, 0o755 if f_.endswith('.so') or os.path.basename(f_) == 'askpass.py' else 0o644)
|
os.chmod(path, 0o755 if should_be_executable(path) else 0o644)
|
||||||
if not is_macos:
|
if not is_macos:
|
||||||
create_linux_bundle_gunk(ddir, args.libdir_name)
|
create_linux_bundle_gunk(ddir, args.libdir_name)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ if [[ -n "$KITTY_BASH_INJECT" ]]; then
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
builtin set +o posix
|
builtin set +o posix
|
||||||
builtin shopt -u inherit_errexit # resetting posix does not clear this
|
builtin shopt -u inherit_errexit 2>/dev/null # resetting posix does not clear this
|
||||||
if [[ -n "$KITTY_BASH_UNEXPORT_HISTFILE" ]]; then
|
if [[ -n "$KITTY_BASH_UNEXPORT_HISTFILE" ]]; then
|
||||||
builtin export -n HISTFILE
|
builtin export -n HISTFILE
|
||||||
builtin unset KITTY_BASH_UNEXPORT_HISTFILE
|
builtin unset KITTY_BASH_UNEXPORT_HISTFILE
|
||||||
|
|||||||
Reference in New Issue
Block a user