Coder Social home page Coder Social logo

terminal-kit's Introduction

★ License Downloads Version Run on repl.it

Stats

Terminal Kit

A full-blown terminal lib featuring: 256 colors, styles, keys & mouse handling, input field, progress bars, screen buffer (including 32-bit composition and image loading), text buffer, and many more...

Whether you just need colors & styles, build a simple interactive command line tool or a complexe terminal application: this is the absolute terminal lib for Node.js!

It does NOT depend on ncurses.

Some tutorials are available at blog.soulserv.net/tag/terminal.

Screenshot, PleaZe!

This is a fraction of what Terminal-Kit can do, with only few lines of code. Click any image to see the documentation related to the feature!

Styles output

Word-wrapping ← Word-wrapping

Table ← Table with automatic column computing, cell fitting and word-wrapping

Input field output

File input output

Input field output

Single line menu output

Single column menu output

Grid menu output

Progress bar output

Progress bar output

Slow typing output

Yes or no output

Spaceship ← Surfaces and Sprites

Draw an image inside the terminal ← Load and draw an image inside the terminal

Key features

New: Document model for building rich app GUI

New: Spinner

New: Table with automatic column computing, cell fitting and word-wrapping

New: Promises can be used instead of callback everywhere

New: Word-wrapping along full terminal width or a pre-defined column-width

New: ScreenBuffer HD 32-bit (RGBA) surfaces with composition and image loading

Quick examples

// Require the lib, get a working terminal
var term = require( 'terminal-kit' ).terminal ;

// The term() function simply output a string to stdout, using current style
// output "Hello world!" in default terminal's colors
term( 'Hello world!\n' ) ;

// This output 'red' in red
term.red( 'red' ) ;

// This output 'bold' in bold
term.bold( 'bold' ) ;

// output 'mixed' using bold, underlined & red, exposing the style-mixing syntax
term.bold.underline.red( 'mixed' ) ;

// printf() style formatting everywhere:
// this will output 'My name is Jack, I'm 32.' in green
term.green( "My name is %s, I'm %d.\n" , 'Jack' , 32 ) ;

// Since v0.16.x, style markup are supported as a shorthand.
// Those two lines produce the same result.
term( "My name is " ).red( "Jack" )( " and I'm " ).green( "32\n" ) ;
term( "My name is ^rJack^ and I'm ^g32\n" ) ;

// Width and height of the terminal
term( 'The terminal size is %dx%d' , term.width , term.height ) ;

// Move the cursor at the upper-left corner
term.moveTo( 1 , 1 ) ;

// We can always pass additional arguments that will be displayed...
term.moveTo( 1 , 1 , 'Upper-left corner' ) ;

// ... and formated
term.moveTo( 1 , 1 , "My name is %s, I'm %d.\n" , 'Jack' , 32 ) ;

// ... or even combined with other styles
term.moveTo.cyan( 1 , 1 , "My name is %s, I'm %d.\n" , 'Jack' , 32  ) ;

// Get some user input
term.magenta( "Enter your name: " ) ;
term.inputField(
	function( error , input ) {
		term.green( "\nYour name is '%s'\n" , input ) ;
	}
) ;

License: MIT

terminal-kit's People

Contributors

achannarasappa avatar apowers313 avatar brandondrew avatar bsorrentino avatar cronvel avatar dangilkerson avatar drunkhacker avatar hfhchan avatar joshwyatt avatar jub3i avatar laurent22 avatar moosethecoder avatar nginth avatar samizdatco avatar stereoraj avatar tniessen avatar zolem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terminal-kit's Issues

ScreenBufferHD with createTerminal?

hello, first I'd like to say thanks for the library. I am having fun making a game with clojurescript and this.

I have been using createTerminal instead of the plain terminal because the game is a server for telnet connections, but I can't seem to get the screenbuffers (with lots of fun colors) to work at the same time.

does ScreenBufferHD only work with terminal?

thanks for any tips. i've got kids crawling all over me and i dont get much time to dig into these things

Control inputField format

Is there any existing feature to control format of inputField on the go ?
I was trying to have a syntax coloration based on the content (For example highlighting typo in red).
Is that something doable ? Any plan for this kind of flexibility ?

Error thrown puts the terminal into a bad state.

Using the following code:

var term = require('terminal-kit').terminal
term.grabInput( { mouse: 'button', focus: true } ) 
term.on( 'mouse' , function( name , data ) {}) 
setTimeout( function() { throw new Error('dafuq') } , 1 ) 

