Tweaked the interfaces a bit, added Python documentation, and added

"Press 'q' to quit" message.
This commit is contained in:
Bruce Hill 2020-04-19 15:59:48 -07:00
parent a41bce136a
commit 470fa9e7c6
5 changed files with 117 additions and 56 deletions

View File

@ -19,10 +19,16 @@ int main(void)
btui_printf(bt, "%s", title); btui_printf(bt, "%s", title);
btui_set_attributes(bt, BTUI_NORMAL); btui_set_attributes(bt, BTUI_NORMAL);
btui_set_attributes(bt, BTUI_FG_NORMAL | BTUI_FAINT); btui_set_attributes(bt, BTUI_BOLD);
btui_move_cursor(bt, 0, bt->height-2);
btui_printf(bt, "Press 'q' to quit");
btui_set_attributes(bt, BTUI_NORMAL);
btui_set_attributes(bt, BTUI_FAINT);
btui_move_cursor(bt, bt->width-16, bt->height-2); btui_move_cursor(bt, bt->width-16, bt->height-2);
btui_printf(bt, "Size = %dx%d", bt->width, bt->height); btui_printf(bt, "Size = %dx%d", bt->width, bt->height);
btui_set_attributes(bt, BTUI_NORMAL); btui_set_attributes(bt, BTUI_NORMAL);
btui_flush(bt); btui_flush(bt);
int mouse_x = -1, mouse_y = -1; int mouse_x = -1, mouse_y = -1;

View File

