Sunday, August 19th, 2001 Friday, September 28th 2001 Comet Way Jerminal v0.2a Copyright 2001©, Comet Way Inc. jonlin@tesuji.org |
The Comet Way Jerminal is a Java terminal which provides basic shell functionality as well as the ability to create classes and invoke methods. A Jerminal session provides an environment that allows you to set environment variables to arbitrary objects that already exist or are created. Any given Jerminal session can be given a set of Input and Output Streams for recieving commands and reporting the results of those commands. The basic Jerminal session assumes two actions: prompting for a command and evaluating a given command. The prompt process updates the current runtime session and provides a prompt for a command. The evaluation process involves parsing and interpreting a String given through the Jerminal session input. In order to use the Jerminal effectively, one must understand the process of the interpretation.
For example:
prompt> command "this is all one token" token2 token3The reserved characters are double quotes ("), percent (%), dollar sign ($), and backslash (\). The quotes are used to group tokens together. The percent is used by putting it in front of a token. That token will be evaluated as a command. The dollar sign is used in front of a token and denotes that that token should be dereferenced as an environment variable. The blackslash is used to escape characters.prompt> command \"token1 token2 token3
prompt> command %"command2 token1 token2" token2 $token3 %$token4When this command is interpreted by the interpreter, the command2 will be evaluated first. The result of that command is passed to the first command as its first argument. The token3 token will be dereferenced as an environment variable; for example, if I have the variable VAR_NAME set to VAR_VALUE, then the interpreter will see $VAR_NAME and replace it with VAR_VALUE. The token4 token is being dereferenced and evaluated. In other words, if I have an environment variable set to 'command token1 token2', by using both the % and the $, I can dereference that variable and evaluate the command. The % and $ characters will still be applied even if they are in a double quoted expression. In order for them to be ignored, they need to be escaped. The ! is a special character when used as the first character of a command string. This tells the interpreter to search for the last command in its history.
Certain variables affect how the shell works. The prompt variable determines what the prompt will look like. There are a few special characters that the prompt will recognize: @T is the current time on 24 hour clock, @t is the current time on a 12 hour clock, @d is the current directory with ~ as your home directory, @D is the absolute path of the current directory, @c is a counter for how many commands where issued to the shell. The home_directory variable denotes what your home directory will be. The ignore_string variable denotes what string will be used to denote a comment. The interpreter will ignore anything that starts with this string. The path_separator_char variable tells the interpreter what the character that separates path names are. The pwd variable points to the java.io.File Object which represents the current working directory. Note that changing the pwd variable to something that isn't a java.io.File object will cause the jerminal to throw exceptions. The history_size variable tells the Jerminal Session how large to make the command history. The jerminal environment variable is a reference to the Jerminal session itself. This provides the user access to the Jerminal Object.
For example:
setenv prompt "[@t][@d] > "Will give you a prompt that will look something like this:
[12:35am][~/work/classes] >
The UnixFileCommands can be disabled if the Jerminal Session is instantiated with the file access flag set to false. Attempts to evaluate a UnixFileCommand command with the file access set to false will result in a UnauthorizedAccessException being thrown. When command classes can't be found for a given command, the Jerminal Session attempts to execute that command natively. It creates a runtime and a process to execute it. The Jerminal Session will try to link the Input and Output streams to the process. If the binary access flag is set to false upon the instantiation of a JerminalSession, the session will not attempt to execute commands if a class for the command is not found. (NOTE: Although the Java APIs allow you to create a Runtime and execute a process, the ability to do this across multiple platforms and Java VMs is very unpredictable. You will recieve an Exception in the native code if you attempt to executing something under Windows 95/98. On Linux and SunOS, commands that don't require input from stdin will usually work.)
aliasClass |
This command adds a classname alias to the current jerminal session
Synopsis:
|
unaliasClass |
This command removes a classname alias
Synopsis:
|
clearHistory |
This command clears the command history in the current jerminal session. The history
will start anew after the interpreter has evaluated the clearHistory command. Synopsis: clearHistory
|
history |
This command displays what is in the current history. Synopsis: history
|
rehash |
This command clears the list of cached commands. Since jerminal commands are Objects and need
to be instantiated in order to use them, the jerminal keeps a cache of the command Objects.
The rehash command will clear that cache and the command Objects are recached when they
are issued to the jerminal.
Synopsis:
|
setenv |
This command displays and sets the environment variables of a jerminal session.
Synopsis:
|
source |
This command reads a file from the local file system and evaluates it line by line. The evaluated
command is printed out by the source command before it is evaluated.
Synopsis: source [source file]
|
unsetenv |
This command removes an environment variable. The only parameter that this command accepts is
the variable name which to remove.
Synopsis: unsetenv [variable name]
|
exit |
This command causes the jerminal to stop accepting commands and send the notifyJerminalExiting()
notification to its listeners. System.exit() is not called, the Thread
that reads commands from jerminal's InputStream is stopped.
Synopsis: exit
|
cat |
This command displays the contents of a file or files.
Synopsis:
|
cd |
This command allows you to change your current working directory.
Synopsis:
|
ls |
This command lists files and directories. There are two flags which you can use: the l and the
a flags (flags are preceded by a '-' character). The l flag will cause this command to
give to a long (detailed) listing of the files and directories. The a flag will display
hidden files as well (files starting with the '.' character).
Synopsis:
|
mkdir |
This command will create a directory on the local file system. Synopsis: mkdir [directory name]
|
mkdirs |
This command will create a directory tree on the local file system. Synopsis: mkdirs [directory name]
|
rm |
This command removes files and directories from the local file system. There are two flags which
the rm command will accept: the r flag and the i flag. The r flag tells the
rm command to recurse through directories and subdirectories when removing (this could be
dangerous!). The i flag will make the rm command ask for a confirmation before deleting
anything.
Synopsis:
|
getClass |
This command takes a java.lang.Object as its only parameter. This command returns a java.lang.Class
object which represents the Class of the argument. Synopsis: getClass [Object]
|
getField |
This command takes a java.lang.Object and a field name (java.lang.String). This command returns the
field of the Object that was given as an argument.
Synopsis:
|
instantiate |
This command instantiates a class and returns the new instance of that class.
Synopsis:
|
invoke |
This command invokes a method on an existing Object.
Synopsis:
|
main |
This command invokes the public static void main(String[]) method for the given class.
Synopsis:
|
javac |
This command compiles a file on the local file system. This command works exactly like the javac command in the java distribution. |
javap |
This command takes classnames as its arguments and lists the class information, including its subclasses, interfaces, constructors, fields, and methods. |
loadClass |
This command is similar to the instantiate command. But instead of using the default
ClassLoader to load the Class, the loadClass command uses its own ClassLoader and reloads the
class data.
Synopsis:
|
setField |
This command sets a field of a java.lang.Object.
Synopsis:
|
echo |
This command will echo whatever arguments you pass it.
|
eval |
This command will evaluate whatever arguments you pass it.
|
nop |
This command will do nothing. The interpreter will, however, process any $ or % tokens it finds.
|
Simple Example |
Welcome to Jerminal v0.1 Jerminal(0)> setenv history_size=50 home_directory=/usr/tmp ignore_string=# jerminal=com.cometway.jerminal.JerminalSession@80cc60d path_separator_char=/ prompt=Jerminal(@c)> pwd=/usr/tmp Jerminal(1)> ls -l Jerminal(2)> mkdir test_directory Jerminal(3)> ls -l drw 1024 Sun Aug 19 03:13:18 EDT 2001 test_directory Jerminal(4)> setenv TEST_VARIABLE "This is a test variable" Jerminal(5)> setenv prompt "[@t][@d] > " Jerminal(@c)> [3:14am][~] > [3:14am][~] > [3:14am][~] > cd test_directory [3:14am][/var/tmp/test_directory] > cd [3:14am][~] > !ls ! -> ls -l drw 1024 Sun Aug 19 03:13:18 EDT 2001 test_directory [3:14am][~] > |
The 3rd command issued (ls -l) listed the currect working directory, which from the 0th command (setenv), is /usr/tmp. The 5th command changes the prompt, and the last command uses the ! character to evaluate a command in the history. In this case, it is the last command in the history that begins with 'ls'. |
Examples using the $ and % directives |
Welcome to Jerminal v0.1 Jerminal(0)> setenv COMMAND1 "echo \"This is what I want to ECHO\" " Jerminal(1)> setenv COMMAND1=echo "This is what I want to ECHO" history_size=50 home_directory=/usr/tmp ignore_string=# jerminal=com.cometway.jerminal.JerminalSession@80cc60d path_separator_char=/ prompt=Jerminal(@c)> pwd=/usr/tmp Jerminal(2)> Jerminal(3)> Jerminal(4)> echo $COMMAND1 echo "This is what I want to ECHO" Jerminal(5)> Jerminal(6)> setenv ECHO $%COMMAND1 Jerminal(7)> setenv COMMAND1=echo "This is what I want to ECHO" ECHO=This is what I want to ECHO history_size=50 home_directory=/usr/tmp ignore_string=# jerminal=com.cometway.jerminal.JerminalSession@80cc60d path_separator_char=/ prompt=Jerminal(@c)> pwd=/usr/tmp Jerminal(8)> Jerminal(9)> echo $ECHO This is what I want to ECHO Jerminal(10)> setenv ECHO %"echo \"I can also echo like this\" " This is what I want to ECHO Jerminal(11)> echo $ECHO I can also echo like this Jerminal(12)> |
The 0th command sets the String 'echo "This is what I want to ECHO"' to the variable COMMAND1. The 6th command sets the variable ECHO to the evaluated contents of the COMMAND1 variable (using the combination of % and $ directives). Since the value of COMMAND1 is 'echo "This is what I want to ECHO"', when this is evaluated, the String 'This is what I want to ECHO' is returned. Thus, the value of ECHO is the String 'This is what I want to ECHO'. Command 10 shows you an alternate way of doing the same thing. |
Example with java Objects |
Welcome to Jerminal v0.1 Jerminal(0)> setenv BUFFER %"instantiate java.lang.StringBuffer" Jerminal: instantiate: Created new instance of java.lang.StringBuffer Jerminal(1)> echo $BUFFER Jerminal(2)> invoke $BUFFER append java.lang.String "THis is the first line\n" THis is the first line Jerminal(3)> invoke $BUFFER append java.lang.String "This is the second line\n" THis is the first line This is the second line Jerminal(4)> Jerminal(5)> echo $BUFFER THis is the first line This is the second line Jerminal(6)> echo %"invoke \$BUFFER length" 47 Jerminal(7)> setenv BUFFER %"instantiate java.lang.StringBuffer java.lang.String \"This is a new StringBuffer\"" Jerminal: instantiate: Created new instance of java.lang.StringBuffer THis is the first line This is the second line Jerminal(8)> echo $BUFFER This is a new StringBuffer Jerminal(9)> |
The first command sets the variable BUFFER to a newly instantiated java.lang.StringBuffer object. The instantiated StringBuffer has no arguments thus the StringBuffer is empty. The 2nd and 3rd commands invokes the java.lang.StringBuffer.append(java.lang.String) method on the StringBuffer stored in the variable BUFFER. The 6th command invokes the length() method and echos the length of the StringBuffer. The 7th command instantiates a new StringBuffer with constructor arguments and stored the value under the BUFFER variable. The setenv command returned the old value of the BUFFER variable which was 'THis is the first line\nThis is the second line\n'. |
Example using a script and loading and manipulating classes |
This script creates an instance of the Comet Way Java Agent Kernel and starts up several Agents.
The first thing this script does is it defines what the comment string will be. In this case '//',
which is what the Java comment String is. Then several class name aliases are set. This allows the
script to say 'String' when it really means 'java.lang.String'. Then the JAK is instantiated and
stored in the variable JAK. The AgentKernel is instantiated and stored in the variable
AGENT_KERNEL. It's initialized and started. With the AgentKernel running, other Agents can
be easily created and loaded. Since order is important, the com.cometway.jak.ServiceManager is
created first, then the com.cometway.httpd.HTTPFileServerAgent, and finally the
com.cometway.httpd.WebServer. The WebServer properties needed to be set before it was created.
setenv ignore_string "//" // This jerminal script creates a JAK, starts a ServiceManager, then starts a // HTTPFileServer and a WebServer // // Classname aliases for convenience aliasClass String java.lang.String aliasClass Props kinetoscope.util.Props aliasClass Object java.lang.Object aliasClass JAK com.cometway.jak.JAK aliasClass Agent com.cometway.jak.AgentInterface // Lets start by instantiating a JAK // setenv JAK %"instantiate JAK" // And we will need an AgentKernel as well // javap com.cometway.jak.AgentKernel // You see that we need a Props object to pass into its constructor setenv TMP_PROPS %"instantiate Props" setenv AGENT_KERNEL %"instantiate com.cometway.jak.AgentKernel Props \$TMP_PROPS" // give the Agent Kernel to our instance of the JAK setField $JAK instance $AGENT_KERNEL // initialize the AgentKernel invoke $AGENT_KERNEL initProps // Create the default reporter setField $JAK reporter %"instantiate com.cometway.jak.Reporter" // Start the Agent Kernel invoke $AGENT_KERNEL startAgent Agent $AGENT_KERNEL // Now we can start loading in some agents, we will start with the ServiceManager setenv TMP %"instantiate Props" invoke $TMP setProperty String Object classname com.cometway.jak.ServiceManager setenv SERVICE_MANAGER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" invoke $AGENT_KERNEL startAgent Agent $SERVICE_MANAGER // With the service manager loaded, we can try to load some services now setenv TMP %"instantiate Props" invoke $TMP setProperty String Object classname com.cometway.httpd.HTTPFileServerAgent setenv inet %"invoke java.net.InetAddress getLocalHost" setenv inet %"invoke \$inet getHostName" setenv tmp %"instantiate java.lang.StringBuffer String http://" invoke $tmp append String $inet invoke $tmp append String :9876/ invoke $TMP setProperty String Object service_url %"invoke \$tmp toString" unsetenv inet unsetenv tmp setenv FILE_SERVER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" invoke $AGENT_KERNEL startAgent Agent $FILE_SERVER // And now we start the web server setenv TMP %"instantiate Props" invoke $TMP setProperty String Object classname com.cometway.httpd.WebServer invoke $TMP setProperty String Object bind_port 9876 setenv inet %"invoke java.net.InetAddress getLocalHost" setenv inet %"invoke \$inet getHostName" setenv tmp %"instantiate java.lang.StringBuffer String http://" invoke $tmp append String $inet invoke $tmp append String :9876/ invoke $TMP setProperty String Object service_url %"invoke \$tmp toString" unsetenv inet unsetenv tmp setenv WEB_SERVER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" invoke $AGENT_KERNEL startAgent Agent $WEB_SERVER |
This is what it looks like when you source it.
Welcome to Jerminal v0.1 Jerminal(0)> # First, I want to set the prompt to something a little more legible Jerminal(1)> setenv prompt "###### > " Jerminal(@c)> ###### > ###### > setenv home_directory /usr/home/jonlin/java /usr/tmp###### > ###### > cd ###### > source ./com/cometway/jerminal/example1.jerm Jerminal: source: setenv ignore_string "//" Jerminal: source: // This jerminal script creates a JAK, starts a ServiceManager, then starts a Jerminal: source: // HTTPFileServer and a WebServer Jerminal: source: // Jerminal: source: // Classname aliases for convenience Jerminal: source: aliasClass String java.lang.String Jerminal: source: aliasClass Props kinetoscope.util.Props Jerminal: source: aliasClass Object java.lang.Object Jerminal: source: aliasClass JAK com.cometway.jak.JAK Jerminal: source: aliasClass Agent com.cometway.jak.AgentInterface Jerminal: source: // Lets start by instantiating a JAK Jerminal: source: // Jerminal: source: setenv JAK %"instantiate JAK" Jerminal: instantiate: Created new instance of com.cometway.jak.JAK Jerminal: source: // And we will need an AgentKernel as well Jerminal: source: // Jerminal: source: javap com.cometway.jak.AgentKernel Jerminal: source: // You see that we need a Props object to pass into its constructor Jerminal: source: setenv TMP_PROPS %"instantiate Props" Jerminal: instantiate: Created new instance of kinetoscope.util.Props Jerminal: source: setenv AGENT_KERNEL %"instantiate com.cometway.jak.AgentKernel Props \$TMP_PROPS" Jerminal: instantiate: Created new instance of com.cometway.jak.AgentKernel Jerminal: source: // give the Agent Kernel to our instance of the JAK Jerminal: source: setField $JAK instance $AGENT_KERNEL Jerminal: source: // initialize the AgentKernel Jerminal: source: invoke $AGENT_KERNEL initProps Jerminal: source: // Create the default reporter Jerminal: source: setField $JAK reporter %"instantiate com.cometway.jak.Reporter" Jerminal: instantiate: Created new instance of com.cometway.jak.Reporter Jerminal: source: // Start the Agent Kernel Jerminal: source: invoke $AGENT_KERNEL startAgent Agent $AGENT_KERNEL [001_StartupAgent] Starting on 19-Aug-01 3:56:25 AM [001_StartupAgent] Loading agents from ./ Jerminal: source: // Now we can start loading in some agents, we will start with the ServiceManager Jerminal: source: setenv TMP %"instantiate Props" Jerminal: instantiate: Created new instance of kinetoscope.util.Props Jerminal: source: invoke $TMP setProperty String Object classname com.cometway.jak.ServiceManager Jerminal: source: setenv SERVICE_MANAGER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" Jerminal: source: invoke $AGENT_KERNEL startAgent Agent $SERVICE_MANAGER [1003_ServiceManager] Starting on 19-Aug-01 3:56:25 AM Jerminal: source: // With the service manager loaded, we can try to load some services now Jerminal: source: setenv TMP %"instantiate Props" Jerminal: instantiate: Created new instance of kinetoscope.util.Props Jerminal: source: invoke $TMP setProperty String Object classname com.cometway.httpd.HTTPFileServerAgent Jerminal: source: setenv inet %"invoke java.net.InetAddress getLocalHost" Jerminal: source: setenv inet %"invoke \$inet getHostName" Jerminal: source: setenv tmp %"instantiate java.lang.StringBuffer String http://" Jerminal: instantiate: Created new instance of java.lang.StringBuffer Jerminal: source: invoke $tmp append String $inet Jerminal: source: invoke $tmp append String :9876/ Jerminal: source: invoke $TMP setProperty String Object service_url %"invoke \$tmp toString" Jerminal: source: unsetenv inet Jerminal: source: unsetenv tmp Jerminal: source: setenv FILE_SERVER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" Jerminal: source: invoke $AGENT_KERNEL startAgent Agent $FILE_SERVER [1004_HTTPFileServerAgent] Starting on 19-Aug-01 3:56:25 AM [1003_ServiceManager] Registered com.cometway.httpd.HTTPFileServerAgent as HTTPFileServerAgent Jerminal: source: // And now we start the web server Jerminal: source: setenv TMP %"instantiate Props" Jerminal: instantiate: Created new instance of kinetoscope.util.Props Jerminal: source: invoke $TMP setProperty String Object classname com.cometway.httpd.WebServer Jerminal: source: invoke $TMP setProperty String Object bind_port 9876 Jerminal: source: setenv inet %"invoke java.net.InetAddress getLocalHost" Jerminal: source: setenv inet %"invoke \$inet getHostName" Jerminal: source: setenv tmp %"instantiate java.lang.StringBuffer String http://" Jerminal: instantiate: Created new instance of java.lang.StringBuffer Jerminal: source: invoke $tmp append String $inet Jerminal: source: invoke $tmp append String :9876/ Jerminal: source: invoke $TMP setProperty String Object service_url %"invoke \$tmp toString" Jerminal: source: unsetenv inet Jerminal: source: unsetenv tmp Jerminal: source: setenv WEB_SERVER %"invoke \$AGENT_KERNEL createAgent Object \$TMP" Jerminal: source: invoke $AGENT_KERNEL startAgent Agent $WEB_SERVER [1005_WebServer] Starting on 19-Aug-01 3:56:25 AM [1005_WebServer] Comet Way Web Server 1.1 Final 2-14-2001 [1005_WebServer] Starting WebServer and listening on port 9876... [1005_WebServer] Server bound successfully. (1003_ServiceManager) Requested: HTTPFileServerAgent 19-Aug-01 3:56:25 AM (1003_ServiceManager) Not found: logger_agent 19-Aug-01 3:56:25 AM ###### > [1005_WebServer] Processing request for: comet/216.29.185.162 GET / [1005_WebServer] Processing request for: comet/216.29.185.162 GET /projects [1005_WebServer] Processing request for: comet/216.29.185.162 GET /projects/ [1005_WebServer] Processing request for: comet/216.29.185.162 GET /projects/httpd [1005_WebServer] Processing request for: comet/216.29.185.162 GET /projects/httpd/ |
The JerminalAgent takes these properties:
listen_port tells the JerminalAgent what port to open the socket on.
password is the password authentication in order to access the session.
allow_file_access is a flag that sets whether local file access is allowed in the JerminalSession.
allow_binary_access is a flag that sets whether local binary access is allowed in the JerminalSession.
default_environment allows you to load in a set of environment variables the first time the JerminalSession is created.
The default listen_port is 7870 and the default password is qazmko'68qwerty,
and a quick way to start a jerminal agent is to create a file that looks like this:
classname=com.cometway.jerminal.JerminalAgent listen_port=7870 password=my_new_password
> java com.cometway.jak.JAK [path of the file I just created]
Screenshots of starting the JerminalAgent and connecting to it:
The JerminalAgent.
Welcome to Jerminal v0.2 Jerminal(0)> Jerminal(1)> main com.cometway.jak.JAK /tmp/1000_JerminalAgent.startup Executing JAK's static main method Jerminal(2)> [JAK] Comet Way JAK 1.3 Preview 7-10-2001 [001_StartupAgent] Starting on 28-Sep-01 11:03:30 AM [001_StartupAgent] Loading agents from ./ [1003_JerminalAgent] Starting on 28-Sep-01 11:03:30 AM
[11:02am][comet-ttyp7][/tmp]> \telnet localhost 7870 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. access code: qazmko'68qwerty Welcome to Jerminal v0.2 Jerminal(0)> Jerminal(1)> Jerminal(2)> Jerminal(3)> ls test_directory Jerminal(4)> setenv TERM=vt100 history_size=50 home_directory=/usr/tmp ignore_string=# jerminal=com.cometway.jerminal.JerminalSession@80ae1dd path_separator_char=/ prompt=Jerminal(@c)> pwd=/usr/tmp Jerminal(5)> ^] telnet> close Connection closed. [11:04am][comet-ttyp7][/tmp]> [11:04am][comet-ttyp7][/tmp]> [11:04am][comet-ttyp7][/tmp]> \telnet localhost 7870 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. access code: qazmko'68qwerty Welcome to Jerminal v0.2 Jerminal(6)> Jerminal(7)>
As you can see, these methods provide the basic functionality of a text window and the JerminalWindow is not limited to being used with only the JerminalSession/ JerminalKeyListener/ DumbTerminal classes. Any application can use a JerminalWindow to display windowed text in a neat and organized fashion. These methods are the same methods that the JerminalKeyListener and the DumbTerminal uses to display its input.
/** * This sets the INSERT flag of the key listener. If set to true, it is expected * that keystrokes read from the JerminalWindow are INSERTed at the cursor. */ public void setInsert(boolean insert); /** * This method returns the state of the INSERT flag. */ public boolean getInsert(); /** * This sets the INTERPRET flag of the key listener. If set to false, the key * listener is expected not to interpret the input. */ public void setInterpret(boolean interpret); /** * This method returns the state of the INTERPRET flag. */ public boolean getInterpret(); /** * This sets the copy/paste buffer of the key listener. */ public void setKillBuffer(String buffer); /** * This method returns the copy/paste buffer. */ public String getKillBuffer(); /** * This method sets the input buffer of the key listener. This is the buffer that * will be sent as a command to the jerminal. */ public void setInputBuffer(String buffer); /** * This method returns what is currently in the input buffer. */ public String getInputBuffer(); /** * This method sets the cursor index of the input buffer. */ public void setBufferIndex(int index); /** * This method returns the cursor index of the input buffer. */ public int getBufferIndex(); /** * This method sets the JerminalWindow which this key listener should be reading * keyboard input from. */ public void setJerminalWindow(JerminalWindow window); /** * This method returns the JerminalWindow which this key listener is reading from. */ public JerminalWindow getJerminalWindow();
The EmacsKeyListener currently interprets the follow keystrokes when the interpret flag is set to true (The interpret flag is set to false in the case that the JerminalSession is executing a binary, where the keyboard input may not want to be interpreted). NOTE: a word is defined to be characters separated by a whitespace or a path separator character.
CTRL+A | Move the cursor to the beginning of the line |
CTRL+B | Move the cursor back one character |
ALT+B | Move the cursor back one word |
CTRL+C | Keyboard break, this flushes whatever was in the current line |
CTRL+D | Delete the character at the cursor |
ALT+D | Delete the word in front of the cursor |
CTRL+E | Move the cursor to the end of the line |
CTRL+F | Move the cursor forward one character |
ALT+F | Move the cursor forward one word |
CTRL+K | Delete all the characters from the cursor to the end of the line and store them in the Kill buffer |
CTRL+L | Refresh the screen (redraw the JerminalWindow) |
CTRL+N | Display the next command in the command history |
CTRL+P | Display the previous command in the command history |
CTRL+Y | Yank the characters in the Kill buffer and insert them at the cursor |
UP arrow | Display the previous command in the command history |
DOWN arrow | Display the next command in the command history |
LEFT arrow | Moves the cursor back one character |
CTRL+LEFT arrow | Moves the cursor back one word |
ALT+LEFT arrow | Delete the word behind the cursor |
RIGHT arrow | Moves the cursor forward one character |
CTRL+RIGHT arrow | Moves the cursor forward one word |
ALT+RIGHT arrow | Delete the word in front of the cursor |
INSERT | Toggles the insert flag. If the insert flag is turned off, characters typed will overwrite the contents at the cursor instead of inserting them |
END | Move the cursor to the end of the line |
ENTER (Return) | This key takes whatever is in the current line and flushes it to the JerminalSession as well as inserting a newline at the end of the line so that it is displayed in the JerminalWindow |
HOME | Move the cursor to the beginning of the line |
DELETE | Deletes the character behind the cursor |
BACKSPACE | Deletes the character behind the cursor |
ALT+DELETE | Deletes the word behind the cursor |
ALT_BACKSPACE | Deletes the word behind the cursor |
TAB | This key will cause the EmacsKeyListener to attempt to complete the current characters (the word) that the cursor is on. It will complete filenames, pathnames, and command names (if the cursor is on the first word of the line) |
ESCAPE | Insert a '\' at the cursor (The escape character) |
SHIFT+PAGE DOWN | Scroll down in the window |
SHIFT+PAGE UP | Scroll up in the window |
Everything else | All other keystrokes read will be interpreted as a character to be inserted at the cursor |
Here is an example of starting the DumbTerminal class from a command line:
[3:57am][comet-ttyp7][/tmp]> j com.cometway.jerminal.DumbTerminal font=Monospaced font_size=10 use_std_out tab_width=20 scroll_back_size=1000 jerminal_props=.jerminal commands_directory=./classes/com/cometway/jerminal/commands/This example will start a DumbTerminal, which opens a window with a JerminalSession inside. The properties that the JerminalWindow recieves are: font (set to Monospace), font_size (set to 10), use_std_out (set to nothing), tab_width (set to 20), scroll_back_lines (set to 1000), jerminal_props (set to the file .jerminal), and commands_directory (set to the directory ./classes/com/cometway/jerminal/commands/). Here is a list of all the valid properties (at the writing of this document) and what part of the Jerminal uses it. All these properties are accepted by the DumbTerminal as name=value pairs on the command line.
Properties used by the JerminalWindow | |
font | This property is the Font that the JerminalWindow will use. The default font is DialogInput. |
font_size | This is the size of the font that is used. The default font size is 9. |
bg | The background color represented by 3 sets of 3 digit integers (no spaces) corresponding to the RED, GREEN, and BLUE values of the color. The default color is 000000000. |
fg | The foreground color represended by 3 sets of 3 digit integers (no spaces) corresponding to the RED, GREEN, and BLUE values of the color. The default foreground color is 255000000. |
x_offset | This is the offset in the positive X direction that everything will be drawn from. Increasing this number will move the contents of the window to the right. This property is used to adjust for difference in the drawing origin (0,0) when using java AWT under different platforms and different java VMs. The default x_offset is 6 |
y_offset | This is the offset in the positive Y direction that everything will be drawn from. Increasing this number will move the contents of the window to the down. This property is used to adjust for difference in the drawing origin (0,0) when using java AWT under different platforms and different java VMs. The default y_offset is 23 |
xCharOffset | This is the offset of pixels on the left and right of the text drawn in the window. Increasing this will increase the space left of the text and right of the text. The default value of this property is 3. |
yCharOffset | This is the offset of pixels on the top and bottom of the text drawn in the window. Increasing this will increase the space above of the text and below of the text. The default value of this property is 4. |
xFrame | This is dynamically calculated offset of the pixels to the left of the text in the window. This value is used when calculating the number of columns of characters that will fit in the window. The default value is 10. |
yFrame | This is dynamically calculated offset of the pixels to the above of the text in the window. This value is used when calculating the number of rows of characters that will fit in the window. The default value is 30. |
initial_width | This is the initial width of the window in terms of how many columns of characters the width of the window will accomodate. The default value of this property is 80. |
initial_height | This is the initial height of the window in terms of how many rows of characters the height of the window will accomodate. The default value of this property is 45. |
scroll_back_lines | This is the number of lines the String array of the JerminalWindow will have. This is the maximum number of lines that will be saved. The default value of this property is 250. |
scroll_lines | This is the number of lines up or down each successive scroll up or scroll down will move. The default value is 25; however, when the window is resized, this value is changed to two thirds the maximum numbers of rows of characters the window will accomodate. |
tab_length | This sets the length of a tab. The tabs themselves are not stored in the window's String array, they are replaced with the appropriate number of spaces. |
fixed_font_width | In the case that the platform or java VM does not support FontMetrics, these properties can be used to specify the width in pixels of the font that you are using. If this property is not provided, the window will attempt to find the width using the FontMetrics. |
fixed_font_height | In the case that the platform or java VM does not support FontMetrics, these properties can be used to specify the height in pixels of the font that you are using. If this property is not provided, the window will attempt to find the height using the FontMetrics. |
Properties used by the DumbTerminal |
|
use_std_out | This property does not need a value. If this property exists, the DumbTerminal will set the System.out OutputStream to the PipedOutputStream that is being read from. Thus, whatever is written to System.out will be displayed in the JerminalWindow. |
use_std_error | This property does not need a value. If this property exists, the DumbTerminal will set the System.err OutputStream to the PipedOutputStream that is being read from. Thus, whatever is written to System.err will be displayed in the JerminalWindow. |
remote_host | If this property exists, the DumbTerminal will open a Socket to this host and connect the Jerminal to the Socket instead of a local JerminalSession. This property is used in conjunction with the remote_port property. |
remote_port | This property is used in conjunction with the remote_host property. It will be the port that the DumbTerminal will open a socket to. |
jerminal_props | The value of this property should be a filename on the local file system which has a list of
name=value pairs separated by newlines. These properties are read in and used to initialize the
JerminalSession that is started. If the
remote_host and remote_port properties are used, this property is ignored.
The list of valid JerminalSession properties
(as of the writing of this document) are: |
use_default_aliases | This property is passed to the properties used to initialize the JerminalSession
that the DumbTerminal creates. The session will
load a set of default classname aliases. They are:classAliases.put("String","java.lang.String"); classAliases.put("Object","java.lang.Object"); classAliases.put("StringBuffer","java.lang.StringBuffer"); classAliases.put("Date","java.util.Date"); classAliases.put("Vector","java.util.Vector"); classAliases.put("Hashtable","java.util.Hashtable"); classAliases.put("Props","kinetoscope.util.Props"); classAliases.put("Pair","kinetoscope.util.Pair"); classAliases.put("StringTools","kinetoscope.util.StringTools"); classAliases.put("DebugTools","kinetoscope.util.DebugTools"); classAliases.put("HTTPLoader","kinetoscope.net.HTTPLoader"); classAliases.put("JAK","com.cometway.jak.JAK"); classAliases.put("JerminalSession","com.cometway.jerminal.JerminalSession"); |
Properties used by the EmacsKeyListener |
|
commands_directory | This is the directory that contains the classes for the JerminalCommand classes. These classes are used by the EmacsKeyListener to do completion on commands, since commands used by the Jerminal are dynamically loaded into memory. If this property is not provided, or invalid (they do not contain the class files), the keyboard interpreter will not be able to complete on commands. |
The JerminalListenerInterface interface is implemented by classes that want to listen to JerminalSession events. When the session is executing a binary, the DumbTerminal must set the JerminalKeyListener's interpret flag to false so that keyboard input is no longer interpreted and should be sent to the session as is. When an invalid command is given to the session, the DumbTerminal will make the JerminalWindow visually beep (flash). When the JerminalSession is exiting (it recieved an exit command), the DumbTerminal must stop reading the output of the session and dispose of the window. Here is an example of a simple class that implements the JerminalListenerInterface. The output of the JerminalSession that is created is sent to System.out and the input is read from System.in.
import java.io.*; import kinetoscope.util.Props; import com.cometway.jerminal.*; public class Listener implements JerminalListenerInterface, Runnable { boolean stopRunning; Thread runThread; public Listener() { runThread = new Thread(this); runThread.start(); } public void notifyRunningBinary() { System.out.println("Running binary..."); } public void notifyFinishedRunningBinary() { System.out.println("Finished running binary..."); } public void notifyInvalidCommand() { System.out.println("BEEP"); } public void notifyExecutingCommand(String command) { System.out.println("Executing command: "+command); } public void notifyFinishedExecutingCommand(String command) { System.out.println("Finished executing command: "+command); } public void notifyJerminalExiting() { stopRunning = true; System.out.println("EXITING"); } public void run() { try { OutputStream out = null; InputStream jIn = null; jIn = new PipedInputStream(); out = new PipedOutputStream((PipedInputStream)jIn); JerminalSession jerminal = new JerminalSession(jIn,System.out,new Props(),true,true,true); jerminal.addListener(this); jerminal.start(); while(!stopRunning) { out.write((char)System.in.read()); out.flush(); } } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { new Listener(); } }If we wanted to use a JerminalWindow and a JerminalKeyListener for the output and input, we would change the run() method to look like this:
public void run() { try { InputStream in = null; OutputStream jOut = null; OutputStream out = null; InputStream jIn = null; in = new PipedInputStream(); jOut = new PipedOutputStream((PipedInputStream)in); jIn = new PipedInputStream(); out = new PipedOutputStream((PipedInputStream)jIn); // create the window and key listener JerminalWindow window = new JerminalWindow(new Props()); JerminalKeyListener keys = new EmacsKeyListener(window); window.keyListener = keys; window.addKeyListener(keys); // create the session and start it JerminalSession jerminal = new JerminalSession(jIn,jOut,new Props(),true,true,true); window.jerminal = jerminal; window.jerminalIn = in; window.jerminalOut = out; jerminal.addListener(this); jerminal.start(); // read from the key listener (in) while(!stopRunning) { int i = in.read(); char c = (char)i; // make a new line if we read a newline if(i==10 || i==13) { window.makeNewLine(); } // insert a tab if we read a tab else if(i==9) { window.insertTab(); } // anything else, write it to the window and move the cursor else { window.insertAtCursor(c); window.moveCursorX(1); } // redraw the window window.refresh(true); } } catch(Exception e) { e.printStackTrace(); } }
The JerminalKeyListener interface is implemented by KeyListeners to interpret the keyboard input from the JerminalWindow. This allows any prefered editing style to be implemented (vi keys, MS Word keys, etc...) and shell functionality to be mapped to keys. Keys can even be mapped to JerminalSession commands.
The JerminalWindow can be used in many different ways without the rest of the Jerminal classes. It can be used by applications to display various levels of debugging output, where no keyboard input is read and the windows can be arbitrarily closed or opened. It can be used to implement a text editor or a console. Here is an example of using the JerminalWindow where the OutputStreams debug0-9, are various streams used to output various levels of debugging (NOTE: this will not compile):
public class DebugManager { JerminalWindow window; // The magic class provides me the debug OutputStreams used by my application public DebugManager(SomeMagicClass someClass) { Props windowProperties = new Props(); window = new JerminalWindow(windowProperties); new StreamReader(new PipedInputStream(someClass.debug0),"DEBUG[0]"); new StreamReader(new PipedInputStream(someClass.debug1),"DEBUG[1]"); new StreamReader(new PipedInputStream(someClass.debug2),"DEBUG[2]"); new StreamReader(new PipedInputStream(someClass.debug3),"DEBUG[3]"); new StreamReader(new PipedInputStream(someClass.debug4),"DEBUG[4]"); } // This Threaded inner class reads from the debug streams and gives them to the window to be displayed class StreamReader extends Thread { String prefix; InputStream in; public StreamReader(InputStream readStream, String outputPrefix) { super(); prefix = outputPrefix; in = readStream; start(); } public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line = reader.readLine(); while(line!=null) { window.insertAtCursor(line); window.makeNewLine(); window.refresh(true); line = reader.readLine(); } } catch(Exception e) {;} } } }
You can view the javadocs here.