Add action to close a session
This commit is contained in:
parent
21fa5bb1ce
commit
d3c46a829d
6 changed files with 99 additions and 6 deletions
|
|
@ -61,6 +61,9 @@ easily swap between them, kitty has you covered. You can use the
|
|||
In this manner you can define as many projects/sessions as you like and easily
|
||||
switch between them with a keypress.
|
||||
|
||||
You can also close sessions using the :ac:`close_session` action, which closes
|
||||
all windows in the session with a single keypress.
|
||||
|
||||
|
||||
Displaying the currently active session name
|
||||
----------------------------------------------
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ class Action(NamedTuple):
|
|||
'lay': 'Layouts',
|
||||
'misc': 'Miscellaneous',
|
||||
'debug': 'Debugging',
|
||||
'session': 'Sessions',
|
||||
}
|
||||
group_title = groups.__getitem__
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,15 @@
|
|||
from .options.types import Options, nullable_colors
|
||||
from .options.utils import MINIMUM_FONT_SIZE, KeyboardMode, KeyDefinition
|
||||
from .os_window_size import initial_window_size_func
|
||||
from .session import Session, create_sessions, default_save_as_session_opts, get_os_window_sizing_data, goto_session, save_as_session
|
||||
from .session import (
|
||||
Session,
|
||||
close_session_with_confirm,
|
||||
create_sessions,
|
||||
default_save_as_session_opts,
|
||||
get_os_window_sizing_data,
|
||||
goto_session,
|
||||
save_as_session,
|
||||
)
|
||||
from .shaders import load_shader_programs
|
||||
from .simple_cli_definitions import grab_keyboard_docs
|
||||
from .tabs import SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager
|
||||
|
|
@ -1025,7 +1033,7 @@ def mark_window_for_close(self, q: Window | None | int = None) -> None:
|
|||
def close_window(self) -> None:
|
||||
self.mark_window_for_close(self.window_for_dispatch)
|
||||
|
||||
def close_windows_with_confirmation_msg(self, windows: Iterable[Window], active_window: Window | None) -> tuple[str, int]:
|
||||
def close_windows_with_confirmation_msg(self, windows: Iterable[Window], active_window: Window | None = None) -> tuple[str, int]:
|
||||
num_running_programs = 0
|
||||
num_background_programs = 0
|
||||
count_background = get_options().confirm_os_window_close[1]
|
||||
|
|
@ -1268,6 +1276,12 @@ def close_tab_no_confirm(self, tab: Tab) -> None:
|
|||
for window in tab:
|
||||
self.mark_window_for_close(window)
|
||||
|
||||
def close_windows_no_confirm(self, windows: Sequence[Window]) -> None:
|
||||
if self.current_visual_select is not None:
|
||||
self.cancel_current_visual_select()
|
||||
for window in windows:
|
||||
self.mark_window_for_close(window)
|
||||
|
||||
@ac('win', 'Toggle the fullscreen status of the active OS Window')
|
||||
def toggle_fullscreen(self, os_window_id: int = 0) -> None:
|
||||
if os_window_id == 0:
|
||||
|
|
@ -1538,6 +1552,14 @@ def active_session(self) -> str:
|
|||
return t.created_in_session_name
|
||||
return ''
|
||||
|
||||
@property
|
||||
def all_loaded_session_names(self) -> Iterator[str]:
|
||||
seen = set()
|
||||
for w in self.all_windows:
|
||||
if w.created_in_session_name and w.created_in_session_name not in seen:
|
||||
seen.add(w.created_in_session_name)
|
||||
yield w.created_in_session_name
|
||||
|
||||
def refresh_active_tab_bar(self) -> bool:
|
||||
tm = self.active_tab_manager
|
||||
if tm:
|
||||
|
|
@ -3057,14 +3079,29 @@ def done2(target_window_id: int, self: Boss) -> None:
|
|||
)
|
||||
return q if isinstance(q, Window) else None
|
||||
|
||||
@ac('misc', 'Switch to the specified session, creating it if not already present. See :ref:`goto_session`.')
|
||||
@ac('session', 'Switch to the specified session, creating it if not already present. See :ref:`goto_session`.')
|
||||
def goto_session(self, *cmdline: str) -> None:
|
||||
goto_session(self, cmdline)
|
||||
|
||||
@ac('misc', 'Save the current kitty state as a session file. See :ref:`save_as_session`.')
|
||||
@ac('session', 'Save the current kitty state as a session file. See :ref:`save_as_session`.')
|
||||
def save_as_session(self, *cmdline: str) -> None:
|
||||
save_as_session(self, cmdline)
|
||||
|
||||
@ac('session', '''
|
||||
Close a session, that is, close all windows that belong to the session.
|
||||
Examples::
|
||||
# Ask for the session to close
|
||||
map f1 close_session
|
||||
# Close the currently active session
|
||||
map f1 close_session .
|
||||
# Close session by name
|
||||
map f1 close_session "my session"
|
||||
# Close session by path to session file
|
||||
map f1 close_session "/path/to/session/file.kitty-session"
|
||||
''')
|
||||
def close_session(self, *cmdline: str) -> None:
|
||||
close_session_with_confirm(self, cmdline)
|
||||
|
||||
@ac('tab', 'Interactively select a tab to switch to')
|
||||
def select_tab(self) -> None:
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class InvalidMods(ValueError):
|
|||
'pass_selection_to_program', 'new_window', 'new_tab', 'new_os_window',
|
||||
'new_window_with_cwd', 'new_tab_with_cwd', 'new_os_window_with_cwd',
|
||||
'launch', 'mouse_handle_click', 'show_error', 'goto_session', 'save_as_session',
|
||||
'close_session',
|
||||
)
|
||||
def shlex_parse(func: str, rest: str) -> FuncArgsType:
|
||||
return func, to_cmdline(rest)
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ def session_arg_to_name(session_arg: str) -> str:
|
|||
return session_name
|
||||
|
||||
|
||||
|
||||
def parse_session(
|
||||
raw: str, opts: Options, environ: Mapping[str, str] | None = None, session_arg: str = '', session_path: str = ''
|
||||
) -> Generator[Session, None, None]:
|
||||
|
|
@ -434,6 +433,58 @@ def get_all_known_sessions() -> dict[str, str]:
|
|||
return all_known_sessions
|
||||
|
||||
|
||||
def close_session_with_confirm(boss: BossType, cmdline: Sequence[str]) -> None:
|
||||
if not cmdline:
|
||||
names = sorted(boss.all_loaded_session_names, key=lambda x: x.lower())
|
||||
if not names:
|
||||
boss.ring_bell_if_allowed()
|
||||
return
|
||||
if len(names) == 1:
|
||||
return close_session_with_confirm(boss, names)
|
||||
def chosen(name: str | None) -> None:
|
||||
if name:
|
||||
close_session_with_confirm(boss, (name,))
|
||||
boss.choose_entry(
|
||||
_('Select a session to close'), ((name, name) for name in names), chosen)
|
||||
return
|
||||
if len(cmdline) != 1:
|
||||
boss.show_error(_('Invalid close_session specification'), _('{} is not a valid argument to close_session').format(shlex.join(cmdline)))
|
||||
return
|
||||
path_or_name = cmdline[0]
|
||||
if path_or_name == '.':
|
||||
if name := boss.active_session:
|
||||
close_session_with_confirm(boss, (name,))
|
||||
else:
|
||||
boss.ring_bell_if_allowed()
|
||||
return
|
||||
if '/' in path_or_name:
|
||||
path_to_name = {v: k for k, v in get_all_known_sessions().items()}
|
||||
name = path_to_name.get(path_or_name, '')
|
||||
if not name:
|
||||
boss.ring_bell_if_allowed()
|
||||
return
|
||||
else:
|
||||
name = path_or_name
|
||||
windows = tuple(w for w in boss.all_windows if w.created_in_session_name == name)
|
||||
if not windows:
|
||||
return
|
||||
msg, num_active_windows = boss.close_windows_with_confirmation_msg(windows, boss.active_window)
|
||||
x = get_options().confirm_os_window_close[0]
|
||||
num = num_active_windows if x < 0 else len(windows)
|
||||
needs_confirmation = x != 0 and num >= abs(x)
|
||||
|
||||
def do_close(confirmed: bool) -> None:
|
||||
if confirmed:
|
||||
boss.close_windows_no_confirm(windows)
|
||||
|
||||
if needs_confirmation:
|
||||
msg = msg or _('It has {} windows?').format(num)
|
||||
msg = _('Are you sure you want to close this session?') + ' ' + msg
|
||||
boss.confirm(msg, do_close, window=boss.active_window, title=_('Close session?'))
|
||||
else:
|
||||
do_close(True)
|
||||
|
||||
|
||||
def choose_session(boss: BossType) -> None:
|
||||
all_known_sessions = get_all_known_sessions()
|
||||
hmap = {n: len(goto_session_history)-i for i, n in enumerate(goto_session_history)}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ def modmap() -> dict[str, int]:
|
|||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Literal
|
||||
ActionGroup = Literal['cp', 'sc', 'win', 'tab', 'mouse', 'mk', 'lay', 'misc', 'debug']
|
||||
ActionGroup = Literal['cp', 'sc', 'win', 'tab', 'mouse', 'mk', 'lay', 'misc', 'debug', 'session']
|
||||
else:
|
||||
ActionGroup = str
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue