To create terminal you must pass interpreter function (as first argument) which will be called when you type enter. Function has two argumentss command that user type in terminal and terminal instance. Optionally you can pass string as first argument, in this case interpreter function will be created for you using passed string as URI (path to file) of JSON-RPC service (it's ajax so must be on the same server or use CORS).
$('#some_id').terminal(function(command) { if (command == 'test') { this.echo("you just typed 'test'"); } else { this.echo('unknown command'); } }, { prompt: '>', name: 'test' });
You can pass object as first argument - the methods will be invoked by commands typed by a user. In those methods this will point to terminal object.
$('#some_id').terminal({ echo: function(arg1) { this.echo(arg1); }, rpc: 'some_file.php', calc: { add: function(a, b) { this.echo(a+b); }, sub: function(a, b) { this.echo(a-b); } } }, { prompt: '>', greeting: false });
This code will create two command echo that will print first argument and add that will add two integers.
From version 0.8.0 you can also use array with strings, objects and functions. You can use multiple number of objects and strings and one function (that will be called last if no other commands found). If you have ignoreSystemDescribe function enabled you will be able to use only one string (JSON-RPC url). If you have completion enabled then your commands will be that from objects and JSON-RPC that have system.describe
$('#some_id').terminal(["rpc.php", { "mysql": function() { this.push(function(command, term) { $.jrpc("rpc.php", 'mysql', [command], function(json) { term.echo(json.result); }); }, { prompt: 'mysql> ' } ); } }], { prompt: '>', greeting: false });
In previous example mysql will be exception, even that rpc have that method it will not call it but create new interpreter.
Terminal will always process numbers if processArguments is set to true (by default).
To have automatic json-rpc service the JSON-RPC endpoint should implement system.describe method, bby default it need to be json object with "procs" property that should be array of that should look like this (params array is optional):
{ "procs": [ {"name": "foo", "params": ["a", "b"]}, {"name": "bar", "params": ["a"]} ] }
If your system.describe method can't return that object you can use describe options, you can use `"result.procs"` and return normal JSON-RPC response with object that have procs property with the same array.
This is a list of options (for second argument):
function(user, password, callback) { if (user == 'demo' && password == 'secret') { callback('AUTHENTICATION TOKEN'); } else { callback(null); } }But you need to know that everybody can look at your javascript source code so it's better to call server using AJAX here and call callback on response. If callback receives truthy value, you can get that value using token method so you can pass when calling the server (and server then can identify that token).
this
context.is_bottom
method.set_mask(true)
.#[[0,1,"command"],[0,2,"command2"]]
first number is index of terminal on a page second is index of command for terminal. (0 is initial state of the terminal so first command have index of 1). Set to false by default. You can record commands you type by calling history_state method.is_bottom
method.system.describe JSON-RPC method
As per JSON-RPC 1.1 the method should return this json:
{ "sdversion": "1.0", "name": "DemoService", "address": "http:\/\/example.com\/rpc", "id":"urn:md5:4e39d82b5acc6b5cc1e7a41b091f6590", "procs" :[ {"name":"echo","params":["string"]} ] }
Before version 1.5 it was required to have a name == 'DemoService' which was added by mistake, fixed in 1.5. Before version 1.5 it was also required to have a name and an id.
In version >= 1.5 you can use option describe to point to the different fields instead of procs (you can use result.procs
and standard JSON-RPC response).
You will have access to terminal object in this object when you put object as first argument. In second argument if you put a function. That object is also returned by the plugin itself. The terminal is created only once so you can call that plugin multiple times. The terminal object is jQuery object extended by methods listed below.
If you want to get instance of the terminal object when you already have terminal created you can call $('selector').terminal()
.
This is list of available methods (you can also use jQuery methods):
anyLinks: true
option.From version 1.3.0 (with fix in 1.10.0) you can use nested formatting like [[;red;]foo [[;blue;]bar] baz]
(terminal is defining $.terminal.nested_formatting
and adding it to $.terminal.defaults.formatters
).
From version 0.4.19 terminal support ANSI formatting like \x1b[1;31mhello[0m will produce red color hello. Here is shorter description of ansi escape codes.
From version 0.7.3 it also support Xterm 8bit (256) colors (you can test using this GNU Head) and formatting output from man command (overtyping).
From version 0.8.0 it support html/css colors like blue, navy or red
From version 0.9.0 Ansi escape code require unix_formatting.js file.
From version 0.9.0 you can execute commands using echo (you can return command to be executed from server) using same syntax as for formatting, if you echo: [[command arg1 arg2...]]
it will execute that command.
From version 1.15.0 you can execute any terminal or cmd method using systax [[ terminal::method(arg1, arg2) ]]
or [[ cmd::method(arg1, arg2) ]]
, in older version you'll need to create command that will invoke terminal method. You can use new in version 1.15.0 method invoke_key
to execute shortcuts from server using [[ terminal::invoke_key("CTRL+L") ]]
.
If you want to create code that manipulate terminal formatting take a look at $.terminal.formatter object.
From version 1.21.0 executing terminal and cmd methods was disabled by default (because of security) and to enable it you need to use invokeMethods: true
option.
Details about formatting can be found on GitHub Wiki pages: Formatting and Syntax Highlighting and Invoking Commands and terminal methods from Server.
echo(..., { flush:false})
).echo(..., { flush:false})
.flush: false
(it will not display text immediately only add the thing into a buffer) then you can send that text to the terminal output using this function.Additionally everything that is passed within the object will be stored with interpreter on the stack — so it can be pop later. See also Multiple intepreters example.
terminal.invoke_key('CTRL+L')
will clear terminal.Object $.terminal contain bunch of utilities use by terminal, but they can also be used by user code.
a: true, f: "foo"
, if f is in boolean option array it will put f: true
and foo will be in "_"), _ field will contain all non options, and log options (like --file at the begining) will be into object like file: "foo.js"
).
Examples:
$.terminal.parse_options("--foo bar -abc baz quux"); // {_: ["quux"], a: true, b: true, c: "baz", foo: "bar"} var cmd = $.terminal.split_command("copy --foo bar -abc baz quux"); $.terminal.parse_options(cmd.args, {boolean: ["foo", "c"]}); // all options will be boolean and they arguments will be counted as free arguments // {_: ["bar", "baz", "quux"], a: true, b: true, c: true, foo: true} $('body').terminal({ copy: function(...args) { var options = $.terminal.parse_options(args); if (options.dest && options.src) { if (copy(options.src, options.dest)) { this.echo('[[;darkgreen;]successful]'); } else { this.error('failed'); } } else { this.echo('usage\ncopy --dest <file> --src <file>'); } } }, {checkArity: false}); function copy(src, dest) { if (src === 'nonexistent') { return false; } return true; // NOTE: for this dummy example, you can use // return src !== 'nonexistent'; }
Command Line is created as separate plugin, so you can create instance of it (if you don't want whole terminal):
$('#some_id').cmd({ prompt: '$> ', width: '100%', commands: function(command) { //process user commands } });
Here is demo that creates terminal using only cmd.
And this pen is a demo of creating text based dialog.
Command Line options: name, keypress, keydown, mask, enabled, width, prompt, commands, keymap.
This is a list of methods if you are what to use only command line.
This is list of keyboard shortcuts (mostly taken from bash):
All interpreters have attached mousewheel event so you can stroll them using mouse. To swich between terminals you can just click on terminal that you want to activate (you can also use focus method).
On Unix, If you select text using mouse you can paste it using middle mouse button (from version 0.8.0).
To change color of terminal simply modify "jquery.terminal.css" file it's really short and not complicated, but you should set inverted class background-color to be the same as color of text.
To change color of one line you can call css jquery method in finalize function passed to echo function.
terminal.echo("hello blue", { finalize: function(div) { div.css("color", "blue"); } });
You can also use formatting using echo function. To change whole terminal colors see style section.
You can also use css variables (aka custom properties) to change colors of the whole terminal see style section.
All strings used by the plugin are located in $.terminal.defaults.strings
object, so you can translate them and have i18n.
All exceptions in user functions (interpreter, prompt, and greetings) are catch and proper error is displayed on terminal (with stack trace). If you want to handle exceptions differently you can add exceptionHandler option and create different logic, for instance send exceptions to server or show just exception name without stack trace.
From version 0.8.0 blinking cursor is created using CSS3 animations (if available) so you can change that animation anyway you like, just look at jquery.terminal.css file. If browser don't support CSS3 animation blinking is created using JavaScript.
To change color of the cursor to green and backgroud to white you can use this css:
.terminal, .cmd { background: white; color: #0f0; } .terminal .inverted, .cmd .inverted, .cmd .cursor.blink { background-color: #0f0; color: white; } @-webkit-keyframes terminal-blink { 0%, 100% { background-color: #fff; color: #0f0; } 50% { background-color: #0e0; color: #fff; } } @-ms-keyframes terminal-blink { 0%, 100% { background-color: #fff; color: #0f0; } 50% { background-color: #0e0; color: #fff; } } @-moz-keyframes terminal-blink { 0%, 100% { background-color: #fff; color: #0f0; } 50% { background-color: #0e0; color: #fff; } } @keyframes terminal-blink { 0%, 100% { background-color: #fff; color: #0f0; } 50% { background-color: #0e0; color: #fff; } }
From version 1.0.0 you can use css variables with code like this:
.terminal { --color: rgba(0, 128, 0, 0.99); --background: white; }
If you want to have consistent selection you should use rgba color with 0.99 transparency, see this stackoverflow answer.
The only caveat is that css variables are not supported by IE nor Edge.
To change cursor to vertical bar you can use this css:
.cmd .cursor.blink { color: #aaa; border-left: 1px solid #aaa; background-color: black; margin-left: -1px; } .terminal .inverted, .cmd .inverted, .cmd .cursor.blink { border-left-color: #000; } @-webkit-keyframes terminal-blink { 0%, 100% { border-left-color: #aaa; } 50% { border-left-color: #000; } } @-ms-keyframes terminal-blink { 0%, 100% { border-left-color: #aaa; } 50% { border-left-color: #000; } } @-moz-keyframes terminal-blink { 0%, 100% { border-left-color: #aaa; } 50% { border-left-color: #000; } } @keyframes terminal-blink { 0%, 100% { border-left-color: #aaa; } 50% { border-left-color: #000; } }
From 1.0.0 version you can simplify this using this css:
.terminal { --color: rgba(0, 128, 0, 0.99); --background: white; --animation: terminal-bar; }
If you need to support IE or Edge you can set animation using:
.cmd .cursor.blink { -webkit-animation-name: terminal-underline; -moz-animation-name: terminal-underline; -ms-animation-name: terminal-underline; animation-name: terminal-underline; } .terminal .inverted, .cmd .inverted { border-bottom-color: #aaa; }
Or this css for bar cursor:
.cmd .cursor.blink { -webkit-animation-name: terminal-bar; -moz-animation-name: terminal-bar; -ms-animation-name: terminal-bar; animation-name: terminal-bar; } .terminal .inverted, .cmd .inverted { border-left-color: #aaa; }
From version 1.11.0 there are handy css classes (underline-animation and bar-animation) that need to be added to terminal element, so you don't overwrite your css variables.
To change the color of the cursor with differerent animation that will work in IE or Edge you will need to create new @keyframes
with different colors, like in previous examples.
To change font size of the terminal you can use this code:
.terminal, .cmd, .terminal .terminal-output div div, .cmd .prompt { font-size: 20px; line-height: 24px; }
Or from version 1.0.0 (and if you don't care about IE or Edge) you can simplify the code using --size css variables like this:
.terminal { --size: 2; }
The size is relative to original size so 1 is normal size, 1.5 is 150% and 2 is double size.
You can take a look at the demo.
From version 1.10.0 you can use --link-color
to change color of the links. From this version links now change background to color and color to background on hover.
From version 1.7.0 you can use new :focus-within
pseudo selector to change style when terminal or cmd is in focus:
.cmd:focus-within .prompt * { color: red; }
From version 1.15.0 (thanks for PR from David Refoua) you can use --error-color
to change color of errors
You can check it out in this codepen
If you want terminal to look like from OSX, Ubuntu or Winows 10 you can take a look at shell.js library, I've used its css with some tweaks to work with jQuery Terminal. See codepen demo
How to add glow to the terminal
Here is proper code that add glow:
#term { --color: rgba(0, 200, 0, 0.99); --animation: terminal-glow; text-shadow: 0 0 3px rgba(0, 200, 0, 0.6); } .terminal .terminal-output > :not(.raw) .error, .terminal .terminal-output > :not(.raw) .error * { text-shadow: 0 0 3px rgba(200, 0, 0, 0.6); } .terminal .terminal-output > :not(.raw) a[href] { text-shadow: 0 0 3px rgba(15, 96, 255, 0.6); }
terminal-glow animation will be new animation in version 2.1.0, you can test this in devel branch.
This will make sure that links have blue and errors red glow.
$.terminal.formatter
is object that use new features of ECMAScript that allow to use normal object in place of regular expression.
It work in any major browser except IE.
You can use this object like Regex in search/match/replace/split string methods, and it use internal regexes (it would be hard to name all different regular expressions used for different tasks) to do all those actions.
var re = $.terminal.formatter; var str = 'aa[[;blue;]bb] cc [[;red;]] dd'; // split is handled by $.terminal.split_formatting that split formatting // and text but it remove empty strings. console.log(str.split(re)); // in replace each part of the formatting is in its own capturing // group (except brackets and semicolons) // both of those remove formatting from string, same as $.terminal.strip console.log(str.replace(re, function(_, style, color, background) { return arguments[6]; })); console.log(str.replace(re, '$6')); // this will return array of all instances of formatting from string console.log(str.match(re)); // this will return index of first formatting console.log(str.search(re));
formatter don't work with extended commands, so the brackets need to have at least 2 semicolons.
Formatters are a way to format strings in different way. You can create syntax highligher with it. Formatter is a function that get string as input and return terminal formatting see echo method (it can also be array with regex and replacement where replacement can be string or function like in normal string::replace). To add new formatter you simply push (or unshift if you want the benefits of nested formatting) new function to $.terminal.defaults.formatters, by default there is one formatter for nested formatting so you can echo [[;red;]red[[;blue;]blue] also red]
and there are 2 files (xml_formatting.js and unix_formatting.js) with formatters in js directory on github, there is also SQL syntax example and Syntax hightlighter using PrismJS in prism.js file.
From version 1.10.0 formatter can be an array with regex and replacement string or function, the second option is requried if you want your formatter that change the length of the text like with emoji demo. Regex formatter have also 3rd argument which can be object with options (right now only one option is avaible which is loop nad keep replacing until it don't find match).
From same version formatter function can have special property __meta__
set to true (used by nested formatter) that allow to process whole text including formatting, instead of just text between formatting. It was created for internal use, but you can use it in your own code.
From version 1.19.0 formatter can return array [string, position] and it pass cursor position as option, if you're using replacement that change length of the string (like in emoji demo) you can using utility tracking_replace that return array with string and position like is recomended by new formatters.
If you have formatter that change length of the string you will have strange cursor position when you move using arrow keys. There are two different cursor positions you move in original cursor position on input command and you get display of virtual cursor on output string so it sometimes stay in the same position like with emoji demo (you will be after emoji while original cursor is inside word that is used to created emoji so you can delete any key inside the word). There are also two functions to move the cursor (on original text display and display_position to move virtual one).
There are 3 keyboard events (all of them you can add in terminal, cmd and push command):
function(e, original) {
, the original is original function callback that can be called, because your function overwrite original behvaior.Caveats: the shortcut CTRL+D is handled by both keydown and keymap. If terminal is paused is handled by keydown and if not in keymap. If you want to overwrite CTRL+D when terminal is paused you need to pass false to pauseEvents option and use keydown otherwise you need to add function to keymap.
You can provide your authentication function which will be called when user enter login and password. Function must have 3 arguments first is user name, second his password and third is callback function which must be called with token or falsy value if user enter wrong user and password. (You should call server via AJAX to authenticate the user).
You can retrieve token from terminal using token method on terminal instance. You can pass this token to functions on the server as first parameter and check if it's valid token.
If you set interpreter to string (it will use this string as URI for JSON-RPC service) you can set login function to string (to call custom method on service passed as interpreter) or true (it will call login method).
If you set URI of JSON-RPC service and login to true or string, it will always pass token as first argument to every JSON-RPC method.
From version 1.16.0 you can return promise of a token from login function.
Because of security in version 1.20.0 links with protocols different then ftp or http(s)
(it was possible to enter javascript protocol, that could lead to XSS if author of hte app
echo user input and save it in DB) was turn off by default. To enable it, you need to use
anyLinks: true
option.
In version 1.21.0 executing
terminal methods using extendend commands
[[ terminal::clear() ]]
was also disabled by default
because attacker (depending on your application) could execute
terminal::echo with raw option to enter any html. To enable this feature
from this version you need to use invokeMethods: true
option.
The features are safe to enable, if you don't save user input in DB and don't echo it back to different users (like with chat application). It's also safe if you escape formatting before you echo stuff.
If you don't save user input in DB but allow to echo back what user types and have enabled execHash options, you may have reflected XSS vulnerability if you enable this features. If you escape formatting this options are also safe.
One more thing to mention that if you're using raw option to echo back stuff from users (and show it other users), you're also vulnerable to XSS like in any application. So if you wan to do that you need to sanitize user input.
You can find ways to bypass XSS filtering on OWASP. The best is always a whitelist of things that is possible to enter by the users.
NOTE: XSS is possible only when you have application that echo back stuff from your users, like with chat application, guest book or when you save state in url hash and allow to execute it together with echo stuff from users. If you don't do that and you control what is echo on terminal you're fine with any options terminal provide.
NOTE 2: To disable exec if you have `execHash` (or echo stuff from users with `invokeMethods: true`), you can also set option `{exec: false}` to your `echo` call and use it only when you get values from server (not from DB indireclty from users). If you do this you will be able to echo stuff from users and execute terminal methods from server (this feature is mostly done just for that).
Terminal include this 3rd party libraries:
terminal also define this helper functions:
$.jrpc — JSON-RPC helper function.
Function arguments:
Additional files:
From version 1.20.0 every file is UMD module.
unix_formatting.js — The file is defining two formatters $.terminal.overtyping
(that handle output from man command, backspaces and ANSI code \x1b[K that clear line) and $.terminal.from_ansi
(that handle graphic ANSI escape codes) and adding them to the beginning of $.terminal.defaults.formatters, so if ANSI escape generate nested formatting it will be picked up by nesting formatter defined in jQuery Terminal source code.
prism.js — contain monkey patch for PrismJS library (for syntax highlighting) that output terminal formatting. To use it you need to include PrimsJS JavaScript and CSS files.
<link rel="stylesheet prefetch" href="https://cdn.jsdelivr.net/npm/prismjs@1.14.0/themes/prism.css"/> <script src="https://cdn.jsdelivr.net/npm/prismjs@1.14.0/prism.min.js"></script>
then after you include PrismJS you need to include terminal prism monkey patch and then you can use
$.terminal.prism(language, text)
. By default prism include only css,js and markup (html) grammars. To include more you need to load appropriate js files. If no language is found the function returns unmodifed text.
First argument is language so you can bind with fixed language and add that function to formatters array:
$.terminal.defaults.formatters.push( $.terminal.prism.bind(null, 'javascript') );
From version 1.18.0 you can use helper $.terminal.sytnax.
$.terminal.syntax('website');
This is preferable way to have syntax highlighting ('website' is special language addded in version 1.18.0 and renders html, css and javascript).
less.js — this file contain jQuery plugin that can be use with terminal (and since terminal instance if extension of jQuery object you can invoke it like terminal method).
$('body').terminal({ less: function(file) { // this is terminal instance and arrow function allow to use // this from outside $.get(file, (text) => this.less(text)); } });
dterm
that is combination of jQuery UI Dialog and jQuery Terminal.xml_formatting.js — created as example of formatter. By including this file it allow to use xml syntax to color text (using echo).
<red>foo <green>bar</green> baz</red>
ascii_table.js — Define UMD module with ascii_table function that return simple ASCII table, like the one from mysql cli command. it have wcwidth as dependecy, in browser it's optional.
pipe.js — defines experimental pipe interpreter (it support | and custom redirects) see pipe example.