Completed
Push — master ( 54dda6...3c4c23 )
by timothy
01:57 queued 55s
created

UIBridge.connect()   A

Complexity

Conditions 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
c 1
b 0
f 1
dl 0
loc 20
rs 9.4285
1
"""Bridge for connecting a UI instance to nvim."""
2
import sys
3
from threading import Semaphore, Thread
4
from traceback import format_exc
5
6
7
class UIBridge(object):
8
9
    """UIBridge class. Connects a Nvim instance to a UI class."""
10
11
    def connect(self, nvim, ui, profile=None, notify=False):
12
        """Connect nvim and the ui.
13
14
        This will start loops for handling the UI and nvim events while
15
        also synchronizing both.
16
        """
17
        self._notify = notify
18
        self._error = None
19
        self._nvim = nvim
20
        self._ui = ui
21
        self._profile = profile
22
        self._sem = Semaphore(0)
23
        t = Thread(target=self._nvim_event_loop)
24
        t.daemon = True
25
        t.start()
26
        self._ui_event_loop()
27
        if self._error:
28
            print(self._error)
29
        if self._profile:
30
            print(self._profile)
31
32
    def exit(self):
33
        """Disconnect by exiting nvim."""
34
        self.detach()
35
        self._call(self._nvim.quit)
36
37
    def input(self, input_str):
38
        """Send input to nvim."""
39
        self._call(self._nvim.input, input_str)
40
41
    def resize(self, columns, rows):
42
        """Send a resize request to nvim."""
43
        self._call(self._nvim.ui_try_resize, columns, rows)
44
45
    def attach(self, columns, rows, rgb):
46
        """Attach the UI to nvim."""
47
        self._call(self._nvim.ui_attach, columns, rows, rgb)
48
49
    def detach(self):
50
        """Detach the UI from nvim."""
51
        self._call(self._nvim.ui_detach)
52
53
    def _call(self, fn, *args):
54
        self._nvim.async_call(fn, *args)
55
56
    def _ui_event_loop(self):
57
        self._sem.acquire()
58
        if self._profile:
59
            import StringIO
60
            import cProfile
61
            import pstats
62
            pr = cProfile.Profile()
63
            pr.enable()
64
        self._ui.start(self)
65
        if self._profile:
66
            pr.disable()
67
            s = StringIO.StringIO()
68
            ps = pstats.Stats(pr, stream=s)
69
            ps.strip_dirs().sort_stats(self._profile).print_stats(30)
70
            self._profile = s.getvalue()
71
72
    def _nvim_event_loop(self):
73
        def on_setup():
74
            self._sem.release()
75
76
        def on_request(method, args):
77
            raise Exception('Not implemented')
78
79
        def on_notification(method, updates):
80
            def apply_updates():
81
                if self._notify:
82
                    sys.stdout.write('attached\n')
83
                    sys.stdout.flush()
84
                    self._notify = False
85
                try:
86
                    for update in updates:
87
                        # import sys
88
                        # l = [','.join([str(a) for a in args])
89
                        #      for args in update[1:]]
90
                        # print >> sys.stderr, update[0], ' '.join(l)
91
                        try:
92
                            handler = getattr(self._ui, '_nvim_' + update[0])
93
                        except AttributeError:
94
                            pass
95
                        else:
96
                            for args in update[1:]:
97
                                handler(*args)
98
                except:
99
                    self._error = format_exc()
100
                    self._call(self._nvim.quit)
101
            if method == 'redraw':
102
                self._ui.schedule_screen_update(apply_updates)
103
104
        self._nvim.run_loop(on_request, on_notification, on_setup)
105
        self._ui.quit()
106