~sil2100/ibus-query/ibus-query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python
# -*- coding: utf-8 -*- 

# Copyright 2013 Ɓukasz 'sil2100' Zemczak
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.


from gi.repository import GLib
from gi.repository import IBus
import time
import dbus
import sys
import threading

class IBusQuery:
    """A simple class allowing string queries to the IBus engine."""

    def __init__(self):
        self._bus = IBus.Bus()
        try:
            self._dbusconn = dbus.connection.Connection(IBus.get_address())
        except:
            print "Error! The ibus-daemon doesn't seem to be running."
            quit()

        # XXX: the new IBus bindings do not export create_input_context for
        #  introspection. This is troublesome - so, to workaround this problem
        #  we're directly fetching a new input context manually
        ibus_obj = self._dbusconn.get_object(IBus.SERVICE_IBUS, IBus.PATH_IBUS)
        self._test = dbus.Interface(ibus_obj, dbus_interface="org.freedesktop.IBus")
        path = self._test.CreateInputContext("IBusPoll")
        self._context = IBus.InputContext.new(path, self._bus.get_connection(), None)

        self._glibloop = GLib.MainLoop()

        self._context.connect("commit-text", self.__commit_text_cb)
        self._context.connect("update-preedit-text", self.__update_preedit_cb)
        self._context.connect("disabled", self.__disabled_cb)
        self._context.set_capabilities (9)

    def __commit_text_cb(self, context, text):
        self.result += text.text
        self._preedit = ''

    def __update_preedit_cb(self, context, text, cursor_pos, visible):
        if visible:
            self._preedit = text.text

    def __disabled_cb(self, a):
        self.result += self._preedit
        self._glibloop.quit()

    def __abort(self):
        self._abort = True

    def poll(self, engine, ibus_input):
        if len(ibus_input) <= 0:
            return None

        self.result = ''
        self._preedit = ''
        self._context.focus_in()
        self._context.set_engine(engine)

        self._abort = False
        timeout = threading.Timer(4.0, self.__abort)
        timeout.start()
        while self._context.get_engine() is None:
            if self._abort is True:
                print "Error! Could not set the engine correctly."
                return None
            continue
        timeout.cancel()

        for c in ibus_input:
            self._context.process_key_event(ord(c), 0, 0)

        self._context.set_engine('')
        self._context.focus_out()

        GLib.timeout_add_seconds(5, lambda *args: self._glibloop.quit())
        self._glibloop.run()

        return self.result


if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "Usage: ibus-query engine-name query"
        quit()

    engine = sys.argv[1]
    query = sys.argv[2]

    poll = IBusQuery()
    print poll.poll(engine, query)