Skip to content

Commit

Permalink
new cli features, more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sezanzeb authored and sezanzeb committed Jan 9, 2021
1 parent 7b2cc56 commit 7f4efba
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 93 deletions.
51 changes: 36 additions & 15 deletions bin/key-mapper-control
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ from argparse import ArgumentParser
from keymapper.logger import logger
from keymapper.config import config
from keymapper.daemon import get_dbus_interface
from keymapper.mapping import Mapping
from keymapper.state import XMODMAP_FILENAME, system_mapping
from keymapper.paths import get_preset_path, get_config_path
from keymapper.state import system_mapping
from keymapper.getdevices import get_devices


AUTOLOAD = 'autoload'
START = 'start'
STOP = 'stop'
STOP_ALL = 'stop-all'
HELLO = 'hello'


Expand All @@ -59,9 +58,24 @@ def group_exists(name):
return False


def main(options, daemon, config_path):
def main(options, daemon):
"""Do the stuff that the executable is supposed to do."""
# Is a function so that I can import it and test it
if options.config_dir is not None:
path = os.path.abspath(os.path.expanduser(os.path.join(
options.config_dir,
'config.json'
)))
if not os.path.exists(path):
logger.error('"%s" does not exist', path)
sys.exit(1)

logger.info('Using config from "%s" instead', path)
config.load_config(path)

config_dir = os.path.dirname(config.path)
presets_dir = os.path.join(config_dir, 'presets')

if options.list_devices:
get_devices()
sys.exit(0)
Expand All @@ -70,7 +84,7 @@ def main(options, daemon, config_path):
print('\n'.join(system_mapping.list_names()))
sys.exit(0)

if options.command not in [AUTOLOAD, START, STOP, HELLO]:
if options.command not in [AUTOLOAD, START, STOP, HELLO, STOP_ALL]:
logger.error('Unknown command "%s"', options.command)

if options.command == AUTOLOAD:
Expand All @@ -82,10 +96,8 @@ def main(options, daemon, config_path):
config.save_config()
continue

mapping = Mapping()
preset_path = get_preset_path(device, preset)
mapping.load(preset_path)
daemon.start_injecting(device, preset_path, config_path)
preset_path = os.path.join(presets_dir, device, preset + '.json')
daemon.start_injecting(device, preset_path, config_dir)

if options.command == START:
if options.device is None:
Expand All @@ -97,7 +109,7 @@ def main(options, daemon, config_path):
sys.exit(1)

preset_path = os.path.abspath(os.path.expanduser(options.preset))
daemon.start_injecting(options.device, preset_path, config_path)
daemon.start_injecting(options.device, preset_path, config_dir)

if options.command == STOP:
if options.device is None:
Expand All @@ -106,6 +118,9 @@ def main(options, daemon, config_path):

daemon.stop_injecting(options.device)

if options.command == STOP_ALL:
daemon.stop()

