Use an env var for fish shell integration

Less intrusive (in some ways) than adding symlinks to ~/.config/fish
Exploits the fact that fish loads scripts from XDG_DATA_DIRS on startup.
Thanks to @page-down for noticing
This commit is contained in:
Kovid Goyal 2021-10-27 14:59:11 +05:30
parent d31935b8eb
commit d3a3f99848
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 42 additions and 40 deletions

View File

@ -17,6 +17,7 @@ from .cli import (
OptionDict, OptionSpecSeq, options_for_completion, parse_option_spec,
prettify
)
from .constants import shell_integration_dir
from .fast_data_types import truncate_point_for_length, wcswidth
from .rc.base import all_command_names, command_for_name
from .shell import options_for_cmd
@ -128,6 +129,11 @@ def remote_control_command_names() -> Tuple[str, ...]:
# Shell specific code {{{
def load_fish2_completion() -> str:
with open(os.path.join(shell_integration_dir, 'fish', 'vendor_completions.d', 'kitty.fish')) as f:
return f.read()
completion_scripts = {
'zsh': '''#compdef kitty
@ -140,7 +146,7 @@ _kitty() {
fi
}
compdef _kitty kitty
''',
'''.__str__,
'bash': '''
_kitty_completions() {
local src
@ -154,7 +160,7 @@ _kitty_completions() {
}
complete -o nospace -F _kitty_completions kitty
''',
'''.__str__,
'fish': '''
function __kitty_completions
# Send all words up to the one before the cursor
@ -162,15 +168,8 @@ function __kitty_completions
end
complete -f -c kitty -a "(__kitty_completions)"
''',
'fish2': '''
if functions -q _ksi_completions
complete -f -c kitty -a "(_ksi_completions)"
else
complete -f -c kitty -a "(commandline -cop | kitty +complete fish)"
end
''',
'''.__str__,
'fish2': load_fish2_completion,
}
ParseResult = Tuple[List[str], bool]
@ -670,7 +669,7 @@ def find_completions(words: Sequence[str], new_word: bool, entry_points: Iterabl
def setup(cstyle: str) -> None:
print(completion_scripts[cstyle])
print(completion_scripts[cstyle]())
def main(args: Sequence[str], entry_points: Iterable[str], namespaced_entry_points: Iterable[str]) -> None:

View File

@ -29,6 +29,7 @@ from .fonts.render import set_font_family
from .options.types import Options
from .os_window_size import initial_window_size_func
from .session import get_os_window_sizing_data
from .shell_integration import setup_shell_integration
from .types import SingleKey
from .utils import (
detach, expandvars, log_error, single_instance,
@ -150,9 +151,6 @@ def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = ())
if not is_wayland() and not is_macos: # no window icons on wayland
set_x11_window_icon()
load_shader_programs.use_selection_fg = opts.selection_foreground is not None
if opts.shell_integration != 'disabled':
from .shell_integration import setup_shell_integration
setup_shell_integration()
with cached_values_for(run_app.cached_values_name) as cached_values:
with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback:
window_id = create_os_window(
@ -274,7 +272,9 @@ def setup_environment(opts: Options, cli_opts: CLIOptions) -> None:
if cli_opts.listen_on and opts.allow_remote_control != 'n':
cli_opts.listen_on = expand_listen_on(cli_opts.listen_on, from_config_file)
os.environ['KITTY_LISTEN_ON'] = cli_opts.listen_on
set_default_env(opts.env.copy())
env = opts.env.copy()
setup_shell_integration(opts, env)
set_default_env(env)
def set_locale() -> None:

View File

@ -5,12 +5,11 @@
import os
import time
from contextlib import suppress
from typing import Optional, Union
from typing import Optional, Union, Dict
from .options.types import Options
from .config import atomic_save
from .constants import shell_integration_dir
from .fast_data_types import get_options
from .types import run_once
from .utils import log_error, resolved_shell
posix_template = '''
@ -50,14 +49,14 @@ def setup_integration(shell_name: str, rc_path: str, template: str = posix_templ
atomic_write(rc_path, newrc)
def setup_zsh_integration() -> None:
def setup_zsh_integration(env: Dict[str, str]) -> None:
base = os.environ.get('ZDOTDIR', os.path.expanduser('~'))
rc = os.path.join(base, '.zshrc')
if os.path.exists(rc): # dont prevent zsh-newuser-install from running
setup_integration('zsh', rc)
def setup_bash_integration() -> None:
def setup_bash_integration(env: Dict[str, str]) -> None:
setup_integration('bash', os.path.expanduser('~/.bashrc'))
@ -73,17 +72,16 @@ def atomic_symlink(destination: str, in_directory: str) -> None:
raise
def setup_fish_integration() -> None:
base = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
base = os.path.join(base, 'fish')
os.makedirs(os.path.join(base, 'completions'), exist_ok=True)
path = os.path.join(shell_integration_dir, 'kitty.fish')
atomic_symlink(path, os.path.join(base, 'conf.d'))
from .complete import completion_scripts
path = os.path.join(base, 'completions', 'kitty.fish')
rc = safe_read(path)
if rc != completion_scripts['fish2']:
atomic_write(path, completion_scripts['fish2'])
def setup_fish_integration(env: Dict[str, str]) -> None:
if 'XDG_DATA_DIRS' in env:
val = env.get('XDG_DATA_DIRS', '')
dirs = list(filter(None, val.split(os.pathsep)))
else:
val = os.environ.get('XDG_DATA_DIRS', '')
dirs = list(filter(None, val.split(os.pathsep)))
if shell_integration_dir not in dirs:
dirs.insert(0, shell_integration_dir)
env['XDG_DATA_DIRS'] = os.pathsep.join(dirs)
SUPPORTED_SHELLS = {
@ -100,19 +98,19 @@ def get_supported_shell_name(path: str) -> Optional[str]:
return None
@run_once
def setup_shell_integration() -> None:
opts = get_options()
q = opts.shell_integration.split()
if opts.shell_integration == 'disabled' or 'no-rc' in q:
return
def setup_shell_integration(opts: Options, env: Dict[str, str]) -> bool:
q = set(opts.shell_integration.split())
if q & {'disabled', 'no-rc'}:
return False
shell = get_supported_shell_name(resolved_shell(opts)[0])
if shell is None:
return
return False
func = SUPPORTED_SHELLS[shell]
try:
func()
func(env)
except Exception:
import traceback
traceback.print_exc()
log_error(f'Failed to setup shell integration for: {shell}')
return False
return True

View File

@ -0,0 +1,5 @@
if functions -q _ksi_completions
complete -f -c kitty -a "(_ksi_completions)"
else
complete -f -c kitty -a "(commandline -cop | kitty +complete fish)"
end