Skip to content

Commit 4772f00

Browse files
committed
feat(Window): Use OptionsMixin for Window.set_option, Window.show_option(s)
1 parent 29ad2f6 commit 4772f00

File tree

1 file changed

+4
-229
lines changed

1 file changed

+4
-229
lines changed

src/libtmux/window.py

Lines changed: 4 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from libtmux._internal.query_list import QueryList
1717
from libtmux.common import has_gte_version, tmux_cmd
1818
from libtmux.constants import (
19-
OPTION_SCOPE_FLAG_MAP,
2019
RESIZE_ADJUSTMENT_DIRECTION_FLAG_MAP,
2120
OptionScope,
2221
PaneDirection,
@@ -27,7 +26,8 @@
2726
from libtmux.pane import Pane
2827

2928
from . import exc
30-
from .options import handle_option_error
29+
from .common import PaneDict, WindowOptionDict
30+
from .options import OptionsMixin
3131

3232
if t.TYPE_CHECKING:
3333
from .common import PaneDict, WindowOptionDict
@@ -38,7 +38,7 @@
3838

3939

4040
@dataclasses.dataclass()
41-
class Window(Obj):
41+
class Window(Obj, OptionsMixin):
4242
""":term:`tmux(1)` :term:`Window` [window_manual]_.
4343
4444
Holds :class:`Pane` objects.
@@ -86,6 +86,7 @@ class Window(Obj):
8686
https://man.openbsd.org/tmux.1#DESCRIPTION. Accessed April 1st, 2018.
8787
"""
8888

89+
default_option_scope: OptionScope | None = OptionScope.Window
8990
server: Server
9091

9192
def refresh(self) -> None:
@@ -390,230 +391,6 @@ def select_layout(self, layout: str | None = None) -> Window:
390391

391392
return self
392393

393-
def set_option(
394-
self,
395-
option: str,
396-
value: int | str,
397-
_format: bool | None = None,
398-
unset: bool | None = None,
399-
unset_panes: bool | None = None,
400-
prevent_overwrite: bool | None = None,
401-
suppress_warnings: bool | None = None,
402-
append: bool | None = None,
403-
g: bool | None = None,
404-
scope: OptionScope | None = None,
405-
) -> Window:
406-
"""Set option for tmux window.
407-
408-
Wraps ``$ tmux set-option <option> <value>``.
409-
410-
Parameters
411-
----------
412-
option : str
413-
option to set, e.g. 'aggressive-resize'
414-
value : str
415-
window option value. True/False will turn in 'on' and 'off',
416-
also accepts string of 'on' or 'off' directly.
417-
418-
Raises
419-
------
420-
:exc:`exc.OptionError`, :exc:`exc.UnknownOption`,
421-
:exc:`exc.InvalidOption`, :exc:`exc.AmbiguousOption`
422-
"""
423-
flags: list[str] = []
424-
if isinstance(value, bool) and value:
425-
value = "on"
426-
elif isinstance(value, bool) and not value:
427-
value = "off"
428-
429-
if unset is not None and unset:
430-
assert isinstance(unset, bool)
431-
flags.append("-u")
432-
433-
if unset_panes is not None and unset_panes:
434-
assert isinstance(unset_panes, bool)
435-
flags.append("-U")
436-
437-
if _format is not None and _format:
438-
assert isinstance(_format, bool)
439-
flags.append("-F")
440-
441-
if prevent_overwrite is not None and prevent_overwrite:
442-
assert isinstance(prevent_overwrite, bool)
443-
flags.append("-o")
444-
445-
if suppress_warnings is not None and suppress_warnings:
446-
assert isinstance(suppress_warnings, bool)
447-
flags.append("-q")
448-
449-
if append is not None and append:
450-
assert isinstance(append, bool)
451-
flags.append("-a")
452-
453-
if g is not None and g:
454-
assert isinstance(g, bool)
455-
flags.append("-g")
456-
457-
if scope is not None:
458-
assert scope in OPTION_SCOPE_FLAG_MAP
459-
flags.append(
460-
OPTION_SCOPE_FLAG_MAP[scope],
461-
)
462-
463-
cmd = self.cmd(
464-
"set-option",
465-
"-w",
466-
*flags,
467-
option,
468-
value,
469-
)
470-
471-
if isinstance(cmd.stderr, list) and len(cmd.stderr):
472-
handle_option_error(cmd.stderr[0])
473-
474-
return self
475-
476-
@t.overload
477-
def show_options(
478-
self,
479-
g: bool | None,
480-
scope: OptionScope | None,
481-
include_hooks: bool | None,
482-
include_parents: bool | None,
483-
values_only: t.Literal[True],
484-
) -> list[str]: ...
485-
486-
@t.overload
487-
def show_options(
488-
self,
489-
g: bool | None,
490-
scope: OptionScope | None,
491-
include_hooks: bool | None,
492-
include_parents: bool | None,
493-
values_only: t.Literal[None] = None,
494-
) -> WindowOptionDict: ...
495-
496-
@t.overload
497-
def show_options(
498-
self,
499-
g: bool | None = None,
500-
scope: OptionScope | None = None,
501-
include_hooks: bool | None = None,
502-
include_parents: bool | None = None,
503-
values_only: t.Literal[False] = False,
504-
) -> WindowOptionDict: ...
505-
506-
def show_options(
507-
self,
508-
g: bool | None = False,
509-
scope: OptionScope | None = OptionScope.Window,
510-
include_hooks: bool | None = None,
511-
include_parents: bool | None = None,
512-
values_only: bool | None = False,
513-
) -> WindowOptionDict | list[str]:
514-
"""Return a dict of options for the window.
515-
516-
Parameters
517-
----------
518-
g : str, optional
519-
Pass ``-g`` flag for global variable, default False.
520-
"""
521-
tmux_args: tuple[str, ...] = ()
522-
523-
if g:
524-
tmux_args += ("-g",)
525-
526-
if scope is not None:
527-
assert scope in OPTION_SCOPE_FLAG_MAP
528-
tmux_args += (OPTION_SCOPE_FLAG_MAP[scope],)
529-
530-
if include_parents is not None and include_parents:
531-
tmux_args += ("-A",)
532-
533-
if include_hooks is not None and include_hooks:
534-
tmux_args += ("-H",)
535-
536-
if values_only is not None and values_only:
537-
tmux_args += ("-v",)
538-
539-
cmd = self.cmd("show-options", *tmux_args)
540-
541-
output = cmd.stdout
542-
543-
# The shlex.split function splits the args at spaces, while also
544-
# retaining quoted sub-strings.
545-
# shlex.split('this is "a test"') => ['this', 'is', 'a test']
546-
547-
window_options: WindowOptionDict = {}
548-
for item in output:
549-
try:
550-
key, val = shlex.split(item)
551-
except ValueError:
552-
logger.exception(f"Error extracting option: {item}")
553-
assert isinstance(key, str)
554-
assert isinstance(val, str)
555-
556-
if isinstance(val, str) and val.isdigit():
557-
window_options[key] = int(val)
558-
559-
return window_options
560-
561-
def show_option(
562-
self,
563-
option: str,
564-
g: bool = False,
565-
scope: OptionScope | None = OptionScope.Window,
566-
include_hooks: bool | None = None,
567-
include_parents: bool | None = None,
568-
) -> str | int | None:
569-
"""Return option value for the target window.
570-
571-
todo: test and return True/False for on/off string
572-
573-
Parameters
574-
----------
575-
option : str
576-
g : bool, optional
577-
Pass ``-g`` flag, global. Default False.
578-
579-
Raises
580-
------
581-
:exc:`exc.OptionError`, :exc:`exc.UnknownOption`,
582-
:exc:`exc.InvalidOption`, :exc:`exc.AmbiguousOption`
583-
"""
584-
tmux_args: tuple[str | int, ...] = ()
585-
586-
if g:
587-
tmux_args += ("-g",)
588-
589-
if scope is not None:
590-
assert scope in OPTION_SCOPE_FLAG_MAP
591-
tmux_args += (OPTION_SCOPE_FLAG_MAP[scope],)
592-
593-
if include_parents is not None and include_parents:
594-
tmux_args += ("-A",)
595-
596-
if include_hooks is not None and include_hooks:
597-
tmux_args += ("-H",)
598-
599-
tmux_args += (option,)
600-
601-
cmd = self.cmd("show-options", *tmux_args)
602-
603-
if len(cmd.stderr):
604-
handle_option_error(cmd.stderr[0])
605-
606-
window_options_output = cmd.stdout
607-
608-
if not len(window_options_output):
609-
return None
610-
611-
value_raw = next(shlex.split(item) for item in window_options_output)
612-
613-
value: str | int = int(value_raw[1]) if value_raw[1].isdigit() else value_raw[1]
614-
615-
return value
616-
617394
def rename_window(self, new_name: str) -> Window:
618395
"""Rename window.
619396
@@ -632,8 +409,6 @@ def rename_window(self, new_name: str) -> Window:
632409
>>> window.rename_window('New name')
633410
Window(@1 1:New name, Session($1 ...))
634411
"""
635-
import shlex
636-
637412
lex = shlex.shlex(new_name)
638413
lex.escape = " "
639414
lex.whitespace_split = False

0 commit comments

Comments
 (0)