LuaTerminal

20 August 2019 Link



Introduction

LuaTerminal is a standalone Lua 5.2+ module that allows you to create a Lua terminal in a IUP text box/scintilla widget or opens a socket terminal allowing remote dumb consoles to remotely execute lua code and receive responses or it can have both running simultaneously with multiple instances of each. IUP is the only external dependency of the module (it needs the iup table to be present in the global space when the module is loaded). If a socket terminal needs to be opened then luasocket is also a dependency and must be present in package.path directly list.
A companion module LuaTerminalRemote is also supplied which helps connecting to the remote terminal by any Lua script.

Features

  • Supports multiple concurrent terminals
  • Independent command history for each terminal
  • Optional Logging facility for each terminal independently
  • Local and Remote (through sockets) terminals

Installation

Jut copy LuaTerminal.lua in the lua package path directory or use LuaRocks as follows:
luarocks install LuaTerminal
For using LuaTerminalRemote copy LuaTerminalRemote.lua to the lua package path directory as well or use LuaRocks as follows:
luarocks install LuaTerminalRemote

Usage

To use the module simply do
  1. require("iuplua")
  2. lt = require("LuaTerminal")

For using the Scintilla based terminal do
  1. require("iuplua")
  2. require("iuplua_scintilla")
  3. lt = require("LuaTerminal")
  4. lt.USESCINTILLA = true

lt is the table containing the LuaTerminal module now.

Local Terminal

A terminal textbox can be obtained by simply doing:
  1. terminal = lt.newTerm(env,true,"logfile.txt")

This creates a terminal which will execute its statements in the environment env, where in the env the print, io.read and io.write will be redirected to use the text box itself as the console and all executed commands and results will be saved in 'logfile.txt'

User Interface

  1. The prompt is displayed as ">" at the beginning of a line where the command entry begins
  2. Ctrl+Up displays the last command
  3. Ctrl+Down displays the next command in the history list
  4. Ctrl+Left displays the first command of the session
  5. Ctrl+Right displays the last command of the session
  6. If an incomplete statement is entered the next line starts with an indentation indicating that the terminal is expecting more input before executing the command.

Remote Terminal

A terminal socket can be opened and the corresponding table object can be obtained by simply doing:
  1. sockTerminal = lt.newSocketTerm(env,true,"logfile.txt")

This creates a socket terminal which will execute all statements received in the tcp socket in the environment env, where in the env the print, io.read and io.write will be redirected to the socket and all executed commands and results will be saved in 'logfile.txt'.

API

Functions

There are just 2 function:
  1. newTerm() - Open a new local terminal in a iupText control
    1. newTerm([environment: table] [,redirectIO: boolean] [,logFileName: string]) -> (iupText: ihandle)
    1. environment is the table used as the environment to execute the terminal statements. If not given an empty table is used a environment.
    2. redirectIO if true then if present in environment print, io.read and io.write will be redirected to use the returned iupText control as the interface. If not given then the redirection not done.
    3. logFileName is the name of the text file where all the executed commands and their results are stored. If not given then no log file created.. If the log file with that name already exists then data is appended to it.
  2. newSocketTerm() - Open a new socket terminal allowing any program to remotely execute code
    1. newSocketTerm([environment: table] [,redirectIO: boolean] [,logFileName: string]) -> (sockTerm: table)
    1. environment is the table used as the environment to execute the terminal statements. If not given an empty table is used a environment.
    2. redirectIO if true then if present in environment print, io.read and io.write will be redirected to use the returned iupText control as the interface. If not given then the redirection not done.
    3. logFileName is the name of the text file where all the executed commands and their results are stored. If not given then no log file created.. If the log file with that name already exists then data is appended to it.

Attributes

LuaTerminal module

LuaTerminal here is the module table returned by require.
  1. LuaTerminal._VERSION - returns the version of the LuaTerminal Module
  2. LuaTerminal.MAXTEXT - the default setting for each created terminal. The number of text characters allowed in the terminal text box will be trimmed to less than this after each command.
  3. LuaTerminal.USESCINTILLA - If set to true before creating the terminal then the terminal will be created using the Scintilla control with the Lua syntax highlighting

Local Terminal table

The local terminal here is the iuptext control returned by the newTerm function
  1. terminal.data - Table containing information about the terminal
    1. history - Array of all commands executed in this session. Index 0 contains the current cursor in the history indicating the last command used in the history
    2. env - Environment of the terminal
    3. logFile - Log File of the terminal if any
    4. maxText - maximum number of characters allowed in the terminal. Initialized with LuaTerminal.MAXTEXT at creation.
    5. prompt - array containing the row and column position of the last prompt displayed.

Remote terminal table

The remote terminal table is the table returned by the newSocketTerm function.
    1. history - Array of all commands executed in this session. Index 0 contains the current cursor in the history indicating the last command used in the history
    2. env - Environment of the terminal
    3. logFile - Log File of the terminal if any
    4. timer - iupTimer object that handles the socket connection by servicing it periodically.

Remote Terminal Connection

Some basic points need to be taken care of when writing the remote side code which can connect to the open socket terminal by LuaTerminal.

Connecting to the terminal

When a new socket terminal is created it periodically multicasts and broadcasts its IP address and port number so that any interested application can connect to it. Once any application connects to it then it will stop broadcasting.
  1. The multicast IP is 239.192.1.1 and port is 11111. The broadcast port is also 11111.
  2. The message sent on this multicast and broadcast is "LUATERMINAL@"..<port number>.."@"..tostring(package.loaded.LuaTerminal). Once this message is received interested application can simply connect to the socket terminal over tcp using the ip from where the multicast/broadcast cap and the port number in the message.
  3. This message should be stored for usage in communication. The message is used in the following scenarios (once the connection to the terminal is made and communication going on):
    1. If in the received message from the terminal ends with the broadcast message then the broadcast message should be swapped with "\n"
    2. If the received message from the terminal is just this broadcast message then that means that the previous data sent to the terminal is incomplete and the lua interpreter over there is waiting for more data to complete the statement and then execute it.
    3. If a message sent to the socket terminal starts with the broadcast message then it is handled as a special case. This allows sending the following special commands to the socket terminal:
      1. <Broadcast Message>.."UP"
      2. <Broadcast Message>.."DOWN"
      3. <Broadcast Message>.."LEFT"
      4. <Broadcast Message>.."RIGHT"
      These commands allow access to the command history on the terminal and returns the respective command.

Sample Test Program

The sample program in the test directory testSocket.lua creates a local terminal as well as opens a socket terminal which can then be connected to by the script remoteTerm.lua which demonstrates how to connect to the socket terminal by using the LuaTerminalRemote module.

Repository

The source code can be downloaded from the github repository here

See Also