Sverminal is a Svelte component that provides a terminal emulator to be used in the browser. This component relies on Tailwind CSS for its styling.
Try out the Live Demo!
Svelte and Tailwind CSS installed in your project.
Step 1: Install the sverminal npm package.
npm install sverminal
Step 2: Add the sverminal package source files to your Tailwind CSS configuration file.
export default {
content: [
'./src/**/*.{html,js,ts,svelte}',
'./node_modules/sverminal/dist/**/*.{html,js,ts,svelte}'
]
};
Simply pass a command handler callback to the Sverminal component.
<script lang="ts">
import Sverminal from 'sverminal';
async function processor(command: string): Promise<void> {
// Your command processing logic here
}
</script>
<Sverminal {processor}/>
Consumers of the Sverminal component can optionally provide a custom configuration. All properties are optional and if omitted will fallback to defaults values. For convenience, all examples below showcase the default values.
<Sverminal {processor} config={myConfiguration}/>
Each property in the style object accepts a list of CSS classes that will be applied to the relevant text elements.
const myConfiguration = {
style: {
prompt: ['text-emerald-400'], //Ex: 'sverminal>'
command: ['text-violet-400'], //The first word of user input
flags: ['text-slate-400'], //Arguments prefixed with '-'
info: ['text-cyan-400'],
error: ['text-red-400'],
warn: ['text-yellow-400'],
text: ['text-slate-50'] //Everything else...
}
}
By default Sverminal will keep track of a users command history in memory. This can be disabled or further configured within a custom configuration. The limit property puts a cap on the number of unique commands tracked in the specified history method. When the cap is reached, newer commands will replace the oldest commands in history.
const myConfiguration = {
history: {
enabled: true,
method: 'memory', //memory (default), sessionstorage, localstorage
limit: 10
},
}
Here are some additional configuration options that you find useful...
const myConfiguration = {
promptSuffix: '>', //The characters to place at the end of the prompt.
newlineBetweenCommands: false, //If set to true, an extra line will be appended after submitting a command.
quoteMultiWordAutoCompletes: true //Optionally wrap multi-word auto-completes with quotes.
}
import { SverminalReader } from '$lib/reader/reader.js';
let sverminalReader = new SverminalReader();
async function processCommand(command: string): Promise<void> {
...
let name = "";
await sverminalReader.read("What is your name?").then((value: string) => {
name = value;
});
...
}
The SverminalWriter class provides library users with the ability to write content back to the terminal. This could be for used for anything from simply printing error messages to the user when a command fails or developing a complex text-based user interface.
The writer API is pretty simple. The echo, error, warn, and info functions writer their respective output to the terminal as independent lines or block display. The write and writeLink functions writer their output inline which provides the client more flexibility when it is desired to output more complex content.
writer.echo('Echo some text');
writer.warn('Print a warning');
writer.error('Print an error');
writer.info('Print some information')
writer.write('This text will be inline and green.', ['text-green-500']);
writer.writeLink('Sverminal!', 'https://sverminal.io', ['text-purple-500']);
writer.clear() //Clears all terminal content.
Here is a minimal example of setting up a writer to simply echo the command back to the user.
<script lang="ts">
import { Sverminal, SverminalWriter } from 'sverminal';
let writer = new SverminalWriter();
async function processor(command: string): Promise<void> {
// Example: echo the command back to the terminal.
writer.echo(command);
}
</script>
<Sverminal {processor} {writer}/>
Some of your commands may require users to enter additional input. The SverminalReader class was created to accomplish this use case. Use it within the command handling function to await additional input from the user.
Here is a minimal example of setting up a reader to request additional user input needed to process a command.
<script lang="ts">
import { Sverminal, SverminalReader } from 'sverminal';
let reader = new SverminalReader();
async function processor(command: string): Promise<void> {
// Example: any command will prompt the user for their name.
let name = await reader.read("What is your name?");
}
</script>
<Sverminal {processor} {reader}/>
To enable users to operate quickly and efficiently within user-defined terminal programs, Sverminal accepts a property called autoCompletes. This property accepts a list of strings that are potential autocomplete options that automatically populate onto the prompt when the user presses the TAB key. This property can be updated with different string lists as the user interacts with the terminal.
Here is an example of what the autoCompletes property might be set to in a simple calculator program. Upon pressing the TAB key, the user can iterate through the commands based on existing characters already typed into the prompt.
<script lang="ts">
import { Sverminal } from 'sverminal';
let autoCompletes = ['add', 'subtract', 'multiply', 'divide'];
async function processor(command: string): Promise<void> {
//Your processing logic here;
}
</script>
If you want to change the auto complete options dynamically while the user is entering a command, the component provides an event 'get-current-command'. This fires each time the user types something into the prompt and provides the active contents of the command so far.
<Sverminal {processor} {autoCompletes} on:get-current-command={getCurrentCommand}/>
Run the demo locally.
npm run dev