gdctl: Add bash completion integration
This auto-completes things such as available connectors, modes, scales, transforms, etc. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4190>
This commit is contained in:
@ -11,6 +11,7 @@ include:
|
||||
meson-options:
|
||||
-Dxwayland_initfd=enabled
|
||||
-Dprofiler=true
|
||||
-Dbash_completion=false
|
||||
|
||||
build-sysext:
|
||||
before_script:
|
||||
@ -124,6 +125,7 @@ variables:
|
||||
zenity
|
||||
python3-dbusmock
|
||||
gnome-desktop-testing
|
||||
python3-argcomplete
|
||||
ruff
|
||||
|
||||
FDO_DISTRIBUTION_EXEC: |
|
||||
@ -194,8 +196,6 @@ variables:
|
||||
mkdir -p /opt/mutter
|
||||
cp build/src/tests/kvm/bzImage /opt/mutter/bzImage
|
||||
|
||||
dnf install -y python3-argcomplete
|
||||
|
||||
git clone https://github.com/arighi/virtme-ng.git
|
||||
cd virtme-ng
|
||||
git fetch --tags
|
||||
|
@ -378,6 +378,7 @@ have_kvm_tests = false
|
||||
have_tty_tests = false
|
||||
have_installed_tests = false
|
||||
have_x11_tests = false
|
||||
have_bash_completion = get_option('bash_completion')
|
||||
|
||||
if have_tests
|
||||
gtk3_dep = dependency('gtk+-3.0', version: gtk3_req)
|
||||
@ -744,6 +745,8 @@ summary('mandir', mandir, section: 'Directories')
|
||||
summary('buildtype', get_option('buildtype'), section: 'Build Configuration')
|
||||
summary('debug', get_option('debug'), section: 'Build Configuration')
|
||||
|
||||
summary('Bash completion', have_bash_completion, section: 'Shell integration')
|
||||
|
||||
summary('OpenGL', have_gl, section: 'Rendering APIs')
|
||||
summary('GLES2', have_gles2, section: 'Rendering APIs')
|
||||
summary('EGL', have_egl, section: 'Rendering APIs')
|
||||
|
@ -224,3 +224,9 @@ option('fonts',
|
||||
value: true,
|
||||
description: 'Enable font rendering integration using Pango'
|
||||
)
|
||||
|
||||
option('bash_completion',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Integrate bash completion for gdctl'
|
||||
)
|
||||
|
95
tools/gdctl
95
tools/gdctl
@ -1,11 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import argcomplete
|
||||
import sys
|
||||
|
||||
from dataclasses import dataclass
|
||||
from gi.repository import GLib, Gio
|
||||
from enum import Enum, Flag
|
||||
from argcomplete.completers import BaseCompleter, SuppressCompleter
|
||||
|
||||
NAME = "org.gnome.Mutter.DisplayConfig"
|
||||
INTERFACE = "org.gnome.Mutter.DisplayConfig"
|
||||
@ -1130,6 +1132,70 @@ class GdctlParser(argparse.ArgumentParser):
|
||||
return namespace
|
||||
|
||||
|
||||
class MonitorCompleter(BaseCompleter):
|
||||
def __call__(self, **kwargs):
|
||||
try:
|
||||
display_config = DisplayConfig()
|
||||
monitors_state = MonitorsState(display_config)
|
||||
return tuple(monitors_state.monitors)
|
||||
except Exception:
|
||||
return ()
|
||||
|
||||
|
||||
class MonitorModeCompleter(BaseCompleter):
|
||||
def __call__(self, parsed_args=None, **kwargs):
|
||||
try:
|
||||
(connector,) = parsed_args._current_sub_group["key"]
|
||||
|
||||
display_config = DisplayConfig()
|
||||
monitors_state = MonitorsState(display_config)
|
||||
|
||||
monitor = monitors_state.monitors[connector]
|
||||
return (mode.name for mode in monitor.modes)
|
||||
except Exception:
|
||||
return ()
|
||||
|
||||
|
||||
class ScaleCompleter(BaseCompleter):
|
||||
def __call__(self, parsed_args=None, **kwargs):
|
||||
try:
|
||||
(connector,) = parsed_args._current_sub_group["key"]
|
||||
|
||||
display_config = DisplayConfig()
|
||||
monitors_state = MonitorsState(display_config)
|
||||
|
||||
monitor = monitors_state.monitors[connector]
|
||||
|
||||
mode = parsed_args._current_sub_group.get("mode", None)
|
||||
if not mode:
|
||||
mode = monitor.preferred_mode
|
||||
|
||||
scales = mode.supported_scales
|
||||
scales.sort(key=lambda scale: abs(scale - mode.preferred_scale))
|
||||
|
||||
return (repr(scale) for scale in scales)
|
||||
except Exception:
|
||||
return ()
|
||||
|
||||
|
||||
class NamedEnumCompleter(BaseCompleter):
|
||||
def __init__(self, enum_type):
|
||||
self.enum_type = enum_type
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
return (str(enum_value) for enum_value in self.enum_type)
|
||||
|
||||
|
||||
class LayoutModeCompleter(NamedEnumCompleter):
|
||||
def __init__(self):
|
||||
super().__init__(LayoutMode)
|
||||
|
||||
|
||||
class TransformCompleter(NamedEnumCompleter):
|
||||
def __init__(self):
|
||||
super().__init__(Transform)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = GdctlParser(
|
||||
description="Display control utility",
|
||||
@ -1196,7 +1262,7 @@ if __name__ == "__main__":
|
||||
choices=[str(layout_mode) for layout_mode in list(LayoutMode)],
|
||||
type=str,
|
||||
action=AppendToGlobal,
|
||||
)
|
||||
).completer = LayoutModeCompleter()
|
||||
set_parser.add_argument(
|
||||
"-L",
|
||||
"--logical-monitor",
|
||||
@ -1216,8 +1282,9 @@ if __name__ == "__main__":
|
||||
dest="monitors",
|
||||
metavar="CONNECTOR",
|
||||
action=SubGroupAction,
|
||||
nargs=1,
|
||||
help="Configure monitor",
|
||||
)
|
||||
).completer = MonitorCompleter()
|
||||
monitor_parser = set_parser.add_argument_group(
|
||||
"monitor",
|
||||
"Monitor options (pass after --monitor)",
|
||||
@ -1229,7 +1296,7 @@ if __name__ == "__main__":
|
||||
action=AppendToSubGroup,
|
||||
help="Monitor mode",
|
||||
type=str,
|
||||
)
|
||||
).completer = MonitorModeCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--primary",
|
||||
"-p",
|
||||
@ -1245,7 +1312,7 @@ if __name__ == "__main__":
|
||||
action=AppendToGroup,
|
||||
help="Logical monitor scale",
|
||||
type=float,
|
||||
)
|
||||
).completer = ScaleCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--transform",
|
||||
"-t",
|
||||
@ -1253,7 +1320,7 @@ if __name__ == "__main__":
|
||||
help="Apply viewport transform",
|
||||
choices=[str(transform) for transform in list(Transform)],
|
||||
type=str,
|
||||
)
|
||||
).completer = TransformCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--x",
|
||||
"-x",
|
||||
@ -1274,28 +1341,38 @@ if __name__ == "__main__":
|
||||
metavar="CONNECTOR",
|
||||
help="Place right of other monitor",
|
||||
type=str,
|
||||
)
|
||||
).completer = MonitorCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--left-of",
|
||||
action=AppendToGroup,
|
||||
metavar="CONNECTOR",
|
||||
help="Place left of other monitor",
|
||||
type=str,
|
||||
)
|
||||
).completer = MonitorCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--above",
|
||||
action=AppendToGroup,
|
||||
metavar="CONNECTOR",
|
||||
help="Place above other monitor",
|
||||
type=str,
|
||||
)
|
||||
).completer = MonitorCompleter()
|
||||
logical_monitor_parser.add_argument(
|
||||
"--below",
|
||||
action=AppendToGroup,
|
||||
metavar="CONNECTOR",
|
||||
help="Place below other monitor",
|
||||
type=str,
|
||||
)
|
||||
).completer = MonitorCompleter()
|
||||
|
||||
for action in [
|
||||
GroupAction,
|
||||
SubGroupAction,
|
||||
AppendToGroup,
|
||||
AppendToSubGroup,
|
||||
AppendToGlobal,
|
||||
]:
|
||||
argcomplete.safe_actions.add(action)
|
||||
argcomplete.autocomplete(parser, default_completer=SuppressCompleter)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -3,5 +3,30 @@ install_data(
|
||||
install_dir: bindir,
|
||||
)
|
||||
|
||||
if have_bash_completion
|
||||
bash_completion = dependency('bash-completion', required: false)
|
||||
if bash_completion.found()
|
||||
bash_completion_dir = bash_completion.get_variable(pkgconfig: 'completionsdir')
|
||||
else
|
||||
bash_completion_dir = get_option('sysconfdir') / 'bash_completion.d'
|
||||
endif
|
||||
|
||||
register_python_argcomplete = find_program('register-python-argcomplete')
|
||||
|
||||
custom_target(
|
||||
'gdctl-bash-completion',
|
||||
output: 'gdctl',
|
||||
command: [
|
||||
register_python_argcomplete,
|
||||
'gdctl',
|
||||
'--complete-arguments',
|
||||
'-o nosort',
|
||||
],
|
||||
capture: true,
|
||||
install_dir: bash_completion_dir,
|
||||
install: true,
|
||||
)
|
||||
endif
|
||||
|
||||
gdctl = find_program('gdctl')
|
||||
get_state_tool = find_program('get-state.py')
|
||||
|
Reference in New Issue
Block a user