if options.command == HELLO:
response = daemon.hello('hello')
logger.info('Daemon answered with "%s"', response)
Expand All @@ -116,11 +131,19 @@ if __name__ == '__main__':
parser.add_argument(
'--command', action='store', dest='command',
help=(
'start, stop, autoload (also stops all current injections) '
'or hello'
'start, stop, autoload (also stops all current injections), '
'hello or stop-all'
),
default=None, metavar='NAME'
)
parser.add_argument(
'--config-dir', action='store', dest='config_dir',
help=(
'path to the config directory containing config.json. '
'defaults to ~/.config/key-mapper/'
),
default=None, metavar='PATH',
)
parser.add_argument(
'--preset', action='store', dest='preset',
help='path to the preset .json file',
Expand Down Expand Up @@ -149,6 +172,4 @@ if __name__ == '__main__':
if daemon is None:
sys.exit(0)

config_path = get_config_path()

main(options, daemon, config_path)
main(options, daemon)
4 changes: 2 additions & 2 deletions data/key-mapper.glade
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</object>
<object class="GtkDialog" id="error_dialog">
<property name="can-focus">False</property>
<property name="border-width">10</property>
<property name="border-width">4</property>
<property name="title" translatable="yes">Key Mapper</property>
<property name="modal">True</property>
<property name="window-position">center</property>
Expand Down Expand Up @@ -138,7 +138,7 @@
</object>
<object class="GtkDialog" id="unsaved_changes">
<property name="can-focus">False</property>
<property name="border-width">10</property>
<property name="border-width">4</property>
<property name="title" translatable="yes">Key Mapper</property>
<property name="modal">True</property>
<property name="window-position">center</property>
Expand Down
4 changes: 4 additions & 0 deletions keymapper/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ def load_config(self, path=None):

def save_config(self):
"""Save the config to the file system."""
if USER == 'root':
logger.debug('Skipping config file creation for the root user')
return

touch(self.path)

with open(self.path, 'w') as file:
Expand Down
7 changes: 3 additions & 4 deletions keymapper/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ def start_injecting(self, device, preset_path, config_dir=None):
# reload the config, since it may have been changed
if config_dir is not None:
config_path = os.path.join(config_dir, 'config.json')
if not os.path.exists(config_path):
logger.error('"%s" does not exist', config_path)
config.load_config(config_path)

if device not in get_devices():
Expand Down Expand Up @@ -212,10 +214,7 @@ def start_injecting(self, device, preset_path, config_dir=None):
return True

def stop(self):
"""Stop all injections and end the service.
Raises dbus.exceptions.DBusException in your main process.
"""
"""Stop all injections."""
logger.info('Stopping all injections')
for injector in self.injectors.values():
injector.stop_injecting()
Expand Down
2 changes: 1 addition & 1 deletion keymapper/dev/injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def handler(*args, uinput=uinput):

def _macro_write(self, code, value, uinput):
"""Handler for macros."""
logger.spam('macro writes code:%s value:%d', code, value)
logger.spam('macro writes %s', (EV_KEY, code, value))
uinput.write(EV_KEY, code, value)
uinput.syn()

Expand Down
47 changes: 0 additions & 47 deletions keymapper/gtk/unsaved.py

This file was deleted.

23 changes: 19 additions & 4 deletions keymapper/gtk/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
from keymapper.logger import logger
from keymapper.getdevices import get_devices
from keymapper.gtk.row import Row, to_string
from keymapper.gtk.unsaved import unsaved_changes_dialog, GO_BACK
from keymapper.dev.reader import keycode_reader
from keymapper.dev.injector import RUNNING, FAILED, NO_GRAB
from keymapper.daemon import get_dbus_interface
Expand All @@ -54,6 +53,9 @@ def gtk_iteration():
CTX_ERROR = 3
CTX_WARNING = 4

CONTINUE = True
GO_BACK = False


def get_selected_row_bg():
"""Get the background color that a row is going to have when selected."""
Expand Down Expand Up @@ -143,6 +145,8 @@ def __init__(self):
builder.connect_signals(self)
self.builder = builder

self.unsaved_changes = builder.get_object('unsaved_changes')

window = self.get('window')
window.show()
# hide everything until stuff is populated
Expand Down Expand Up @@ -184,6 +188,17 @@ def __init__(self):
self.ctrl = 0
self.unreleased_warn = 0

def unsaved_changes_dialog(self):
"""Blocks until the user decided about an action."""
self.unsaved_changes.show()
response = self.unsaved_changes.run()
self.unsaved_changes.hide()

if response == Gtk.ResponseType.ACCEPT:
return CONTINUE

return GO_BACK

def key_press(self, _, event):
"""To execute shortcuts.
Expand Down Expand Up @@ -522,7 +537,7 @@ def on_select_device(self, dropdown):
if dropdown.get_active_id() == self.selected_device:
return

if custom_mapping.changed and unsaved_changes_dialog() == GO_BACK:
if custom_mapping.changed and self.unsaved_changes_dialog() == GO_BACK:
dropdown.set_active_id(self.selected_device)
return

Expand Down Expand Up @@ -594,7 +609,7 @@ def show_device_mapping_status(self):
@with_selected_device
def on_create_preset_clicked(self, _):
"""Create a new preset and select it."""
if custom_mapping.changed and unsaved_changes_dialog() == GO_BACK:
if custom_mapping.changed and self.unsaved_changes_dialog() == GO_BACK:
return

try:
Expand All @@ -614,7 +629,7 @@ def on_select_preset(self, dropdown):
if dropdown.get_active_id() == self.selected_preset:
return

if custom_mapping.changed and unsaved_changes_dialog() == GO_BACK:
if custom_mapping.changed and self.unsaved_changes_dialog() == GO_BACK:
dropdown.set_active_id(self.selected_preset)
return

Expand Down
2 changes: 1 addition & 1 deletion keymapper/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def key_spam(self, key, msg, *args):

start = time.time()

LOG_PATH = '~/.log/key-mapper'
LOG_PATH = os.path.expanduser('~/.log/key-mapper')


class Formatter(logging.Formatter):
Expand Down
2 changes: 1 addition & 1 deletion keymapper/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def populate(self):
path = get_config_path(XMODMAP_FILENAME)
touch(path)
with open(path, 'w') as file:
logger.info('Writing "%s"', path)
logger.debug('Writing "%s"', path)
json.dump(xmodmap_dict, file, indent=4)

self._mapping.update(xmodmap_dict)
Expand Down
1 change: 1 addition & 0 deletions readme/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ running (or without sudo if your user has the appropriate permissions).

```bash
key-mapper-control --command autoload
key-mapper-control --command autoload --config "/home/user/.config/key-mapper/"
sudo key-mapper-control --list-devices
key-mapper-control --command stop --device "Razer Razer Naga Trinity"
key-mapper-control --command start --device "Razer Razer Naga Trinity" --preset "~/.config/key-mapper/presets/gamepad/a.json"
Expand Down
10 changes: 3 additions & 7 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,6 @@ def list_devices():
evdev.InputEvent = InputEvent


def patch_unsaved():
# don't block tests
from keymapper.gtk import unsaved
unsaved.unsaved_changes_dialog = lambda: unsaved.CONTINUE


def patch_events():
# improve logging of stuff
evdev.InputEvent.__str__ = lambda self: (
Expand All @@ -397,7 +391,6 @@ def clear_write_history():
# the original versions
patch_paths()
patch_evdev()
patch_unsaved()
patch_select()
patch_events()

Expand All @@ -407,6 +400,7 @@ def clear_write_history():
from keymapper.dev.reader import keycode_reader
from keymapper.getdevices import refresh_devices
from keymapper.state import system_mapping, custom_mapping
from keymapper.paths import get_config_path
from keymapper.dev.keycode_mapper import active_macros, unreleased

# no need for a high number in tests
Expand Down Expand Up @@ -438,12 +432,14 @@ def cleanup():
if os.path.exists(tmp):
shutil.rmtree(tmp)

config.path = os.path.join(get_config_path(), 'config.json')
config.clear_config()
config.save_config()

system_mapping.populate()
custom_mapping.empty()
custom_mapping.clear_config()
custom_mapping.changed = False

clear_write_history()

Expand Down
Loading

0 comments on commit 7f4efba

Please sign in to comment.