From 1ca8cba62a028f9a3f4244dbcd867cde7d9cc44c Mon Sep 17 00:00:00 2001 From: Oliver Berger Date: Wed, 27 Apr 2016 10:18:57 +0200 Subject: [PATCH 1/2] add detach and config file support --- neovim_gui/cli.py | 101 +++++++++++++++++++++++++++++++++++++++++-- neovim_gui/gtk_ui.py | 13 +++--- setup.py | 3 +- 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/neovim_gui/cli.py b/neovim_gui/cli.py index 8bd2e7a..dd4e341 100644 --- a/neovim_gui/cli.py +++ b/neovim_gui/cli.py @@ -1,26 +1,117 @@ """CLI for accessing the gtk/tickit UIs implemented by this package.""" +import os +import resource +import sys import shlex import click +import yaml from .ui_bridge import UIBridge from neovim import attach from neovim.compat import IS_PYTHON3 +CONFIG_FILES = ( + '.pynvim.yaml', + '~/.pynvim.yaml', + '~/.config/pynvim/config.yaml' +) + + +def load_config(config_file): + """Load config values from yaml.""" + + if config_file: + with open(config_file) as f: + return yaml.load(f) + + else: + for config_file in CONFIG_FILES: + try: + with open(os.path.expanduser(config_file)) as f: + return yaml.load(f) + + except IOError: + pass + + return {} + + +# http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/ +def detach_proc(workdir='.', umask=0): + """Detach a process from the controlling terminal and run it in the + background as a daemon. + """ + + # Default maximum for the number of available file descriptors. + MAXFD = 1024 + + # The standard I/O file descriptors are redirected to /dev/null by default. + if (hasattr(os, "devnull")): + REDIRECT_TO = os.devnull + else: + REDIRECT_TO = "/dev/null" + + try: + pid = os.fork() + except OSError, e: + raise Exception, "%s [%d]" % (e.strerror, e.errno) + + if (pid == 0): + os.setsid() + + try: + pid = os.fork() + + except OSError, e: + raise Exception, "%s [%d]" % (e.strerror, e.errno) + + if (pid == 0): + os.chdir(workdir) + os.umask(umask) + else: + os._exit(0) + else: + os._exit(0) + + maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] + if (maxfd == resource.RLIM_INFINITY): + maxfd = MAXFD + + # Iterate through and close all file descriptors. + for fd in range(0, maxfd): + try: + os.close(fd) + except OSError: + pass + + os.open(REDIRECT_TO, os.O_RDWR) + + os.dup2(0, 1) + os.dup2(0, 2) + + return(0) + + @click.command(context_settings=dict(allow_extra_args=True)) @click.option('--prog') @click.option('--notify', '-n', default=False, is_flag=True) @click.option('--listen', '-l') @click.option('--connect', '-c') -@click.option('--font', '-f', default=('Monospace', 13), nargs=2) @click.option('--profile', default='disable', type=click.Choice(['ncalls', 'tottime', 'percall', 'cumtime', 'name', 'disable'])) +@click.option('config_file', '--config', type=click.Path(exists=True)) +@click.option('--detach/--no-detach', default=True, is_flag=True) @click.pass_context -def main(ctx, prog, notify, listen, connect, font, profile): +def main(ctx, prog, notify, listen, connect, profile, config_file, detach): """Entry point.""" + + if detach: + exit_code = detach_proc() + address = connect or listen if address: @@ -61,10 +152,14 @@ def main(ctx, prog, notify, listen, connect, font, profile): nvim = attach('child', argv=nvim_argv) from .gtk_ui import GtkUI - ui = GtkUI(font) + config = load_config(config_file) + ui = GtkUI(config) bridge = UIBridge() bridge.connect(nvim, ui, profile if profile != 'disable' else None, notify) + if detach: + sys.exit(exit_code) + if __name__ == '__main__': main() diff --git a/neovim_gui/gtk_ui.py b/neovim_gui/gtk_ui.py index 8f1f1d8..5905609 100644 --- a/neovim_gui/gtk_ui.py +++ b/neovim_gui/gtk_ui.py @@ -73,13 +73,14 @@ class GtkUI(object): """Gtk+ UI class.""" - def __init__(self, font): + def __init__(self, config): """Initialize the UI instance.""" self._redraw_arg = None - self._foreground = -1 - self._background = -1 - self._font_name = font[0] - self._font_size = font[1] + self._foreground = config.get('foreground', -1) + self._background = config.get('background', -1) + self._window_background = config.get('window_background', '#aaaaaa') + self._font_size = config.get('font_size', 13) + self._font_name = config.get('font_name', 'Monospace') self._screen = None self._attrs = None self._busy = False @@ -115,6 +116,8 @@ def start(self, bridge): window.connect('scroll-event', self._gtk_scroll) window.connect('focus-in-event', self._gtk_focus_in) window.connect('focus-out-event', self._gtk_focus_out) + window.modify_bg(Gtk.StateType.NORMAL, + Gdk.color_parse(self._window_background)) window.show_all() im_context = Gtk.IMMulticontext() im_context.set_client_window(drawing_area.get_window()) diff --git a/setup.py b/setup.py index 71b88f3..a473350 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,8 @@ install_requires = [ 'neovim>=0.1.3', 'click>=3.0', - 'pygobject' + 'pygobject', + 'pyyaml' ] ext_modules = None From 8a2014d4593542d969d864104563da101c3c1833 Mon Sep 17 00:00:00 2001 From: Oliver Berger Date: Wed, 4 May 2016 21:52:44 +0200 Subject: [PATCH 2/2] removed unecessary reraising of generalized exceptions --- neovim_gui/cli.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/neovim_gui/cli.py b/neovim_gui/cli.py index dd4e341..596f7bf 100644 --- a/neovim_gui/cli.py +++ b/neovim_gui/cli.py @@ -53,20 +53,11 @@ def detach_proc(workdir='.', umask=0): else: REDIRECT_TO = "/dev/null" - try: - pid = os.fork() - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) - + pid = os.fork() if (pid == 0): os.setsid() - try: - pid = os.fork() - - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) - + pid = os.fork() if (pid == 0): os.chdir(workdir) os.umask(umask)