Skip to content

Commit 4d3ff9e

Browse files
committedOct 14, 2018
Rewrite as flexible object
- Proper API - Basic readable docs - Fixed history not counting args - Improved things - More generic demo page
1 parent 815d08a commit 4d3ff9e

File tree

4 files changed

+187
-158
lines changed

4 files changed

+187
-158
lines changed
 

‎README.md

+11-17
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,36 @@ var settings = {
2323
name: "echo", //Command name
2424
description: "a test command with one echo arg", //Help text to be displayed when `help` command is called
2525
parameters: ["a string to be echoed in console"], //An optional array of successive parameter descriptions, used when the command that needs args is being called without any args
26-
func: function(params){println(params[0])} //Function to be called when the command is executed. Accepts an array of parameters, ordered in the same way as in the previous property
26+
func: function(params){plainterm.print(params[0])} //Function to be called when the command is executed. Accepts an array of parameters, ordered in the same way as in the previous property
2727
},
2828
test: {
2929
name: "test",
3030
description: "a test command with no args",
31-
func: function(){println("testing things")}
31+
func: function(){plainterm.print("testing things")}
3232
},
3333
multiply: {
3434
name: "multiply",
3535
description: "Multiply two numbers",
3636
parameters: ["number one", "number two"],
37-
func: function(params){println(params[0]*params[1])}
37+
func: function(params){plainterm.print(params[0]*params[1])}
3838
}
3939
}
4040
};
4141

