Skip to content

Ming-doan/ter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ter CLI Framework

Author Version License

Ter is the CLI Framework that will build a CLI application with cool syntax which will amaze your school coding projects.

In Ter, we are strongly amaze the syntax and terminologies of other modern UI framework. Our main purpose of creating this framework is to make the terminal app more interactive and fancy with pages, command prompt, and built-in UI.

Main concept of Ter

Everything that you can see on the terminal screen is the result of print statement in Python. Then the screen is paused to wait for the user command by input statement. We consider everytime that printing out and waiting for input for future change is a state (inspired by React).

Each state includes:

clear screen -> render component -> pause program -> run logic

The state will continuously loop until the exit method is called.

  • Clear screen phase: Create your terminal and ready to print new content.
  • Render component phase: Render your content with new data. (State is changed)
  • Pause programm phase: Pause program to listen input from user.
  • Run logic phase: Execute logic based on user input to change the data.

Quick start

  • Install terapp in Python package.
$ pip install terapp
  • Create a simple Ter app
# Import libs
import terapp

# Create app instance
app = terapp.Ter()

# Define Screen
class MyScreen(ter.Component):
    def __init__(self):
        self.count = 0

    # Override render method
    def render(self, context):
        print("Counting app")
        print(self.count) # Print count value

    # Override prompt method
    def prompt(self):
        return "Enter your number: "

    # Override logic method
    def logic(self, command, context):
        # Add user number to count
        self.count += int(command)

# Add Screen to route. Ter will get the first route as init screen
app.register_routes({
    'home': MyScreen
})

# Begin loop of your app
app.run()

Folder Structure

Ter is strongly recommending uses organize app's files. By using this structure, your app is more scalable and easy to maintain in the future.

your_folder
    └ screens
    |    └ your_screen.py
    └ state
    |    └ your_state.py
    └ main.py
  • screens folder contains all your screen of your app.
  • state folder contains all global state of your app. (Inspired by Redux)
  • main.py contains the app instance and some config for your app.

Ter App

Ter manages every things in the app instance. Include all the screen in your app.

from terapp import Ter
app = Ter()

Ter provides the Config class which includes all the custom config of app. Ter config includes:

  • default_pause_message (str): If you don't override the prompt method, this string will be displayed instead.
from terapp import Ter, Config
app = Ter(
    config=Config(default_pause_message="Press enter to continue...")
)
# Or you can provide config by config method
app.config(
    config=Config(default_pause_message="Press enter to continue...")
)

Component

In ter, we define every screen is a component which always have methods:

  • render (required): This method will run first and do all code inside it before program will be pause.
  • prompt (optional): This method must return a string for a user prompt message. If not, the prompt message will use default_pause_message instead.
  • logic (optional): This method will run after the user complete typing the prompt to run your desired logic before the new loop.
from terapp import Component

class YourScreen(Component):
    def __init__(self):
        # Define your local variable here
        self.local_variable = ...

    # Render method
    def render(self, context):
        # Print something
        ...

    # Prompt method, optional
    def prompt(self):
        return "Some message"

    # Logic method, optional
    def logic(self, command, context):
        # Do somthing with use input at command params
        ...

To add your screen into app, register routes in main.py file

# Import YourScreen class from screens folder
from screens import YourScreen

# The register_routes method requires a dictionary of Components
app.register_routes({
    'identify_of_route': YourScreen
})

Navigation

Consider we have 2 screens as below in main.py file.

# Import Screens class from screens folder
from screens import Screen1, Screen2

# The register_routes method requires a dictionary of Components
app.register_routes({
    's1': Screen1
    's2': Screen2
})

We want to navigate from Screen1 to Screen2 at logic method of Screen1

class Screen1:
    ...

    def logic(self, command, context):
        # Navigate to Screen 2 if user type `2`
        if command == '2':
            # Use navigate method of Context and passing the key of Screen
            context.navigate('s2')

Global State

The term of state management is strongly inspired by Redux library in React framework. It stores the value of and be accessing in diffirent Screens. Unlike the local varable that we define at the __init__ method of a Screen which only accessed inside the class, this state can be store, update anywhere in your app.

Create your state at state/your_state.py file.

from terapp import State

# Initialize store instance
store = State(init_state=0)

# Create a name for an event and this action
store.reducers(
    reducer='increase_count',
    action=lambda state, payload: state += payload
)

Import the store instance into the Screen

from state.your_state import store

class Screen:
    ...

    def logic(self, command, context):
        # Increase the count value
        # Use dispatch method, access by the event name and passing new data
        store.dispatch(
            reducer='increase_count',
            payload=int(command)
        )

The init_state can be a dictionary or anything

store = State(init_state={
    'name': "Ming Doan",
    'age': 20
})

store.reducers(
    reducer='change_name',
    action=lambda state, payload: {
        'name': payload # Update name
    }
)

High level UI

Ter is providing some quick UI in terminal app.

  • Header
from terapp import Header

class Screen:
    ...

    def render(self, contex):
        print(Header(context, "This is header"))

Future development

Ter was only the alpha version, the future update will arrive soon. (Depend on Author 😁🙌)

Author & Maintainer Ming Doan

About

A simple CLI framework for Python App

Resources

License

Stars

0 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages