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,
|
OptionDict, OptionSpecSeq, options_for_completion, parse_option_spec,
|
||||||
prettify
|
prettify
|
||||||
)
|
)
|
||||||
|
from .constants import shell_integration_dir
|
||||||
from .fast_data_types import truncate_point_for_length, wcswidth
|
from .fast_data_types import truncate_point_for_length, wcswidth
|
||||||
from .rc.base import all_command_names, command_for_name
|
from .rc.base import all_command_names, command_for_name
|
||||||
from .shell import options_for_cmd
|
from .shell import options_for_cmd
|
||||||
@ -128,6 +129,11 @@ def remote_control_command_names() -> Tuple[str, ...]:
|
|||||||
# Shell specific code {{{
|
# 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 = {
|
completion_scripts = {
|
||||||
'zsh': '''#compdef kitty
|
'zsh': '''#compdef kitty
|
||||||
|
|
||||||
@ -140,7 +146,7 @@ _kitty() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
compdef _kitty kitty
|
compdef _kitty kitty
|
||||||
''',
|
'''.__str__,
|
||||||
'bash': '''
|
'bash': '''
|
||||||
_kitty_completions() {
|
_kitty_completions() {
|
||||||
local src
|
local src
|
||||||
@ -154,7 +160,7 @@ _kitty_completions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
complete -o nospace -F _kitty_completions kitty
|
complete -o nospace -F _kitty_completions kitty
|
||||||
''',
|
'''.__str__,
|
||||||
'fish': '''
|
'fish': '''
|
||||||
function __kitty_completions
|
function __kitty_completions
|
||||||
# Send all words up to the one before the cursor
|
# Send all words up to the one before the cursor
|
||||||
@ -162,15 +168,8 @@ function __kitty_completions
|
|||||||
end
|
end
|
||||||
|
|
||||||
complete -f -c kitty -a "(__kitty_completions)"
|
complete -f -c kitty -a "(__kitty_completions)"
|
||||||
''',
|
'''.__str__,
|
||||||
'fish2': '''
|
'fish2': load_fish2_completion,
|
||||||
if functions -q _ksi_completions
|
|
||||||
complete -f -c kitty -a "(_ksi_completions)"
|
|
||||||
else
|
|
||||||
complete -f -c kitty -a "(commandline -cop | kitty +complete fish)"
|
|
||||||
end
|
|
||||||
''',
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseResult = Tuple[List[str], bool]
|
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:
|
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:
|
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 .options.types import Options
|
||||||
from .os_window_size import initial_window_size_func
|
from .os_window_size import initial_window_size_func
|
||||||
from .session import get_os_window_sizing_data
|
from .session import get_os_window_sizing_data
|
||||||
|
from .shell_integration import setup_shell_integration
|
||||||
from .types import SingleKey
|
from .types import SingleKey
|
||||||
from .utils import (
|
from .utils import (
|
||||||
detach, expandvars, log_error, single_instance,
|
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
|
if not is_wayland() and not is_macos: # no window icons on wayland
|
||||||
set_x11_window_icon()
|
set_x11_window_icon()
|
||||||
load_shader_programs.use_selection_fg = opts.selection_foreground is not None
|
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 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:
|
with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback:
|
||||||
window_id = create_os_window(
|
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':
|
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)
|
cli_opts.listen_on = expand_listen_on(cli_opts.listen_on, from_config_file)
|
||||||
os.environ['KITTY_LISTEN_ON'] = cli_opts.listen_on
|
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:
|
def set_locale() -> None:
|
||||||
|
|||||||
@ -5,12 +5,11 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from contextlib import suppress
|
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 .config import atomic_save
|
||||||
from .constants import shell_integration_dir
|
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
|
from .utils import log_error, resolved_shell
|
||||||
|
|
||||||
posix_template = '''
|
posix_template = '''
|
||||||
@ -50,14 +49,14 @@ def setup_integration(shell_name: str, rc_path: str, template: str = posix_templ
|
|||||||
atomic_write(rc_path, newrc)
|
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('~'))
|
base = os.environ.get('ZDOTDIR', os.path.expanduser('~'))
|
||||||
rc = os.path.join(base, '.zshrc')
|
rc = os.path.join(base, '.zshrc')
|
||||||
if os.path.exists(rc): # dont prevent zsh-newuser-install from running
|
if os.path.exists(rc): # dont prevent zsh-newuser-install from running
|
||||||
setup_integration('zsh', rc)
|
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'))
|
setup_integration('bash', os.path.expanduser('~/.bashrc'))
|
||||||
|
|
||||||
|
|
||||||
@ -73,17 +72,16 @@ def atomic_symlink(destination: str, in_directory: str) -> None:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def setup_fish_integration() -> None:
|
def setup_fish_integration(env: Dict[str, str]) -> None:
|
||||||
base = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
|
if 'XDG_DATA_DIRS' in env:
|
||||||
base = os.path.join(base, 'fish')
|
val = env.get('XDG_DATA_DIRS', '')
|
||||||
os.makedirs(os.path.join(base, 'completions'), exist_ok=True)
|
dirs = list(filter(None, val.split(os.pathsep)))
|
||||||
path = os.path.join(shell_integration_dir, 'kitty.fish')
|
else:
|
||||||
atomic_symlink(path, os.path.join(base, 'conf.d'))
|
val = os.environ.get('XDG_DATA_DIRS', '')
|
||||||
from .complete import completion_scripts
|
dirs = list(filter(None, val.split(os.pathsep)))
|
||||||
path = os.path.join(base, 'completions', 'kitty.fish')
|
if shell_integration_dir not in dirs:
|
||||||
rc = safe_read(path)
|
dirs.insert(0, shell_integration_dir)
|
||||||
if rc != completion_scripts['fish2']:
|
env['XDG_DATA_DIRS'] = os.pathsep.join(dirs)
|
||||||
atomic_write(path, completion_scripts['fish2'])
|
|
||||||
|
|
||||||
|
|
||||||
SUPPORTED_SHELLS = {
|
SUPPORTED_SHELLS = {
|
||||||
@ -100,19 +98,19 @@ def get_supported_shell_name(path: str) -> Optional[str]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@run_once
|
def setup_shell_integration(opts: Options, env: Dict[str, str]) -> bool:
|
||||||
def setup_shell_integration() -> None:
|
q = set(opts.shell_integration.split())
|
||||||
opts = get_options()
|
if q & {'disabled', 'no-rc'}:
|
||||||
q = opts.shell_integration.split()
|
return False
|
||||||
if opts.shell_integration == 'disabled' or 'no-rc' in q:
|
|
||||||
return
|
|
||||||
shell = get_supported_shell_name(resolved_shell(opts)[0])
|
shell = get_supported_shell_name(resolved_shell(opts)[0])
|
||||||
if shell is None:
|
if shell is None:
|
||||||
return
|
return False
|
||||||
func = SUPPORTED_SHELLS[shell]
|
func = SUPPORTED_SHELLS[shell]
|
||||||
try:
|
try:
|
||||||
func()
|
func(env)
|
||||||
except Exception:
|
except Exception:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
log_error(f'Failed to setup shell integration for: {shell}')
|
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