42-
term_init(settings);
42+
plainterm.init(settings);
4343
```
4444

4545
## Working with the terminal:
4646

4747
`help` - Display a list of all commands with descriptions
48+
4849
`command` - Execute a command. Will display "Usage: command [parameter 1 description] [parameter 2 description], etc.", when needs args but called without them.
4950

5051
## API:
5152

52-
`println(text, command)` - Print a text in terminal starting from a new line. Command - optional, count given string as a command (prepend prompt, syntax highlight).
53-
54-
`bash.version` - plainterm.js version
55-
`bash.commands` - an object containing all available commands available
56-
57-
58-
`bash.commands.[command].name` - command name
59-
60-
`bash.commands.[command].description` - command description
61-
62-
`bash.commands.[command].parameters` - command parameters
63-
64-
`bash.commands.[command].func` - retrieve a function. call with `bash.commands.[command].func()`
53+
| Method | Description | Parameters |
54+
| ------------- | ------------- | ------------- |
55+
| `init(settings)` | Initialize a terminal in a DOM with given ID | Object. See the example above |
56+
| `print(text, c)` | Prints a given text in the terminal | `text` - String, `c` - Boolean, optional, defaults to false. Count given string as a command (displays prompt, syntax highlight and appears in history) |
57+
| `run(text)` | Emulates a command execution in a terminal (acts the same way as a use would have typed and pressed Enter) | `text` - String |
58+
| `hist(up)` | Search in command history. Returns string. | `up` - Boolean, optional. Defaults to true. Upward/downward search. |

‎index.html

+22-14
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,55 @@
22
<html lang="en">
33
<head>
44
<meta charset="utf-8">
5-
<title>mkrl.xyz</title>
6-
<meta name="description" content="A personal website of mine. Why are you here?">
7-
<meta name="author" content="mkrl">
8-
<link rel="stylesheet" href="s.css">
5+
<title>plainterm.js</title>
6+
<link rel="stylesheet" href="style.css">
7+
<style>
8+
.container > div {
9+
margin: 0 auto;
10+
}
11+
</style>
912
</head>
1013
<body>
1114

12-
<center><h3>Hello</h3></center>
15+
<center><h3>Terminal</h3></center>
1316

17+
<div class="container">
1418
<div id="terminal">
1519
</div>
20+
</div>
1621

1722
<script src="./plainterm.js"></script>
1823
<script>
1924
var settings = {
2025
id: "terminal",
21-
welcome: "Welcome to plainterm.js terminal emulator",
2226
prompt: "user@mkrl.xyz:~$ ",
2327
commands: {
24-
test: {
25-
name: "test",
26-
description: "a test command with no args",
27-
func: function(){println("testing things")}
28+
about: {
29+
name: "about",
30+
description: "about the module",
31+
func: function(){plainterm.print('A dead simple lightweight pure Javascript terminal "emulator" that is intended to be used for entertainment purposes. Written in one night.')}
32+
},
33+
repo: {
34+
name: "repo",
35+
description: "GitHub repository",
36+
func: function(){plainterm.print('<a href="https://github.com/mkrl/plainterm.js" target="blank">Click</a>')}
2837
},
2938
echo: {
3039
name: "echo",
3140
description: "a test command with one echo arg",
3241
parameters: ["a string to be echoed in console"],
33-
func: function(params){println(params[0])}
42+
func: function(params){plainterm.print(params[0])}
3443
},
3544
multiply: {
3645
name: "multiply",
3746
description: "multiply two numbers",
3847
parameters: ["number one", "number two"],
39-
func: function(params){println(params[0]*params[1])}
48+
func: function(params){plainterm.print(params[0]*params[1])}
4049
}
4150
}
4251
};
4352

44-
term_init(settings);
45-
println(settings.welcome);
53+
plainterm.init(settings);
4654
</script>
4755
</body>
4856
</html>

‎plainterm.js

+153-125
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,173 @@
11
/* plainterm.js
22
https://github.com/mkrl/plainterm.js */
33

4-
//Declare master object
5-
var bash = {commands: {}, history: [], last: 0,
6-
version: "0.3"
7-
}
8-
9-
//Master command constructor
10-
function Command(name, description, parameters = [], func) {
11-
this.name = name;
12-
this.description = description;
13-
this.parameters = parameters;
14-
if (parameters.length > 0) {
15-
var pnames = "";
16-
for (p of parameters) {
17-
pnames = pnames + " [" + p + "]";
18-
}
19-
this.func = function(params) {
20-
params = params || false;
21-
if (params == false) {
22-
println("usage: " + name + pnames);
23-
} else {
24-
func(params);
4+
5+
var plainterm = (function() {
6+
7+
//Master object
8+
var bash = {commands: {}, history: [], last: 0,
9+
version: "0.4"
10+
}
11+
12+
//Master command constructor
13+
function Command(name, description, parameters = [], func) {
14+
this.name = name;
15+
this.description = description;
16+
this.parameters = parameters;
17+
if (parameters.length > 0) {
18+
var pnames = "";
19+
for (p of parameters) {
20+
pnames = pnames + " [" + p + "]";
2521
}
22+
this.func = function(params) {
23+
params = params || false;
24+
if ((params == false)||(params.length < parameters.length)) {
25+
println("usage: " + name + pnames);
26+
} else {
27+
func(params);
28+
}
29+
}
30+
} else {
31+
this.func = func;
2632
}
27-
} else {
28-
this.func = func;
2933
}
30-
}
3134

32-
//Constructing help command
33-
bash.commands.help = new Command("help","shows a help message", [],
34-
function(){
35-
Object.getOwnPropertyNames(bash.commands).map(function(cmd){
36-
println(bash.commands[cmd].name + " - " + bash.commands[cmd].description);
37-
});
38-
});
35+
//Utility functions
36+
37+
//Initialize terminal from parameters
38+
function term_init(settings) {
39+
settings.id = settings.id || "terminal";
40+
settings.welcome = settings.welcome || "plainterm.js v. " + bash.version;
41+
settings.prompt = settings.prompt || "$ ";
42+
for (o of Object.keys(settings.commands)) {
43+
var cmd = settings.commands[o];
44+
addcommand(cmd);
45+
}
46+
build_tree(document.getElementById(settings.id));
47+
println(settings.welcome);
48+
}
3949

4050

41-
//Utility functions
51+
//Build terminal DOM tree
52+
function build_tree(dom) {
53+
dom.className = "terminal";
54+
var container = document.createElement("div");
55+
var input_container = document.createElement("div");
56+
var prompt_span = document.createElement("span");
57+
prompt_span.innerHTML = settings.prompt;
58+
var input = document.createElement("input");
59+
container.className = "terminal-container";
60+
input_container.className = "terminal-type";
61+
input.setAttribute("type", "text");
62+
input.setAttribute("onkeypress", "plainterm.run(this)");
63+
dom.appendChild(container);
64+
dom.appendChild(input_container);
65+
for (e of document.getElementsByClassName("terminal-type")) {
66+
e.appendChild(prompt_span);
67+
e.appendChild(input);
68+
}
69+
bash.container = dom.firstElementChild;
70+
bash.container.input = input;
71+
dom.onclick = function() {input.focus()}
72+
}
4273

43-
//Initialize terminal from parameters
44-
function term_init(settings) {
45-
settings.id = settings.id || "terminal";
46-
settings.welcome = settings.welcome || "plainterm.js v. " + bash.version;
47-
settings.prompt = settings.prompt || "$ ";
48-
for (o of Object.keys(settings.commands)) {
49-
var cmd = settings.commands[o];
74+
function addcommand(cmd) {
5075
bash.commands[cmd.name] = new Command(cmd.name, cmd.description, cmd.parameters, cmd.func);
5176
}
52-
build_tree(document.getElementById(settings.id));
5377

54-
}
55-
56-
57-
//Build terminal DOM tree
58-
function build_tree(dom) {
59-
var container = document.createElement("div");
60-
var input_container = document.createElement("div");
61-
var prompt_span = document.createElement("span");
62-
prompt_span.innerHTML = settings.prompt;
63-
var input = document.createElement("input");
64-
container.className = "terminal-container";
65-
input_container.className = "terminal-type";
66-
input.setAttribute("type", "text");
67-
input.setAttribute("onkeypress", "run(this)");
68-
dom.appendChild(container);
69-
dom.appendChild(input_container);
70-
for (e of document.getElementsByClassName("terminal-type")) {
71-
e.appendChild(prompt_span);
72-
e.appendChild(input);
73-
}
74-
bash.container = dom.firstElementChild;
75-
bash.container.input = input;
76-
dom.onclick = function() {input.focus()}
77-
}
78-
79-
//Prints a newline in console
80-
function println(content, c = false) {
81-
var line = document.createElement("p");
82-
if (c === true) {
83-
var cmd = document.createElement("span");
84-
cmd.innerHTML = content;
85-
cmd.className = "command";
86-
line.innerHTML = settings.prompt;
87-
bash.container.appendChild(line);
88-
line.appendChild(cmd);
89-
} else {
90-
line.innerHTML = content;
91-
bash.container.appendChild(line);
78+
79+
//Prints a newline in console
80+
function println(content, c = false) {
81+
var line = document.createElement("p");
82+
if (c === true) {
83+
var cmd = document.createElement("span");
84+
cmd.innerHTML = content;
85+
cmd.className = "command";
86+
line.innerHTML = settings.prompt;
87+
bash.container.appendChild(line);
88+
line.appendChild(cmd);
89+
} else {
90+
line.innerHTML = content;
91+
bash.container.appendChild(line);
92+
}
9293
}
93-
}
94-
95-
//Eval as command
96-
function evaluate(cmd) {
97-
comms = cmd.split(/\s+/);
98-
comm = comms[0];
99-
comms.shift();
100-
if (Object.getOwnPropertyNames(bash.commands).indexOf(comm) > -1) {
101-
bash.commands[comm].func(comms);
102-
bash.history.unshift(comm);
103-
} else {
104-
println(comm + " - command not found")
94+
95+
//Eval as command
96+
function evaluate(cmd) {
97+
comms = cmd.split(/\s+/);
98+
comm = comms[0];
99+
comms.shift();
100+
if (Object.getOwnPropertyNames(bash.commands).indexOf(comm) > -1) {
101+
bash.commands[comm].func(comms);
102+
bash.history.unshift(cmd);
103+
} else {
104+
println(comm + " - command not found")
105+
}
105106
}
106-
}
107-
108-
//Reads text on Enter press
109-
function run(cmd) {
110-
if(event.keyCode == 13) {
111-
println(cmd.value, true);
112-
if (cmd.value.length > 0) {
113-
evaluate(cmd.value)
107+
108+
//Reads text on Enter press
109+
function run(cmd) {
110+
if(event.keyCode == 13) {
111+
println(cmd.value, true);
112+
if (cmd.value.length > 0) {
113+
evaluate(cmd.value)
114+
}
115+
cmd.value = "";
116+
bash.last = 0;
117+
bash.container.input.scrollIntoView();
114118
}
115-
cmd.value = "";
116-
bash.last = 0;
117-
bash.container.input.scrollIntoView();
118119
}
119-
}
120-
121-
//History
122-
123-
function get_from_history(up = true) {
124-
if (bash.history.length > 0) {
125-
if (up === true && bash.last < bash.history.length-1) {
126-
bash.container.input.value = bash.history[bash.last];
127-
bash.last++;
128-
} else if (up === false && bash.last > 0){
129-
bash.container.input.value = bash.history[bash.last];
130-
bash.last--;
120+
121+
//History
122+
123+
function get_from_history(up = true) {
124+
if (bash.history.length > 0) {
125+
if (up === true && bash.last < bash.history.length-1) {
126+
bash.container.input.value = bash.history[bash.last];
127+
bash.last++;
128+
} else if (up === false && bash.last > 0){
129+
bash.container.input.value = bash.history[bash.last];
130+
bash.last--;
131+
}
131132
}
132133
}
133-
}
134-
135-
document.addEventListener('keydown', function(event) {
136-
const key = event.key;
137-
switch (event.key) {
138-
case "ArrowUp":
139-
get_from_history();
140-
break;
141-
case "ArrowDown":
142-
get_from_history(false);
143-
break;
134+
135+
document.addEventListener('keydown', function(event) {
136+
const key = event.key;
137+
switch (event.key) {
138+
case "ArrowUp":
139+
get_from_history();
140+
break;
141+
case "ArrowDown":
142+
get_from_history(false);
143+
break;
144+
}
145+
});
146+
147+
//Constructing default help command
148+
bash.commands.help = new Command("help","shows a help message", [],
149+
function(){
150+
Object.getOwnPropertyNames(bash.commands).map(function(cmd){
151+
println(bash.commands[cmd].name + " - " + bash.commands[cmd].description);
152+
});
153+
});
154+
155+
//API
156+
return {
157+
init: term_init,
158+
run: run,
159+
print: println,
160+
hist: get_from_history
144161
}
145-
});
162+
163+
})();
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+

‎s.css ‎style.css

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
/* plainterm.js
22
https://github.com/mkrl/plainterm.js */
33

4-
#terminal {
4+
.terminal {
55
width: 500px;
66
height: 600px;
77
overflow-y: auto;
88
overflow-x: hidden;
9-
margin: 0 auto;
109
border: 1px black solid;
1110
background-color: black;
1211
color: white;

0 commit comments

Comments
 (0)
Please sign in to comment.