Source code for core.keybinds

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Keybinding management."""

import collections
import os
import shutil

from . import baselines, helpers, log, paths
from .lnp import lnp


def _keybind_fname(filename):
    """Turn a string into a valid filename for storing keybindings."""
    filename = os.path.basename(filename)
    if not filename.endswith('.txt'):
        filename = filename + '.txt'
    return paths.get('keybinds', filename)


[docs]def read_keybinds(): """Returns a list of keybinding files.""" files = [] for fname in helpers.get_text_files(paths.get('keybinds')): with open(fname, encoding='cp437') as f: if ('[DISPLAY_STRING:' in f.read()) == \ ('legacy' in lnp.df_info.variations): files.append(fname) return tuple(sorted(os.path.basename(o) for o in files))
def _sdl_get_binds(filename, compressed=True): """Return serialised keybindings for the given file. Returns a compressed version, without vanilla entries, unless disabled. Allows keybindings to be stored as files with only the non-vanilla bindings, improving readability and compatibility across DF versions. Only compatible with SDL versions, however. """ with open(filename, encoding='cp437') as f: lines = f.readlines() od, lastkey = collections.OrderedDict(), None for line in (line.strip() for line in lines if line.strip()): if line.startswith('[BIND:'): od[line], lastkey = [], line elif lastkey is not None: od[lastkey].append(line) if not compressed: return od van = _get_vanilla_binds() if van is not None: return collections.OrderedDict( (k, v) for k, v in od.items() # only keep items with a vanilla counterpart, which is different if van.get(k) and set(van.get(k)) != set(v)) return None def _sdl_write_binds(filename, binds_od, expanded=False): """Write keybindings to the given file, optionally expanding them.""" if expanded: van = _get_vanilla_binds() if van is not None: binds_od = collections.OrderedDict( (k, binds_od.get(k) or v) for k, v in van.items()) lines = [''] for bind, vals in binds_od.items(): lines.append(bind) # no indent allowed in interface.txt; otherwise makes reading easier lines.extend(vals if expanded else [' ' + v for v in vals]) text = '\n'.join(lines) + '\n' if filename is None: return text with open(filename, 'w', encoding='cp437') as f: f.write(text) return None def _get_vanilla_binds(): """Return the vanilla keybindings for use in compression or expansion.""" try: vanfile = os.path.join( baselines.find_vanilla(False), 'data', 'init', 'interface.txt') return _sdl_get_binds(vanfile, compressed=False) except TypeError: log.w("Can't load or change keybinds with missing baseline!") return None
[docs]def load_keybinds(filename): """ Overwrites Dwarf Fortress keybindings from a file. Params: filename The keybindings file to use. """ target = paths.get('init', 'interface.txt') filename = _keybind_fname(filename) log.i('Loading keybinds: ' + filename) if 'legacy' in lnp.df_info.variations: shutil.copyfile(filename, target) else: _sdl_write_binds(target, _sdl_get_binds(filename), expanded=True)
[docs]def keybind_exists(filename): """ Returns whether a keybindings file already exists. Args: filename: the filename to check. """ return os.access(_keybind_fname(filename), os.F_OK)
[docs]def save_keybinds(filename): """ Save current keybindings to a file. Args: filename: the name of the new keybindings file. """ installed = paths.get('init', 'interface.txt') filename = _keybind_fname(filename) log.i('Saving current keybinds as ' + filename) if 'legacy' in lnp.df_info.variations: shutil.copyfile(installed, filename) else: _sdl_write_binds(filename, _sdl_get_binds(installed))
[docs]def delete_keybinds(filename): """ Deletes a keybindings file. Args: filename: the filename to delete. """ log.i('Deleting ' + filename + 'keybinds') os.remove(_keybind_fname(filename))
[docs]def get_installed_file(): """Returns the name of the currently installed keybindings.""" def unordered(fname): """An order-independent representation of keybindings from a file.""" return {k: set(v) for k, v in _sdl_get_binds(fname).items()} try: installed = unordered(paths.get('df', 'data', 'init', 'interface.txt')) for fname in helpers.get_text_files(paths.get('keybinds')): if installed == unordered(fname): return os.path.basename(fname) except Exception: # Baseline missing, or interface.txt is missing from baseline - use # plain file comparison pass files = helpers.get_text_files(paths.get('keybinds')) current = paths.get('init', 'interface.txt') result = helpers.detect_installed_file(current, files) return os.path.basename(result)