Add preliminary(!) support for bidirectional communication with i3bar

Novelty use only.
This commit is contained in:
enkore 2013-03-09 21:23:36 +01:00
parent 279c3504c2
commit 657bdb826a
7 changed files with 46 additions and 5 deletions

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys
import threading
from .core import util, io from .core import util, io
from .core.modules import * from .core.modules import *
@ -18,8 +19,12 @@ def main():
class Status: class Status:
def __init__(self, standalone=False, interval=1, input_stream=sys.stdin): def __init__(self, standalone=False, interval=1, input_stream=sys.stdin):
self.standalone = standalone
if standalone: if standalone:
self.io = io.StandaloneIO(interval) self.io = io.StandaloneIO(interval)
self.ce_thread = threading.Thread(target=self.run_command_endpoint)
self.ce_thread.daemon = True
self.ce_thread.start()
else: else:
self.io = io.IOHandler(input_stream) self.io = io.IOHandler(input_stream)
@ -31,6 +36,13 @@ class Status:
if module: if module:
self.modules.append(module, *args, **kwargs) self.modules.append(module, *args, **kwargs)
def run_command_endpoint(self):
for j in io.JSONIO(io=io.IOHandler(sys.stdin, io.DevNull()), skiplines=1).read():
if j["command"] == "block_clicked":
module = self.modules.get_by_id(j["instance"])
if module:
module.on_click()
def run(self): def run(self):
for j in io.JSONIO(self.io).read(): for j in io.JSONIO(self.io).read():
for module in self.modules: for module in self.modules:

View File

@ -2,7 +2,13 @@
import time import time
import json import json
import sys import sys
import threading
from contextlib import contextmanager from contextlib import contextmanager
import io
class DevNull(io.TextIOBase):
def write(self, string):
pass
class IOHandler: class IOHandler:
def __init__(self, inp=sys.stdin, out=sys.stdout): def __init__(self, inp=sys.stdin, out=sys.stdout):
@ -50,7 +56,7 @@ class StandaloneIO(IOHandler):
""" """
n = -1 n = -1
proto = ('{"version":1}', "[", "[]", ",[]", ) proto = ('{"version":1,"bidirectional":1}', "[", "[]", ",[]", )
def __init__(self, interval=1): def __init__(self, interval=1):
super().__init__() super().__init__()
@ -62,6 +68,7 @@ class StandaloneIO(IOHandler):
time.sleep(self.interval) time.sleep(self.interval)
except KeyboardInterrupt: except KeyboardInterrupt:
return return
yield self.read_line() yield self.read_line()
def read_line(self): def read_line(self):
@ -70,10 +77,10 @@ class StandaloneIO(IOHandler):
return self.proto[min(self.n, len(self.proto)-1)] return self.proto[min(self.n, len(self.proto)-1)]
class JSONIO: class JSONIO:
def __init__(self, io): def __init__(self, io, skiplines=2):
self.io = io self.io = io
self.io.write_line(self.io.read_line()) for i in range(skiplines):
self.io.write_line(self.io.read_line()) self.io.write_line(self.io.read_line())
def read(self): def read(self):
"""Iterate over all JSON input (Generator)""" """Iterate over all JSON input (Generator)"""

View File

@ -18,8 +18,12 @@ class Module(SettingsBase):
if self.output: if self.output:
if "name" not in self.output: if "name" not in self.output:
self.output["name"] = self.__name__ self.output["name"] = self.__name__
self.output["instance"] = str(id(self))
json.insert(0, self.output) json.insert(0, self.output)
def on_click(self):
pass
def __repr__(self): def __repr__(self):
return self.__class__.__name__ return self.__class__.__name__

View File

@ -51,6 +51,13 @@ class ModuleList(collections.UserList):
module.registered(self.status_handler) module.registered(self.status_handler)
super().append(module) super().append(module)
def get_by_id(self, find_id):
find_id = int(find_id)
for module in self:
if int(id(module)) == find_id:
return module
return None
class PrefixedKeyDict(collections.UserDict): class PrefixedKeyDict(collections.UserDict):
def __init__(self, prefix): def __init__(self, prefix):
super().__init__() super().__init__()

View File

@ -8,6 +8,7 @@ import urllib.request, urllib.parse, urllib.error
import re import re
import http.cookiejar import http.cookiejar
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import webbrowser
from i3pystatus import IntervalModule from i3pystatus import IntervalModule
@ -85,3 +86,6 @@ class ModsDeChecker(IntervalModule):
self.logged_in = True self.logged_in = True
self.opener.addheaders.append(("Cookie", "{}={}".format(cookie.name, cookie.value))) self.opener.addheaders.append(("Cookie", "{}={}".format(cookie.name, cookie.value)))
return True return True
def on_click(self):
webbrowser.open_new_tab("http://forum.mods.de/bb/")

View File

@ -1,5 +1,6 @@
from urllib.request import urlopen from urllib.request import urlopen
import webbrowser
import lxml.html import lxml.html
from lxml.cssselect import CSSSelector from lxml.cssselect import CSSSelector
@ -37,6 +38,9 @@ class DHL(TrackerAPI):
ret["status"] = self.intrarow_status_selector(last_row)[0].text.strip() ret["status"] = self.intrarow_status_selector(last_row)[0].text.strip()
return ret return ret
def get_url(self):
return self.url
class ParcelTracker(IntervalModule): class ParcelTracker(IntervalModule):
interval = 20 interval = 20
@ -59,3 +63,6 @@ class ParcelTracker(IntervalModule):
"full_text": self.format.format(**fdict).strip(), "full_text": self.format.format(**fdict).strip(),
"instance": self.name, "instance": self.name,
} }
def on_click(self):
webbrowser.open_new_tab(self.instance.get_url())

View File

@ -3,7 +3,7 @@
from setuptools import setup from setuptools import setup
setup(name="i3pystatus", setup(name="i3pystatus",
version="3.8.2", version="3.9",
description="Like i3status, this generates status line for i3bar / i3wm", description="Like i3status, this generates status line for i3bar / i3wm",
url="http://github.com/enkore/i3pystatus", url="http://github.com/enkore/i3pystatus",
license="MIT", license="MIT",