I get a terminal where my mouse actions are swallowed and instead some escape sequences are written into it.

This happens both with terminology and gnome-terminal.

restoreCursor not working when current line is at bottom of terminal?

I am trying to use a singleColumnMenu to display some options. The idea here is when the user selects an item, the app will:

  1. Clear the singleColumnMenu
  2. Replace it with a .inputField
  3. Gather the input
  4. Redisplay the singleColumnMenu where it was before

I tried some preliminary code to see if I could accomplish steps 1-2, but restoreCursor() is acting in a nondeterministic fashion. I'm on OSX in Terminal.app.

If I cmd-K my terminal to clear the screen, my app works perfectly. In fact I can execute the app a few times and it still works perfectly. However, when my terminal's prompt get down near the bottom of my terminal screen and I execute my program, the menu is not erased and the input is placed after the menu items. If I cmd-K and run again, everything works fine again.

I've attached a gif that shows what's happening.

Curson Restor Problem

Here is the code:

var term = require( 'terminal-kit' ).terminal ;

var items = [
  'Option 1.' ,
  'Option 2.' ,
  'Option 3.'
] ;

term.saveCursor();
start();

function start() {
  //display the menu
  term.singleColumnMenu( items , ( error , response ) => {
    //restore the cursor to where it was before the menu was displayed
    term.restoreCursor();
    //console.log(`origX=${origX}, origY=${origY}`);
    //term.moveTo(origX, origY);
    term.eraseDisplayBelow();
    //dsiplay the input field where the menu once was
    term(' Enter some text: ');
    term
      .inputField(function( error, input ) {
        term.restoreCursor();
        term.eraseDisplayBelow();
        term.singleColumnMenu( items, (error, response) => { process.exit(); } );
      });
  } ) ;
}

Autocomplete middle of token does not remove trailing matching content

Awesome lib. I have a problem with autocompletion though. How to reproduce:

Run:

var term = require( 'terminal-kit' ).terminal ;

var history = [ 'John' , 'Jack' , 'Joey' , 'Billy' , 'Bob' ] ;

var autoComplete = [
	'Barack Obama' , 'George W. Bush' , 'Bill Clinton' , 'George Bush' ,
	'Ronald W. Reagan' , 'Jimmy Carter' , 'Gerald Ford' , 'Richard Nixon' ,
	'Lyndon Johnson' , 'John F. Kennedy' , 'Dwight Eisenhower' ,
	'Harry Truman' , 'Franklin Roosevelt'
] ;

term( 'Please enter your name: ' ) ;

term.inputField(
	{ history: history , autoComplete: autoComplete , autoCompleteMenu: true } ,
	function( error , input ) {

		term.green( "\nYour name is '%s'\n" , input ) ;
		process.exit() ;
	}
) ;

Enter some matching input and move cursor to the left:
screenshot

now press TAB:
Input will now be broken
screenshot

Expected result:
Auto-complete should recognize that the content following cursor is part of the matched completion and overwrite it.

Position at specific location in inputField?

I was wondering is it currently possible to programmatically move the cursor in an inputField? The use case I have in mind is that I display an inputField and pre-populate with eg mkdir "" and I move the cursor automatically between the quotes so that the user can start typing from there directly.

I know there's already something to start with a default value but I couldn't find how to set the cursor. Can this currently be done?

.gridMenu() indentation?

@cronvel I have quick questions. I was wondering, is there a way to set an indentation (tab char) when displaying the .gridMenu()?

screen shot 2017-08-28 at 4 25 17 pm

I attached a screenshot to better show what I mean. I did try to use the following options: leftPadding, selectedLeftPadding, rightPadding and selectedRightPadding but with not ideal results.

The issue is that when you move the cursor on top of a name, they get chopped off and weird things happens.

I wonder if there is a way to do it :)

Stop scrollback in fullscreen()

Is there a way to stop the user from scrolling up above the fullscreen window while fullscreen() is enabled? Blessed does this, but I haven't been able to make it work with terminal-kit.

How to return the string using .str()?

