From 9f5e0353058a131fe800ce8dd0f01e7453bd6643 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 30 Aug 2015 03:24:55 +0200 Subject: [PATCH 1/4] Add giant notice to point people to the new filenav repo If anyone overlooks this, it's their fault. --- filenav.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/filenav.py b/filenav.py index 5ea9715..0401df0 100644 --- a/filenav.py +++ b/filenav.py @@ -1,4 +1,23 @@ # -*- coding: utf-8 -*- +############################################################################### +# THIS VERSION OF FILENAV IS OLD AND NO LONGER UPDATED! +# THIS VERSION OF FILENAV IS OLD AND NO LONGER UPDATED! +# THIS VERSION OF FILENAV IS OLD AND NO LONGER UPDATED! +# Did I mention that THIS VERSION OF FILENAV IS OLD AND NO LONGER UPDATED? +# For the current version of filenav, see the dedicated filenav repo: +# https://github.com/dgelessus/filenav +############################################################################### + + + + + + + + + + + ############################################################################### # filenav by dgelessus # http://github.com/dgelessus/pythonista-scripts/blob/master/filenav.py From 9ef39620ea154dd68ff717564ac27206c029832c Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 30 Aug 2015 03:30:16 +0200 Subject: [PATCH 2/4] License, finally --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9a4f1c7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 dgelessus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 1108ce42c50307d3c8334c126061ee745ff9b68d Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sat, 12 Dec 2015 18:45:47 +0100 Subject: [PATCH 3/4] Create moduledump.py --- moduledump.py | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 moduledump.py diff --git a/moduledump.py b/moduledump.py new file mode 100644 index 0000000..324ef58 --- /dev/null +++ b/moduledump.py @@ -0,0 +1,109 @@ +import collections +import inspect +import importlib +import io +import os +import sys +import types + +def flatten(seq): + for obj in seq: + try: + it = iter(obj) + except TypeError: + yield obj + else: + for o in flatten(obj): + yield o + +def sorted_mapping(mapping, **kwargs): + out = collections.OrderedDict() + + for k in sorted(mapping.keys(), **kwargs): + out[k] = mapping[k] + + return out + +def order_classes(classes): + classes = list(classes) + ordered = list(flatten(inspect.getclasstree(classes))) + + ordered.reverse() + + for cls in list(ordered): + if cls not in classes or ordered.count(cls) > 1: + ordered.remove(cls) + + ordered.reverse() + + return ordered + +def order_attributes(attrs): + constants = {} + functions = {} + classes = {} + + for key, value in attrs.items(): + if isinstance(value, type(int.real)) or key in ("__abstractmethods__", "__base__", "__bases__", "__class__", "__dict__", "__dictoffset__", "__file__", "__flags__", "__itemsize__", "__module__", "__name__", "__package__", "__subclasses__", "__weakrefoffset__"): + pass + elif isinstance(value, (type, types.ClassType)): + classes[key] = value + elif isinstance(value, (types.FunctionType, types.BuiltinFunctionType, type(list.append), type(object.__init__), classmethod, staticmethod)): + if not (key.startswith("__") and key.endswith("__")): + functions[key] = value + else: + constants[key] = value + + constants = sorted_mapping(constants) + functions = sorted_mapping(functions) + classes = sorted_mapping(classes) + classes_reverse = collections.OrderedDict((v, k) for k, v in classes.items()) + + classes_ordered = collections.OrderedDict((classes_reverse[cls], cls) for cls in order_classes(classes.values())) + + return collections.OrderedDict(constants.items() + functions.items() + classes_ordered.items()) + +def stringify_constant(name, value): + return u"{} = {!r}".format(name, value) + +def stringify_function(name, value): + return u"def {}(*args, **kwargs): pass".format(name) + +def stringify_classmethod(name, value): + return u"def {}(cls, *args, **kwargs): pass".format(name) + +def stringify_method(name, value): + return u"def {}(self, *args, **kwargs): pass".format(name) + +def stringify_class(name, value): + attrs = list((k, v) for k, v in inspect.getmembers(value) if not hasattr(super(value), k) or v != getattr(super(value), k)) + + if type(value) not in [type(cls) for cls in value.__bases__]: + attrs = [("__metaclass__", type(value))] + attrs + + body = u"\n".join(u" " + line for line in stringify_attributes(order_attributes(collections.OrderedDict(attrs))).splitlines()) + + return u"\nclass {}({}):\n{}".format(name, ", ".join(cls.__name__ for cls in value.__bases__), body) + +def stringify_attributes(attrs): + lines = [] + + for k, v in attrs.items(): + if isinstance(v, (type, types.ClassType)): + lines.append(stringify_class(k, v)) + elif isinstance(v, (types.MethodType, type(list.append), type(object.__init__))): + lines.append(stringify_method(k, v)) + elif isinstance(v, classmethod): + lines.append(stringify_classmethod(k, v)) + elif isinstance(v, (types.FunctionType, types.BuiltinFunctionType, staticmethod)): + lines.append(stringify_function(k, v)) + else: + lines.append(stringify_constant(k, v)) + + return u"\n".join(lines) + +if __name__ == "__main__": + name = sys.argv[1] + + with io.open(os.extsep.join((name, u"py")), "w") as f: + f.write(stringify_attributes(order_attributes(collections.OrderedDict(inspect.getmembers(importlib.import_module(name)))))) From aa318cfe4ca9f7cf9c4b97e678b0685a4b337449 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Thu, 5 May 2016 22:10:12 +0200 Subject: [PATCH 4/4] Create today_python_console.py --- today_python_console.py | 210 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 today_python_console.py diff --git a/today_python_console.py b/today_python_console.py new file mode 100644 index 0000000..b768c1e --- /dev/null +++ b/today_python_console.py @@ -0,0 +1,210 @@ +import appex +import code +import sys +import threading +import time +import ui + +class NotifyOnCloseView(ui.View): + def will_close(self): + with self.condition: + self.condition.notify_all() + +class Keyboard(object): + KEY_LAYOUTS = [ + [ + [*"^1234567890ß´", "BACKSPACE"], + [*"qwertzuiopü+", "ENTER_TOP"], + [*"asdfghjklöä#", "ENTER_BOTTOM"], + ["SHIFT", *"YXCVBNM;:_"], + ["ALT", "SPACE", "ARROW_LEFT", "ARROW_RIGHT"], + ], [ + [*"„¡“¶¢[]|{}≠¿'", "BACKSPACE"], + [*"«∑€®†Ω¨⁄øπ•±", "ENTER_TOP"], + [*"å‚∂ƒ©ªº∆@œæ‘", "ENTER_BOTTOM"], + ["SHIFT", *"≤¥≈ç√∫~µ∞…–"], + ["ALT", "SPACE", "ARROW_LEFT", "ARROW_RIGHT"], + ], [ + [*"“¬”#£fi^\\˜·¯˙˚", "BACKSPACE"], + [*"»„‰¸˝ˇÁÛØ∏°", "ENTER_TOP"], + [*"ÅÍ™ÏÌÓıˆflŒÆ’", "ENTER_BOTTOM"], + ["SHIFT", *"≥‡ÙÇ◊‹›˘˛÷—"], + ["ALT", "SPACE", "ARROW_LEFT", "ARROW_RIGHT"], + ], + ] + + KEY_SYMBOLS = { + "ALT": "\N{option key}", + "ARROW_LEFT": "\N{leftwards arrow}", + "ARROW_RIGHT": "\N{rightwards arrow}", + "BACKSPACE": "\N{erase to the left}", + "ENTER_BOTTOM": "\N{return symbol}", + "ENTER_TOP": "|", + "SHIFT": "\N{upwards white arrow}", + "SPACE": "\N{open box}", + } + + MOD_SHIFT = 1 << 0 + MOD_ALT = 1 << 1 + + def __init__(self): + self.text = [] + self.pos = 0 + self.modifiers = 0b00 + + ##self.root = ui.load_view("keyboard") + self.root = NotifyOnCloseView() + self.root.width = 480 + self.root.height = 480 + self.root.bg_color = (0.0, 0.0, 0.0, 0.0) + + self.root.add_subview(ui.Label(name="textbox")) + self.root["textbox"].flex = "TW" + self.root["textbox"].x = 0 + self.root["textbox"].y = 274 + self.root["textbox"].width = self.root.width + self.root["textbox"].height = 32 + self.root["textbox"].text = "|" + self.root["textbox"].font = ("Menlo", 18) + self.root["textbox"].text_color = (1.0, 1.0, 1.0, 1.0) + + self.root.add_subview(ui.View(name="keys")) + self.root["keys"].flex = "TW" + self.root["keys"].x = 0 + self.root["keys"].y = 314 + self.root["keys"].width = self.root.width + self.root["keys"].height = 160 + + self.reading = self.root.condition = threading.Condition() + + self.cached_layouts = [] + + for layout in type(self).KEY_LAYOUTS: + container = ui.View() + self.cached_layouts.append(container) + container.flex = "WH" + container.x = 0 + container.y = 0 + container.width = self.root["keys"].width + container.height = self.root["keys"].height + + row_height = container.height / len(layout) + + for i, chars in enumerate(layout): + row = ui.View() + container.add_subview(row) + row.x = 0 + row.y = i * row_height + row.width = row.superview.width + row.height = row_height + row.flex = "TBLRWH" + + key_width = row.width / len(chars) + + for j, char in enumerate(chars): + key = ui.Button() + row.add_subview(key) + key.x = j * key_width + key.y = 0 + key.width = key_width + key.height = key.superview.height + key.flex = "TBLRWH" + key.font = ("Menlo", 18) + key.key = char + key.title = type(self).KEY_SYMBOLS.get(char, char) + key.tint_color = (1.0, 1.0, 1.0, 1.0) + key.bg_color = (0.0, 0.0, 0.0, 0.25) + key.border_color = (0.0, 0.0, 0.0, 1.0) + key.border_width = 2.0 + key.corner_radius = 5.0 + key.action = self.key_pressed + + self.update_layout() + + def update_layout(self): + keys = self.root["keys"] + + for sv in keys.subviews: + keys.remove_subview(sv) + + v = self.cached_layouts[self.modifiers] + keys.add_subview(v) + v.x = 0 + v.y = 0 + v.width = keys.width + v.height = keys.height + + def update_text(self): + self.root["textbox"].text = "".join([*self.text[:self.pos], "|", *self.text[self.pos:]]) + + def key_pressed(self, sender): + key = sender.key + + if key == "ALT": + self.modifiers ^= type(self).MOD_ALT + self.update_layout() + elif key == "ARROW_LEFT": + if self.pos > 0: + self.pos -= 1 + elif key == "ARROW_RIGHT": + if self.pos < len(self.text): + self.pos += 1 + elif key == "BACKSPACE": + if self.pos > 0: + del self.text[self.pos-1] + self.pos -= 1 + elif key in {"ENTER_BOTTOM", "ENTER_TOP"}: + self.text.append("\n") + with self.reading: + self.reading.notify() + elif key == "SHIFT": + self.modifiers ^= type(self).MOD_SHIFT + self.update_layout() + elif key == "SPACE": + self.text.insert(self.pos, " ") + self.pos += 1 + else: + self.text.insert(self.pos, key) + self.pos += 1 + + self.update_text() + + def read(self, size=-1): + with self.reading: + self.reading.wait() + ret = "".join(self.text) + + self.text.clear() + self.pos = 0 + self.update_text() + + print(ret, end="") + return ret + +def main(): + kb = Keyboard() + + if appex.is_widget(): + appex.set_widget_view(kb.root) + else: + kb.root.present("sheet") + + def read(self, size=-1): + return kb.read(size) + + def readline(self): + return kb.read() + + sys.stdin.__class__.read = read + sys.stdin.__class__.readline = readline + + code.interact() + +if __name__ == "__main__": + main()