Create TUI on python

Hello, Habr! In this article I'll talk about
npyscreen
- a library for creating text interfaces for terminal and console applications.
 
Create TUI on python
 
site with the documentation .
 
Let's write Hello World
 
It is convenient to create forms by inheriting them from the built-in classes. Thus, you can override the built-in methods to extend the functionality of the application.
 
Here is a simple Hello World [/b]
#! /usr /bin /env python3
import npyscreen
class App (npyscreen.StandardApp):
def onStart (self):
self.addForm ("MAIN", MainForm, name = "Hello Habr!")
class MainForm (npyscreen.ActionForm):
# Constructor
def create (self):
# Add the TitleText widget to the form
self.title = self.add (npyscreen.TitleText, name = "TitleText", value = "Hello World!")
# an override method that triggers when the "ok" button
is clicked. def on_ok (self):
self.parentApp.setNextForm (None)
# an overridden method that triggers when the cancel button is pressed
def on_cancel (self):
self.title.value = "Hello World!"
MyApp = App ()
MyApp.run ()

 

 
 
The arrangement of the elements is
 
By default, widgets occupy the maximum possible space.
 
To specify the exact coordinates, you need to set the parameters:
 
 
relx
,
rely
- the position of the widget relative to the origin of the form.
 
width
,
height
,
max_width
,
max_height
- Limit the size of the widget.
 
 
Example [/b]
#! /usr /bin /env python3
import npyscreen
class App (npyscreen.StandardApp):
def onStart (self):
self.addForm ("MAIN", MainForm, name = "Hello Habr!")
class MainForm (npyscreen.FormBaseNew):
def create (self):
# Recognize the space used by the form
y, x = self.useable_space ()
self.add (npyscreen.TitleDateCombo, name = "Date:", max_width = x //2)
self.add (npyscreen.TitleMultiSelect, relx = x //2 + ? rely = ? value =[1, 2], name = "Pick Several", values ​​=["Option1", "Option2", "Option3"], scroll_exit = True)
# You can use the negative coordinates
self.add (npyscreen.TitleFilename, name = "Filename:", rely = -5)
MyApp = App ()
MyApp.run ()

 

 
 
Boxes and custom colors
 
To make a wrapper in the form of a box is simple - you need to create a class inherited from
BoxTitle
and override the attribute
_contained_widget
, putting there the widget that will be inside.
 
In
npyscreen
Several built-in color themes are available. If you want, you can add your own. You can install them using the
method. setTheme
.
 
With the adjustment of the color of the text, everything is slightly more complicated. I had expand the functional library to make it work.
 
Example [/b]
#! /usr /bin /env python3
from src import npyscreen
import random
class App (npyscreen.StandardApp):
def onStart (self):
# Set the theme. DefaultTheme
is used by default. npyscreen.setTheme (npyscreen.Themes.ColorfulTheme)
self.addForm ("MAIN", MainForm, name = "Hello Habr!")
class InputBox (npyscreen.BoxTitle):
# MultiLineEdit will now be surrounded by box
_contained_widget = npyscreen.MultiLineEdit
class MainForm (npyscreen.FormBaseNew):
def create (self):
y, x = self.useable_space ()
obj = self.add (npyscreen.BoxTitle, name = "BoxTitle",
custom_highlighting = True, values ​​=["first line", "second line"],
.us = y //? max_width = x //2 - ? max_height = y //2)
self.add (InputBox, name = "Boxed MultiLineEdit", footer = "footer",
relx = x //? rely = 2)
color1 = self.theme_manager.findPair (self, 'GOOD')
color2 = self.theme_manager.findPair (self, 'WARNING')
color3 = self.theme_manager.findPair (self, 'NO_EDIT')
color_list =[color1, color2, color3]
first_line_colors =[random.choice(color_list) for i in range(len("first line"))]
second_line_colors =[random.choice(color_list) for i in range(len("second"))]
# Fill the lines with custom colors
obj.entry_widget.highlighting_arr_color_data =[first_line_colors, second_line_colors]
MyApp = App ()
MyApp.run ()

 

 
 
Events and handlers
 
Class
StandardApp
npyscreen supports the event queue.
 
As a treatment for pressing, the method
is used. add_handlers
.
 
Example [/b]
#! /usr /bin /env python3
import npyscreen
import curses
class App (npyscreen.StandardApp):
def onStart (self):
self.addForm ("MAIN", MainForm, name = "Hello Habr!")
class InputBox1 (npyscreen.BoxTitle):
_contained_widget = npyscreen.MultiLineEdit
def when_value_edited (self):
self.parent.parentApp.queue_event (npyscreen.Event ("event_value_edited"))
class InputBox2 (npyscreen.BoxTitle):
_contained_widget = npyscreen.MultiLineEdit
class MainForm (npyscreen.FormBaseNew):
def create (self):
self.add_event_hander ("event_value_edited", self.event_value_edited)
new_handlers = {
# Set ctrl + Q for the output of
"^ Q": self.exit_func,
# Set alt + enter to clear inputbox
curses.ascii.alt (curses.ascii.NL): self.inputbox_clear
}
self.add_handlers (new_handlers)
y, x = self.useable_space ()
self.InputBox1 = self.add (InputBox? name = "Editable", max_height = y //2)
self.InputBox2 = self.add (InputBox? footer = "No editable", editable = False)
def event_value_edited (self, event):
self.InputBox2.value = self.InputBox1.value
self.InputBox2.display ()
def inputbox_clear (self, _input):
self.InputBox1.value = self.InputBox2.value = ""
self.InputBox1.display ()
self.InputBox2.display ()
def exit_func (self, _input):
exit (0)
MyApp = App ()
MyApp.run ()

 

 
 
References:
 
Official documentation
 
The original source code is
 
The repository I updated (the main githab seems to have died)
 
The telegram client is on npyscreen (which is on the first screenshot)
+ +1 -

Add comment