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:
parent
d31935b8eb
commit
d3a3f99848
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
5
shell-integration/fish/vendor_completions.d/kitty.fish
Normal file
5
shell-integration/fish/vendor_completions.d/kitty.fish
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user