Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sebastien/urwide
Extensions for URWID
https://github.com/sebastien/urwide
Last synced: 14 days ago
JSON representation
Extensions for URWID
- Host: GitHub
- URL: https://github.com/sebastien/urwide
- Owner: sebastien
- Created: 2017-07-28T16:21:10.000Z (over 7 years ago)
- Default Branch: main
- Last Pushed: 2024-09-12T00:57:33.000Z (3 months ago)
- Last Synced: 2024-11-18T23:59:07.446Z (23 days ago)
- Language: Python
- Size: 71.3 KB
- Stars: 16
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- my-awesome-github-stars - sebastien/urwide - Extensions for URWID (Python)
README
```
____ _____________ __ __.___________ ___________
| | \______ \/ \ / \ \______ \ \_ _____/
| | /| _/\ \/\/ / || | \ | __)_
| | / | | \ \ /| || ` \| \
|______/ |____|_ / \__/\ / |___/_______ /_______ /
\/ \/ \/ \/
```Introduction
============[URWID](http://www.urwid.org) is a powerful library that allows you to write command-line
interfaces in the Python language. While URWID is very powerful, it is
quite low-level compared to existing UI toolkits, which can make development
of more advanced user interface a bit difficult.The main idea behind URWIDE is to extend URWID with a *domain-specific language
to describe console-based interfaces*, drastically reducing the amount of code
required to create console-based applications.URWIDE's declarative, text-based UI description language supports:
- MVC-like architecture
- Custom stylesheets
- Event handling (key, focus, press, edit)
- I18N (string collections)To give you an idea of what URWIDE can provide, here is a very simple
`helloworld.py` example:```python
import urwide# This is the equivalent of a CSS stylesheet
CONSOLE_STYLE = """
Frame : Dg, _, SO
header : WH, DC, BO
"""# This is the description of the actual interface
CONSOLE_UI = """\
Hdr URWIDE Hello world
___Txt Hello World ! args:#txt_hello
GFl
Btn [Hello !] &press=hello
Btn [Bye !] &press=bye
End
"""# This is the handling code, providing the logic
class Handler(urwide.Handler):
def onHello( self, button ):
self.ui.widgets.txt_hello.set_text("You said hello !")
def onBye( self, button ):
self.ui.end("bye !")# We create a console application
urwide.Console().create(CONSOLE_STYLE, CONSOLE_UI, Handler()).main()
```UI Description Language
=======================URWIDE allows to describe a user interface using a very simple line-oriented
language. You can define a complete UI in just a few lines. This description
allows you to:- Identify your widgets with a unique name
- Associate detailed information and tooltip
- Bind style information to your widgets
- Bind event handlersThe description syntax is very simple, and simply consists of a set of lines of
the following form:```
CLS DATA? [ID|STYLE|INFO|EVENT]* [ARGUMENTS]
```as an example, here is the definition of a button with `Click me!` as label,
which will be available as `btn_click`, displayed using the `clickButton`
style, displaying the `CLICK` tooltip when focused, and calling the
`clicked` callback when pressed :```
Btn [Click me!] #btn_click @clickButton !CLICK &press=clicked
```To sum up the available attributes:
- *CLS* is a three letter code that corresponds to the widget code
- *DATA* is a widget-specific text content
- *ID* sets the identifier of the widget
- *STYLE* sets the style class of the widget
- *EVENT* defines an event handler attached to the widget
- *INFO* defines the widget tooltip and detailed information
- *ARGUMENTS* defines additional widget attributes- Widget identifier
```
#id
```- Widget style class
```
@style
```- Widget tooltip
```
!TEXT
```- Widget info
```
?TEXT
```- Event handling
```
&event=method
```Supported events:
- `focus`
- `edit`
- `key`- Python arguments
```
name=value, name=value, name=value
```- Comments
```
# This is a comment
```Comments are useful to annotate your URWIDE source code, or to enable/disable
parts of it. Comments are simply lines starting with the `#` character.Blocks
------```
Ple
Txt I am within the above pile
End
```or
```
GFl
Txt Here are buttons
Btn [previous]
Btn [next]
End
```*SYNTAX* | *DESCRIPTION*
------------------|:-----------------------------------------------------
`#name` | Widget name, makes it accessible as `ui.widgets.name`
`@class` | Style class associated with the widget.
`&event=callback` | Makes the `onCallback` method of the `ui.handler()` react to the `event` (press, key, edit, focus) when it occurs on the widget.
`!TOOLTIP` | `ui.strings.TOOLTIP` or `"TOOLTIP"` is used as a tooltip for the widget (when it is focused)
`?INFO` | `ui.strings.INFO` or `"INFO"` is used as information for the widget (when it is focused) `arg=value, ...` Additional Python arguments that will be passed to the widget constructor (eg. `multiline=true` for Edit)
`# comment` | a comment line that will be ignored when parsingSupported Widgets
=================URWIDE tries to support most used URWID widgets, and also introduces _pseudo
widgets_ that facilitate the specification of your application layout.Blank
-----```
EOL
```A blank widget is simply an _empty line_ within the UI description.
Divider
-------```
---
===
:::
```These three forms create dividers composed of respectively `-`, `=` and `:`
characters. In case you will want a particular pattern in your divider, you
can user the following form:```
Dvd ~-~-
```Which will make you a divider composed of `~-~-`.
Text
----```
Txt TEXT
Txt TEXT args:ARGUMENTS
```Examples
```
Txt Hello, I'm a text
Txt Hello, I'm a text args:align='left'
```Note _________________________________________________________________
Be sure to use the `args:` prefix to give arguments to the text, because
otherwise your arguments will be interpreted as being part of the
displayed text.Button
------```
Btn [LABEL]
```Choice
------```
Chc [ :group] I am an unselected option
Chc [X:group] I am a selected option
Chc [X:other] I am a selected option from the 'other' group
Chc [ :group] I am an unselected option args:#my_choice
```A choice is composed of:
- Its _state_ and _group_ represented by the leading '[S:GROUP]', where 'S'
is either ' ' or 'X' and 'GROUP' is any string. Groups are availabled in
as 'ui.groups.GROUP' ('ui.groups' is a 'UI.Collection' instance)- Its _label_, following the state and group definition. It can be free-form
text.- The _ui arguments_, optionally following the label, but prefixed by
'args:'Pile
----```
Ple
...
End
```Gridflow
--------```
Gfl
...
End
```Box
---```
Box border=1
...
End
```Boxes allow to draw a border around a widget. You can simply indicate the
size of the border using the `border` attribute.Columns
-------```
Col
***
End
```Summary
-------*CODE* | *WIDGET* |*TYPE*
-------|:-------------------|:------------------------------------------
`Txt` | Text | widget
`Edt` | Edit | widget
`Btn` | Button | widget
`Chc` | RadioButton | widget
`Dvd` | Divider | widget
`Ple` | Pile | container
`GFl` | GridFlow | container
`Box` | Box (not in URWID) | containerEvent handling
==============URWIDE provides support for handling events and binding event handlers to each
individual widget. The events currently supported are:- `focus` (any), which is triggered when the widget received focus
- `key` (any), which is triggered when a key is pressed on a widget
- `edit` (Edit), which is triggered after an Edit was edited
- `press` (Buttons, CheckBox), which is triggered when a button is pressedEvents are handled by _handlers_, which are objects that define methods that
implement a particular reaction. For instance, if you have an event named
`showHelp`, you handler class will be like that:```
class MyHandler(urwide.Handler):def onShowHelp( self, widget ):
# Do something here
```And then, if you want to trigger the "`showHelp`" event when a button is
pressed:```
Btn [Show help] &press=showHelp
```This will automatically make the binding between the ui and the handler,
provided that you register your handler into the ui:```
ui.handler(MyHandler())
```Collections
===========URWIDE will create an instance of the `urwide.UI` class when given a style (will
be presented later) and a UI description. This instance will take care of
everything for you, from events to widgets. You will generally only want to
access or modify the `widgets` and `strings` collections.Both collections can be edited by accessing values as attribute. Setting an
attribute will add a key within the collection, accessing it will return the
bound value, or raise an exception if the value was not found.```
ui.strings.SOME_TEXT = "This text can be used as a value in a widget"ui.widgets
```Style syntax
============```
[STYLE] : FG, BG, FN
```- _STYLE_ is the name of the style
- _FG_ is the foreground color
- _BG_ is the backgrond color
- _FN_ is the font styleA style name can be:
- _URWID widget name_ (`Edit`, `Text`, etc)
- _style name_ (defined by `@style` in the widgets list)
- _widget id_, as defined by the `#id` of the UIFocus styles can be specified by appending `*` to each style name:
```
Edit : BL, _, SO
Edit* : DM, Lg, SO
```means that all `Edit` widgets will have black as color when unfocused, and dark
magenta when focused.Here is a table that sums up the possible values that can be used to describe
the styles. These values are described in the URWID reference for the
[Screen](http://excess.org/urwid/reference.html#Screen-register_palette_entry)
class.*CODE* | *VALUE* |*FOREGROUND*|*BACKGROUND*| *FONT*
-------|:--------------|:-----------|:-----------|:-------------------
WH | white | yes | no | -
BL | black | no | yes | -
YL | yellow | yes | no | -
BR | brown | yes | no | -
DR | dark red | no | yes | -
DB | dark blue | yes | yes | -
DG | dark green | yes | yes | -
DM | dark magenta | yes | yes | -
DC | dark cyan | yes | yes | -
Dg | dark gray | yes | no | -
LR | light red | yes | no | -
LG | light green | yes | no | -
LB | light blue | yes | no | -
LM | light magenta | yes | no | -
LC | light cyan | yes | no | -
Lg | light gray | yes | yes | -
BO | bold | - | - | yes
UL | underline | - | - | yes
SO | standout | - | - | yes
_ | default | yes | yes | yesUsing dialogs:
```python
dialog = Dialog()
# Don't know why this is necessary, but it doesn't work if it's not there
sialog.handler(dialog_handler)
self.pushHandler(dialog_handler)def dialog_end():
self.popHandler()
```