@ -32,6 +32,11 @@ btui(function(bt)
bt:write(title) bt:write(title)
end) end)
bt:withattributes("bold", function()
bt:move(0, bt:height()-1)
bt:write("Press 'q' to quit")
end)
bt:withattributes("faint", function() bt:withattributes("faint", function()
local s = ("Size: (%dx%d)"):format(bt:width(), bt:height()) local s = ("Size: (%dx%d)"):format(bt:width(), bt:height())
bt:move(bt:width()-#s, bt:height()-1) bt:move(bt:width()-#s, bt:height()-1)

View File

@ -1,7 +1,7 @@
import ctypes import ctypes
from contextlib import contextmanager from contextlib import contextmanager
__all__ = ['btui'] __all__ = ['open_btui']
# Load the shared library into c types. # Load the shared library into c types.
libbtui = ctypes.CDLL("./libbtui.so") libbtui = ctypes.CDLL("./libbtui.so")
@ -101,12 +101,6 @@ BTUI_INVERSE_ATTRS = {
class BTUI: class BTUI:
def __enter__(self):
self.enable()
def __exit__(self, *exc):
self.disable()
def enable(self): def enable(self):
self._btui = libbtui.btui_enable() self._btui = libbtui.btui_enable()
@ -231,4 +225,10 @@ class BTUI:
libbtui.btui_draw_shadow(self._btui, int(x), int(y), int(w), int(h)) libbtui.btui_draw_shadow(self._btui, int(x), int(y), int(w), int(h))
btui = BTUI() _btui = BTUI()
@contextmanager
def open_btui():
_btui.enable()
try: yield _btui
finally: _btui.disable()

View File

@ -1,37 +1,41 @@
from btui import btui from btui import open_btui
with btui: with open_btui() as bt:
key = None key = None
x, y = 1, 1 x, y = 1, 1
while key != 'q' and key != 'Ctrl-c': while key != 'q' and key != 'Ctrl-c':
if key == '?': if key == '?':
with btui.disabled(): with bt.disabled():
input("Press enter to continue.") input("Press enter to continue.")
elif key == 'Ctrl-z': elif key == 'Ctrl-z':
btui.suspend() bt.suspend()
btui.clear() bt.clear()
with btui.fg(.8, .95, .2): with bt.fg(.8, .95, .2):
btui.outline_box(x, y, 30, 1) bt.outline_box(x, y, 30, 1)
btui.move(x, y) bt.move(x, y)
btui.write(f"Pressed: {key}") bt.write(f"Pressed: {key}")
with btui.attributes("bg_blue", "fg_black"): with bt.attributes("bg_blue", "fg_black"):
title = "Python BTUI Demo" title = "Python bt Demo"
w = len(title) w = len(title)
center = (btui.width - w) // 2 center = (bt.width - w) // 2
btui.fill_box(center - 2, 0, w + 4, 3) bt.fill_box(center - 2, 0, w + 4, 3)
btui.draw_shadow(center - 2, 0, w + 4, 3) bt.draw_shadow(center - 2, 0, w + 4, 3)
btui.move(center, 1) bt.move(center, 1)
btui.write(title) bt.write(title)
with btui.attributes("faint"): with bt.attributes("bold"):
s = f"Size: ({btui.width}x{btui.height})" bt.move(0, bt.height-1)
btui.move(btui.width-len(s), btui.height-1) bt.write("Press 'q' to quit")
btui.write(s)
key, mx, my = btui.getkey() with bt.attributes("faint"):
s = f"Size: ({bt.width}x{bt.height})"
bt.move(bt.width-len(s), bt.height-1)
bt.write(s)
key, mx, my = bt.getkey()
if mx: if mx:
x, y = mx, my x, y = mx, my

View File

@ -79,7 +79,7 @@ key handling can be improved slightly by polling with zero timeout.
## Language Bindings ## Language Bindings
BTUI comes with bindings for C and Lua, with plans to add Python bindings. BTUI comes with bindings for C, Python, and Lua.
### C API ### C API
@ -122,38 +122,84 @@ be called with a `BTUI` object, which can be used to do TUI actions. Errors will
be propagated out of the function, but the terminal will be cleaned up nicely be propagated out of the function, but the terminal will be cleaned up nicely
before the error is printed. Here's a simple example program: before the error is printed. Here's a simple example program:
require("btui")(function(bt) ```lua
-- Run this code within the TUI, using "bt" as the TUI object require("btui")(function(bt)
... -- Run this code within the TUI, using "bt" as the TUI object
end) ...
end)
bt:enable() -- Enables btui (if previously disabled) bt:enable() -- Enables btui (if previously disabled)
bt:disable() -- Disables btui bt:disable() -- Disables btui
bt:withdisabled(fn) -- Calls "fn" with btui disabled, then re-enables btui bt:withdisabled(fn) -- Calls "fn" with btui disabled, then re-enables btui
bt:getkey(timeout=-1) -- Returns a keypress (and optionally, mouse x and y coordinates). The optional timeout argument specifies how long, in tenths of a second, to wait for the next keypress. bt:getkey(timeout=-1) -- Returns a keypress (and optionally, mouse x and y coordinates). The optional timeout argument specifies how long, in tenths of a second, to wait for the next keypress.
bt:write() -- Write text to the terminal bt:write() -- Write text to the terminal
bt:clear(type="screen") -- Clear the terminal. Options are: "screen", "right", "left", "above", "below", "line" bt:clear(type="screen") -- Clear the terminal. Options are: "screen", "right", "left", "above", "below", "line"
bt:flush() -- Flush the terminal output. Most operations do this anyways. bt:flush() -- Flush the terminal output. Most operations do this anyways.
bt:move(x, y) -- Move the cursor to the given position. (0,0) is the top left corner. bt:move(x, y) -- Move the cursor to the given position. (0,0) is the top left corner.
-- R,G,B values are in the range [0.0, 1.0]: -- R,G,B values are in the range [0.0, 1.0]:
bt:withfg(r,g,b, fn) -- Set the foreground color to (r,g,b), call fn, then reset the foreground color to default bt:withfg(r,g,b, fn) -- Set the foreground color to (r,g,b), call fn, then reset the foreground color to default
bt:withbg(r,g,b, fn) -- Set the background color to (r,g,b), call fn, then reset the background color to default bt:withbg(r,g,b, fn) -- Set the background color to (r,g,b), call fn, then reset the background color to default
bt:linebox(x,y,w,h) -- Draw an outlined box around the given rectangle bt:linebox(x,y,w,h) -- Draw an outlined box around the given rectangle
bt:fillbox(x,y,w,h) -- Fill the given rectangle with space characters bt:fillbox(x,y,w,h) -- Fill the given rectangle with space characters
bt:shadow(x,y,w,h) -- Draw a shaded shadow to the bottom right of the given rectangle bt:shadow(x,y,w,h) -- Draw a shaded shadow to the bottom right of the given rectangle
bt:withattributes(attrs..., fn) -- Set the given attributes, call fn, then unset them bt:withattributes(attrs..., fn) -- Set the given attributes, call fn, then unset them
bt:setattributes(attrs...) -- Set the given attributes bt:setattributes(attrs...) -- Set the given attributes
bt:unsetattributes(attrs...) -- Unset the given attributes bt:unsetattributes(attrs...) -- Unset the given attributes
bt:suspend() -- Suspend the current process and drop back into normal terminal mode bt:suspend() -- Suspend the current process and drop back into normal terminal mode
bt:width() -- Return the scren width bt:width() -- Return the scren width
bt:height() -- Return the screen height bt:height() -- Return the screen height
```
See [Lua/test.lua](Lua/test.lua) for example usage. Run `make lua` to build the See [Lua/test.lua](Lua/test.lua) for example usage. Run `make lua` to build the
Lua library, and `make testlua` to run the Lua BTUI demo. Lua library, and `make testlua` to run the Lua BTUI demo.
### Python API ### Python API
Coming soon. The Python library has only one value: `open_btui()`. This is a context manager,
which can be used to safely wrap TUI applications.
```python
import btui
with btui.open_btui() as bt:
# Your code here...
```
The returned object has the following methods:
```python
def enable(self):
def disable(self):
@contextmanager
def disabled(self):
def getkey(self, timeout=None): # returns key, mouse_x, mouse_y
@property
def width(self):
@property
def height(self):
def write(self, *args, sep=''):
def write_bytes(self, b):
def move(self, x, y):
def flush(self):
def suspend(self):
def clear(self, mode='screen'):
def set_attributes(self, *attrs):
def unset_attributes(self, *attrs):
@contextmanager
def attributes(self, *attrs):
def set_fg(self, r, g, b):
def set_bg(self, r, g, b):
@contextmanager
def fg(self, r, g, b):
@contextmanager
def bg(self, r, g, b):
def outline_box(self, x, y, w, h):
def fill_box(self, x, y, w, h):
def draw_shadow(self, x, y, w, h):
```
See [Python/test.py](Python/test.py) for example code, which can be run with
`make testpython`.
## FAQ ## FAQ