Maybe I misunderstand the documentation, but shouldn't
`term.blue('BLUE').str()' return a string with escape codes for blue? It always print the string in blue to the terminal.

Terminal-kit is failing in meteor.

var x = Npm.require("terminal-kit");

Error:

undefined

/home/singgum3b/.meteor/packages/meteor-tool/.1.1.10.ki0ccv++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:245
                        throw(ex);
                              ^
TypeError: Object prototype may only be an Object or null
    at create (native)
    at Function.create (/home/singgum3b/.meteor/packages/ecmascript-runtime/.0.2.6.s34ngz++os+web.browser+web.cordova/npm/node_modules/meteor-ecmascript-runtime/node_modules/core-js/modules/es6.symbol.js:87:28)
    at Object.<anonymous> (/home/singgum3b/Projects/meteor-gulp-seed/node_modules/terminal-kit/lib/ScreenBuffer.js:42:33)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/home/singgum3b/Projects/meteor-gulp-seed/node_modules/terminal-kit/lib/termkit.js:58:24)

any idea?

How to Animate a Line

Hi ^^, thx you for Terminal-kit !

I'm trying to animate lines with the screenBuffer like the demo spaceship but i'm having trouble to understand how animation logic work with the screenbuffer.

The idea its to create a big buffer to put one buffer per line to write word and move words left to right.

like this :

var viewport = termkit.ScreenBuffer.create({
  dst: term,
  width: term.width - 5,
  height: term.height
});

term.fullscreen();
term.hideCursor();

var lines =[];
var test;
// _____________Config Object Ligne________________
function createLineBuffer(callback) {
  line = termkit.ScreenBuffer.create({
    dst: viewport,
    width: term.width - 5,
    height: 2,
    x: 1,
    y: 2
  });

  line.put({
    x: 1,
    y: 1,
    attr: {
      color: 'brightMagenta',
      bgColor: "black"
    }
  }, " test1");
  callback(line);
  lines.push(line)
}
function nextMove(){
  lines[0].x ++;
  lines[0].draw();
}

function drawBuffer(object) { // draw le buffer
  viewport.draw();
  object.draw();
}
createLineBuffer(drawBuffer)

function animate() {
  createLineBuffer(drawBuffer)
  setInterval(nextMove, 1000);
}
animate();

The question is pretty short.

What's the logic to animate a linebuffer ?

createBuffer, put , draw and move x ? Do i need to clear the buffer before draw() for the next move ?

If someone can give me a simple example it will be awesome.
Please help me ^^.

Thx you :).

What applications are based on this package?

I've just had a look at the package and I'm really impressed by it, the documentation, examples and tutorials are also excellent.

I'm curious thought, what was it initially created for? Is it to support an existing application? By the way are there any well know application based on this package (perhaps there could be a list in the readme file)?

Screen Dump

Allows to extract screen text data.

My use-case is testing some terminal interface. Other use-cases my be "term-screensavers"; Post written highlighters; Automation...

Assistance with handling and tracking down the cause of: Error: .getCursorLocation() timed out

I've built an SSH server to wrap some unsecured connections. Using terminal-kit for the interactive auth and menus. During interactive auth I've been having an issue where sometimes on slow vpn connections term.inputField will return an error of "Error: .getCursorLocation() timed out". I'm managed to solve this with: term.timeout = 3000 but that is not a very robust solution unless I pick some arbitrarily large value. but that could have its own issues.

To give a little background client's connect via varied Linux/Windows ssh clients. I'm using SSH2 on the server side. Once a shell is ready I create a terminal using the shells stream. From there on out its term(prompt) and term.inputField(...) to perform interactive two-factor auth as well as menu display/selection. Mainly, during login term.inputField will sometimes return Error: .getCursorLocation() timed out. Once it has done this it seems to kill stdin half of the stream. Thus it does not seem like it will be easy to recover from this error without creating the term.

_handleConnection(client, info) {
   ...
    client
        ...
        .on('session', (accept, reject)=> {
            let session = accept()
            this.logger(connectionData.id, connectionData.username, "session start")

            session
                .on('shell', (accept, reject)=> {
                    this.logger(connectionData.id, connectionData.username, "shell opened")
                    connectionData.stream = accept()
                    connectionData.term = term.createTerminal({stdin: connectionData.stream, stdout: connectionData.stream})
                    connectionData.term.timeout = 3000
                    connectionData.state = (connectionData.authMethod === 'interactive') ? 'auth' : 'mainMenu'
                    connectionData.interval = setInterval(()=>this._connectionLoop(connectionData), 100)
                })
    ...........

// called repeatedly from the auth code to get username/password/2FA token
_getInput({term, prompt, minLength = 1, maxLength = 128, maxTries = 3, tries = 0, isPassword = false, resolve, reject, connectionData = {id: '-', username: '-'}}) {
    let internalFunc = ({term, minLength = 0, maxLength = 128, maxTries, tries, isPassword, resolve, reject})=> {
        this.logger(connectionData.id, connectionData.username, `_getInput.internalFunc: ${prompt}`)
        term(prompt)
        term.inputField({echo: !isPassword, maxLength, minLength}, (error, input) => {
            this.logger(connectionData.id, connectionData.username, `_getInput.internalFunc.term.inputField received: input = ${input} error = ${error}`)
            term('\r\n\r\n')
            if (error || !input || input === '') {
                if (tries < maxTries) {
                    tries++
                    this._getInput({term, prompt, minLength, maxLength, maxTries, tries, isPassword, resolve, reject, connectionData})
                } else {
                    reject(error)
                }
            } else {
                resolve(input)
            }
        })
    }

    if (resolve === undefined || reject === undefined) {
        this.logger(connectionData.id, connectionData.username, `_getInput: ${prompt}`)
        return new Promise((resolve, reject)=> {
            this._getInput({term, prompt, minLength, maxLength, maxTries, tries, isPassword, resolve, reject, connectionData})
        })
    } else {
        internalFunc({term, prompt, minLength, maxLength, maxTries, tries, isPassword, resolve, reject})
    }
}

I'd be grateful for some feedback on how to better handle the "Error: .getCursorLocation() timed out"

inputField runs forever

I would expect this program to terminate

var term = require('terminal-kit').terminal

term('enter something: ')
term.inputField(function (err, input) {
  term('should terminate')
  terminate()
})

function terminate () {
  term.grabInput(false)
  // should terminate app now?
}

But it never does. Not until the user manually closes it. Is this expected behaviour?

Promises

any plans to make this return promises instead of the standard callback?

Delete and insert line does not work in cygwin

I'm trying to use terminal-kit with cygwin, specifically Git Bash on Windows.

When I try to use deleteLine or insertLine, noting happens.

The only debug info I could get was that the terminalKit.generic value is 'cygwin'.

Please let me know if there is some other debugging info I can get you..

Move `grabInput()` to standalone module

I've seen that grabInput() and onStdin() methods are really powerful and at the same time they are mostly agnostic to the rest of the terminal, so do you mind converting them on an independent module exposing them as an EventEmitter? This way it would not be needed to require the full library... Would you accept pull-requests for that?

Autocomplete not working?

I've copied and run the documentation example that features history and auto-completion, but the auto-complete is not working for me. Can you help me to understand why?

(I'm using node v6.8.1, [email protected], iTerm and Fish shell).

jun-14-2017 18-08-04

InputField autoComplete strip prefix

It would be great to have an option to strip a prefix from auto-complete items.
For example if you want to build a shell-like environment, cmd fil could be auto-completed to cmd file0 or cmd file1. Within the items shown for completion, the cmd prefix should be stripped out.

terminal-kit very upset if TERM is not set

Sometimes (i.e. on Windows), the TERM environment might not be set. In detectTerminal.js, this makes appId undefined, and then makes generic undefined and then causes a crash when the give-up code tries to convert undefined to lower-case.

The solution is to have a fallback string of some sort if none of the environment variables the library is looking for are set. I have no idea if after that the library will work correctly on any of these platforms, bit it will at least not explode immediately.

Use terminal-kit with not stream

Hi. First of all, thanks for this library, it is great.
I'm trying to use terminal-kit to send / read data over a very simple telnet server. Writing works fine, it clears the screen and greets who's connected with a red "Welcome". Input events, on the other side, don't seem to work. This is my sample code:

const tkit = require('terminal-kit');
const net  = require('net');

const server = net.createServer(socket => {
    const term = tkit.createTerminal({
        stdin:  socket,
        stdout: socket,
    });

    term.clear();
    term.red('Welcome!');

    term.on('key', key => {
        console.log(key);
    });

    // THIS WORKS
    // socket.on('data', data => {
    //     console.log(data);
    // });
});

// Listen on port 8888
server.listen(8888);

Do TextBuffers support transparency?

I've run into some unexpected differences in behavior between TextBuffers and ScreenBuffers and am wondering if there's a way to get the 'empty' cells in a TextBuffer to be transparent in the same way that empty ScreenBuffer cells are.

From the docs, my understanding was that calling .setEmptyCellAttr() with charTransparency:true would mean that empty cells in the TextBuffer wouldn't overwrite the characters in its destination ScreenBuffer. But as you can see in the top screenshot below, the entire 20x3 block of the TextBuffer is overwriting the dots in the background ScreenBuffer.

I had expected results that look more like the bottom screenshot (i.e., without the surrounding black bars). Is this a bug, or am I just misunderstanding how transparency & blending works between TextBuffers and ScreenBuffers?

terminal-kit-textbuffer-not-blending

function useTextBuffer(){
  // place a textbuffer in the middle of the destination 
  // screenbuffer and set its empty cells to be 
  // transparent for bg and char
  foreground = termkit.TextBuffer.create({
    dst:background,
    x:10,
    y:8,
    width:20,
    height:3
  })
  foreground.setEmptyCellAttr({
      bgTransparency:true, 
      charTransparency:true
  })

  // the message text should be visible, but the surrounding
  // rows and cols of the TextBuffer should(?) be transparent
  foreground.moveTo(2,1)
  foreground.insert('hello textbuffer')
}

function useScreenBuffer(){
  // place a child screenbuffer in the middle of the
  // parent screenbuffer and draw a similar message
  foreground = termkit.ScreenBuffer.create({
    dst:background,
    x:10,
    y:8,
    width:20,
    height:3
  })

  foreground.put({x:1, y:1}, 'hello screenbuffer')
}

var termkit = require( 'terminal-kit' ),
    term = termkit.terminal,
    foreground, background;

// set up the base ScreenBuffer and add one of our two
// child buffers to it then draw everything to the term
background = termkit.ScreenBuffer.create({
  dst:term,
  x:1, 
  y:1,
  width:40,
  height:20,
  noFill:true
})
background.fill({
  char:'·', 
  attr:{color:'white', bgColor:'brightBlue'}
})

useTextBuffer() // or useScreenBuffer()

term.clear()
foreground.draw({blending:true})
background.draw()

grabInput permanently changes the behavior of the term emulator.

After using grabInput({mouse: 'button'}) the default behavior of the mouse events gets swallowed (this is expected) and each mouse action spits stuff into the term (e.g. 0;4;7M, this is not expected and I do not know how to avoid or circumvent it), this doesn't stop even after grabInput(false) and process.exit(), making the term window useless after I ran the script.

I tried this with terminology and gnome-terminal.

Efficient way to erase characters in a specific area?

I'm not sure if this already part of the API and I missed it, but is there any way to erase a specific part of the terminal without moving around other characters?

eg. for example I have this:

0123
5678
9012

And want to have this (erase the two characters in the middle):

0123
5  8
9012

I found a way by doing this:

term.moveTo(2,2);
term.delete(2);
term.insert(2);

But that seems a bit inefficient. Is there a better way?

Add support for 'default' fg/bg colors in ScreenBuffer

In experimenting with the ScreenBuffer object, it seems that even if I don't set an initial 'fill' color, when the draw() method is called and it updates the screen, it defaults to drawing a black background for every character.

For instance, I would have expected these code snippets to result in comparable output:

// directly draw to terminal
var termkit = require( 'terminal-kit' ),
    term = termkit.terminal;

term.clear()
term.moveTo(14,4, 'hello world')
term.moveTo(40, 9)

// indirectly draw via ScreenBuffer
var termkit = require( 'terminal-kit' ),
    term = termkit.terminal,
    ScreenBuffer = termkit.ScreenBuffer;

var screen = ScreenBuffer.create({
    dst:term,
    x:1, y:1,
    width:40,
    height:9
})
term.clear()
screen.put({x:14,y:4}, 'hello world')
screen.draw()

But the results are quite different looking:
termkit-screenbuffer

Is there any way that default or transparent could be added as a bgColor value in ScreenBuffer's attrs arg so that text could be displayed using the terminal's standard color scheme rather than overriding it? Or does this functionality already exist and I'm just misunderstanding how to use it?

"resize" event not working?

I'm trying to get the resize event to work, or simply to get the new terminal height whenever it's resized, but it's not working so far.

I've narrowed it down to this simple script:

var term = require( 'terminal-kit' ).terminal ;

setInterval(function() {
	console.info(term.height);
}, 1000);

term.on('resize', function(width, height) {
	console.info('Resize: ' + width + ', ' + height);
});

This will continuously print the same size, even as I resize the terminal, and the "resize" event is never fired.

If I Ctrl+C the script and start it again, it will then pick up the new terminal size, so it's getting it right but it just never updates once the script starts.

I've tried in ConEmu and the default Windows terminal, both under WSL and DOS but none of these are working. Any idea what could be the issue?

Nested ScreenBuffer

I'm having trouble getting nested ScreenBuffers to work in my account() function. I'm sure I'm just going about it wrong, but could use some direction. I'm simply not finding an example to reference.

The end goal is to have a section (the grey rectangle) that has several pieces of information in different areas that are updated regularly; as shown by the green rectangles. Unfortunately, I'm not able to get those nested ScreenBuffers to show content.

image

Forgive my Photoshop skills, please. Also, the green rectangles will end up not being colored; they'll be grey as well.

Additionally, I'm not sure if I have to fill the ScreenBuffer with spaces to color the background gray. Is there a better way?

Code

const os = require('os');
const pjson = require('../package.json');
const prettyBytes = require('pretty-bytes');
const settings = require('config');
const sprintf = require('sprintf-js').sprintf;
const term = require('terminal-kit').terminal;
const tkit = require('terminal-kit');



function account () {
	let info = sprintf('CPU Cores: %d   |   Free Memory: %s', os.cpus().length, os.freemem());
	let c_justify = parseInt((term.width / 2) - (info.length / 2)) + 1;
	let fill = new Array(term.width).join(' ');
	

	let b_line1 = tkit.ScreenBuffer.create({
		dst: b_account,
		X: 1,
		y: 3,
		width: term.width-2,
		height: 1,
		// blending: true,
		// noFill: true,
	});

	let b_line2 = tkit.ScreenBuffer.create({
		dst: b_account,
		X: 2,
		y: 3,
		width: term.width-2,
		height: 1,
		// blending: true,
		// noFill: true,
	});

	let b_line3 = tkit.ScreenBuffer.create({
		dst: b_account,
		X: 3,
		y: 3,
		width: term.width-2,
		height: 1,
		// blending: true,
		// noFill: true,
	});


	let options = {
		x: 1,
		y: 0,
		wrap: false,
		attr: {
			color: 'black',
			bgColor: 'gray',
		},
	};

	// b_account.put(options, fill);
	b_line1.put(options, fill);
	b_line1.draw();
	b_line2.put(options, fill);
	b_line2.draw();
	b_line3.put(options, fill);
	b_line3.draw();

	options.x = c_justify
	b_account.put(options, info);
	b_account.draw();
}



function footer (bytesReceived) {
	let info = sprintf('CPU Cores: %d   |   Free Memory: %s   |   WebSocket Bytes Received: %d', os.cpus().length, prettyBytes(os.freemem()), parseInt(bytesReceived));
	let c_justify = parseInt((term.width / 2) - (info.length / 2)) + 1;
	let fill = new Array(term.width + 1).join(' ');
	
	let options = {
		x: 0,
		y: 0,
		wrap: false,
		attr: {
			color: 'black',
			bgColor: 'white',
		},
	};

	b_footer.put(options, fill);

	options.x = c_justify
	b_footer.put(options, info);
	b_footer.draw();
}



function header () {
	let options = {
		x: 1,
		y: 0,
		wrap: false,
		attr: {
			color: 'brightYellow',
			bgColor: 'cyan',
			bgTransparency: true,
		},
	};

	b_header.put(options, 'Testing Terminal Kit v%s', pjson.version);

	let node_env = sprintf('W:%d H:%d   |   NODE_ENV: %s', term.width, term.height, process.env.NODE_ENV);
	let r_justify = term.width - (node_env.length + 1);

	options.x = r_justify
	b_header.put(options, node_env);

	b_header.draw();
}


var b_header = undefined;
var b_account = undefined;
var b_footer = undefined;
function load_layout() {
	b_header = tkit.ScreenBuffer.create({
		dst: term,
		X: 1,
		y: 1,
		width: term.width,
		height: 1,
	});


	b_account = tkit.ScreenBuffer.create({
		dst: term,
		X: 1,
		y: 3,
		width: term.width-2,
		height: 3,
		// blending: true,
		// noFill: true,
	});


       // Will add additional sections later.


	b_footer = tkit.ScreenBuffer.create({
		dst: term,
		X: 1,
		y: term.height,
		width: term.width,
		height: 1,
		// blending: true,
		// noFill: true,
	});
}



term.windowTitle('Testing Terminal Kit');

// Clear Screen
term.clear();
term.moveTo(1, 1).bgCyan.brightYellow.eraseLine();
term.eraseDisplayBelow();

// Events
term.on('resize', (width, height) => {
	// console.log('TERM RESIZED:', width, height);
	load_layout();
})


load_layout();
header();
account();
footer();



module.exports = function (input, done) {
	header();
	footer(input.bytesReceived);
}

[Windows] time-out when writing while reading

My expectation is, that when having the following code

'use strict';

const tk = require('terminal-kit').terminal;

tk('TEST\n> ');
tk.inputField({
    history: [],
}, (err, input) => {
    if (err) {
        throw err;
    }
    
    console.log('Your input: ' + input);
});

tk('TEST2\n');

I'd get an output of

TEST
TEST2
> |

with the cursor at the pipe, or at least

TEST
> |
TEST2

But terminal-kit fails with the error

C:\Users\marco_000\tmp>node test.js
TEST
> TEST2
C:\Users\marco_000\tmp\test.js:10
        throw err;
        ^

Error: .getCursorLocation() timed out
    at Terminal.getCursorLocation (C:\Users\marco_000\tmp\node_modules\terminal-kit
\lib\Terminal.js:1118:50)
    at init (C:\Users\marco_000\tmp\node_modules\terminal-kit\lib\inputField.js:198
:8)
    at Terminal.inputField (C:\Users\marco_000\tmp\node_modules\terminal-kit\lib\in
putField.js:840:2)
    at Object.<anonymous> (C:\Users\marco_000\tmp\test.js:6:4)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)

Make newlines set cursor x position to 0

When I output a chunk of text with newlines it looks very odd because the newline doesn't change the x position of the cursor. I don't know if there's a compelling reason not to move the cursor to the beginning of the line on a newline but if so it would be nice to either be able to set an option to do it or somehow manually do it. I would manually search and replace newlines with the right control codes in my output string if I knew what they were but it changes depending on the terminal and you've already built a system to figure all that out.

Hmm how do you show Done in the progress bar

Maybe I'm blind, but some who the example code shows Done when the progress bar reaches 100%. But for some reason when I use the progress bar I don't get that? What triggers this action?

Support gray color

Would be nice to use "gray" instead of "brightBlack". Currently getting TypeError: Cannot read property 'str' of undefined when using term.gray.str('foo').

Funny cursor positions depending on invocation of `singleColumnMenu`

If I invoke a singleColumnMenu like so:

function displayMenu(items) {
  menu = term.singleColumnMenu( items, ( error, response ) => {
    eraseMenu();
    switch (response.selectedIndex) {
      case Menu.MONGO.idx:  { 
         term(' Enter a Mongo Query: ');
         inputField = term.inputField(function( error, input ) { ... });
         break; 
      }
      case Menu.EXIT.idx:   { menu.abort(); process.exit(); }
      default: displayInput(' Enter some text: ');
    }
  });
}

Everything works great like so:

Working...

However, if I move that singleColumnMenu callback into an .on('submit', ..._ block, the following behaviour happens (i.e. inputField is moved to the bottom of the now-erased menu):

Not working

Full code can be found here:

https://gist.github.com/ctataryn/58ed333e4d810073e7b766425889b325

Remove a event listener (off)

I see in the documentation is possible to add a event listener using: term.on('key', fn), when I tried to use: term.off('key', fn) doesn't remove it.

Is possible to unset the event listener? I need in particular for this terminal application the possibility to bind different key handlers in different screens so it will be useful to set/unset the key event listener function.

inputField with singleColumnMenu in auto complete (instead of singleLineMenu)

My app has an inputField with autoCompleteMenu but the options are too long and they are not looking good on a singleLineMenu. As far as I could tell by reading the docs and the source there is no way to configure the type of the menu, right?

I could create a PR to add this option to the inputField config, do you think it is a good idea? There is any other way to change this?

How to catch the keypress

Hi, first of all, compliments for the module.

I'm using term.on( 'key') to get the user keyboard input, but when I press something like ARROW_UP it produces on screen this: ^[[A and until I press enter the on('key') callback is not fired.. so, since I need to simulate the cursor moving when the user press arrow keys how can I do?

term.grabInput( );
term.on( 'key' , function( key , matches , data ) { 
switch ( key )
    {
        case 'UP' : term.up( 1 ) ; break ;
        case 'DOWN' : term.down( 1 ) ; break ;
        case 'LEFT' : term.left( 1 ) ; break ;
        case 'RIGHT' : term.right( 1 ) ; break ;
        case 'CTRL_C' : process.exit() ; break ;
        default:   
            // Echo anything else
            term.noFormat(
                Buffer.isBuffer( data.code ) ?
                    data.code :
                    String.fromCharCode( data.code )
            ) ;
            break ;
    }
});

The example code is from here: http://blog.soulserv.net and (for me) is not working as described.. the arrow keys produces (on screen): ^[[A, ... and until I press enter the key event is not fired

gridMenu error with array not containing string items

e.g.

let array = [1, 2, 3, 4];

term.gridMenu(array,  (error , response) => {
    term( '\n' ).eraseLineAfter.green(
        "#%s selected: %s (%s,%s)\n" ,
        response.selectedIndex ,
        response.selectedText ,
        response.x ,
        response.y
    );
});

Problem in gridMenu.js module - 122 line
I think need throw exception if array not contains string items, or try cast items to string.

I can fix this error

.inputField() features: password and truncate

Hi @cronvel,

I just would like to say, epic work on the module, made my life definitely much easier :).

I would like to give you two suggestions for potential new features :) Basically two things the I missed while working with the module:

  1. A password field that will replace the characters with nothing, or * to hide the typed password
  2. truncate a long ass entry. For example if I have a very long API Key that wraps, it be nice if there was the possibility to say, show only max 10 characters and the rest will be hidden. For example:
  • 2kj4k23j4hkj23h4kjh23[...]
  • 2kj4k23j4hkj23h4kjh23...

Something like this. This way the UI won't brake :)

Other then that, super cool stuff :)

.inputField(): More input control (erase begining of input, erase end of input, move to next/previous word)

I'm trying to implement the CTRL_U and CTRL_K functionality that erases from the cursor to the beginning of the line and from the cursor to the end of the line, respectively. Unfortunately I can't use the actual control codes for this because the control codes are only erasing the text on the screen, not changing the actual text in the buffer. Also, calling term.eraseLineBefore() (which sends the control code) will erase the whole line including the prompt text for the input field.

My next approach was to try to get the total input string length from the input field, along with the cursor position and call backDelete() or delete() for each character until I've erased to the beginning or end of the input string. However, the position returned from the call to inputField.getPosition() is just the cursor position in the terminal, not the position in the input string. And since there is prompt text before it I would have to do a lot more work to subtract the length of the prompt text and figure out if the command is wrapping onto multiple lines and hope I didn't miss something, just so I could hopefully get the right cursor position in the input string.

I think ideally there would be a simple way to set the input value, not just get it. And whether that happens or not it would really be helpful if there was a way to get and set the cursor position in the input string rather than working with the raw terminal coordinates. What are your thoughts? Do you think there is a better way to solve this problem? Or would this be an easy thing to implement?

Multi/Split window support

Hi guys, I am pretty new to terminal kit and its continuing to amaze me. I just wanted to find out if there is any way to have multi/split window UI. I am attaching a sample image of what I am looking for. It has a list/table at the left and content area on the right

Thanks guys
3316428506_a929c7dcbd_o

How to keep a progress bar at the bottom of the terminal?

Hello,

I've been trying to figure out how to create output similar to how Ubuntu's "apt update" and "apt upgrade" commands work - they show a bunch of output of lines of data, and appended to the bottom of the entire terminal is progress bar.

Currently I'm able to create the progress bar and output items all using terminal-kit, except when my progress bar is 'done' it get's overwritten by the next text output. in steps this looks like this in my code:

  1. start progress bar
  2. update progress bar
  3. progress bar finishes
  4. output text of further tasks

Sample Output:
!B audio/Thanks-v1.wav=========>] done
!B audio/outro-v2.wav
!B audio/Outro-V1.wav
!B assets/timecode-2.5min.mp4
!B assets/60-opacity.png

Desired Output:
!B audio/Thanks-v1.wav
!B audio/outro-v2.wav
!B audio/Outro-V1.wav
!B assets/timecode-2.5min.mp4
!B assets/60-opacity.png
( more text output here )
Progress: 100%[======================>] done

I've tried the "moveTo" before writing the next text after a progress bar and I'm not seeing any better results. The progress bar always get's overwritten by the next text output.

My environment is:
Mac OSX El Capitan (10.11.6)
NodeJS 6.5.0
Terminal Kit 1.10.2.

I've been able to build a pretty nice UI in my first usage of this toolkit and it worked really well, so perhaps I've done something wrong. Thanks again for such a great tool!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.