clite.commands.data = function() { clite.commands.load('vi',function(args,env,io) { var stdio = io.include('stdio'); var clite = io.include('clite'); var curses = io.include('curses'); // definitely not dark magic var term = io.include('term'); const VIMODE_VIEW = 0; const VIMODE_CMD = 1; const VIMODE_EDIT = 2; var cmd_buff = ''; var file = null; var mode = VIMODE_VIEW; // 0 view mode, 1 command mode, 2 edit mode var cursor_line = 0; var cursor_col = 0; var cursor_line_real = 0; var cursor_col_real = 0; var changed = false; var num = false; var message = ''; var cols; var rows; var lines = []; var topLine = 0; var bottomLine = 0; function switchMode(m) { if (m == mode) return; switch (m) { case VIMODE_CMD: mode = 1; curses.echo(); curses.move(rows-1,0); curses.printw(':'); cmd_buff = ':'; showAt(topLine); break; case VIMODE_EDIT: mode = 2; curses.noecho(); message = 'INSERT'; showAt(topLine); break; case VIMODE_VIEW: default: mode = 0; cmd_buff = ''; curses.noecho(); showAt(topLine); break; } } function help() { stdio.printf(` vi - Visual text file editor Usage: vi [OPTION] Options: -? Print this help information `); } function calculateBottomLine() { bottomLine = lines.length; var r = rows; var i = lines.length-1; for (; i>-1; i--) { r -= lines[i].rows; if (r<0) i++; if (r <= 0) break; } bottomLine = i; } function drawCursorLine(line) { var cl = 0; var s = -1; var disp = ''; var rows = 0; var done = false; for (var i=0; i cols) { var b = ''; var e = ''; if (s > -1) { b = disp.substring(0,s); e = l.disp.substring(s); }else{ b = disp.substring(0,disp.length-1); e = disp.substring(disp.length-1); } disp = b+'\n'+e; cl = e.length; rows++; s = -1; } switch (line[i]) { case '\t': { if (cl > (cols-4)) { disp += '\n'; cl = 0; rows++; s = -1; break; } s = disp.length; var c = 4-(s%4); for (var j=0; j lines.length) line = lines.length; if (line < 0) line = 0; var start = line; var end = line+rows-2; if (end > lines.length) end = lines.length; curses.clear(); var k = 0; if (num) { for (var i=start; i cols) { var b = ''; var e = ''; if (s > -1) { b = l.disp.substring(0,s); e = l.disp.substring(s); }else{ b = l.disp.substring(0,l.disp.length-1); e = l.disp.substring(l.disp.length-1); } l.disp = b+'\n'+e; cl = e.length; l.rows++; s = -1; } switch (line[i]) { case '\t': { if (cl > (cols-4)) { l.disp += '\n'; cl = 0; l.rows++; s = -1; break; } s = l.disp.length; var c = 4-(s%4); for (var j=0; j 0) { cursor_line--; if (cursor_line <= topLine && topLine > 0) topLine--; showAt(topLine); } } function cursorDn() { if (cursor_line < lines.length-1) { cursor_line++; calculateBottomLine(); if (topLine < bottomLine) { topLine++; } showAt(topLine); } } function cursorLt() { if (cursor_col > 0) cursor_col--; showAt(topLine); } function cursorRt() { if (cursor_col < lines[cursor_line].real.length) cursor_col++; showAt(topLine); } function setLine(str) { lines[cursor_line] = prepLine(str); calculateBottomLine(); changed = true; } function insertLine(str) { var l = prepLine(str); lines.splice(cursor_line+1,0,l); cursor_col = 0; cursorDn(); changed = true; } function input(key) { if (mode == 0) { // view mode //message = ''; switch (key) { case curses.key.KEY_UP: cursorUp(); break; case curses.key.KEY_DOWN: cursorDn(); break; case curses.key.KEY_LEFT: cursorLt(); break; case curses.key.KEY_RIGHT: cursorRt(); break; case 'i': switchMode(VIMODE_EDIT); break; case 'a': cursor_col = lines[cursor_line][0].length; switchMode(VIMODE_EDIT); break; case ':': switchMode(VIMODE_CMD); break; } }else if (mode == 1) { // command mode //message = ''; switch (key) { case curses.key.KEY_ESCAPE: switchMode(VIMODE_VIEW); break; case curses.key.KEY_ENTER: if (!doCommand(cmd_buff)) return; showAt(topLine); cmd_buff = ''; break; case curses.key.KEY_BACKSPACE: if (cmd_buff.length > 0) { cmd_buff = cmd_buff.substring(0,cmd_buff.length-1); showAt(topLine); if (!cmd_buff.length) switchMode(VIMODE_VIEW); } break; default: if (typeof key === 'string' && key.length == 1) cmd_buff+=key; break; } }else{ // 2 edit mode message = 'INSERT'; switch (key) { case curses.key.KEY_ESCAPE: message = ''; switchMode(VIMODE_VIEW); break; case curses.key.KEY_UP: cursorUp(); break; case curses.key.KEY_DOWN: cursorDn(); break; case curses.key.KEY_LEFT: cursorLt(); break; case curses.key.KEY_RIGHT: cursorRt(); break; case curses.key.KEY_BACKSPACE: if (cursor_col > 0) { var l = lines[cursor_line].real; var b = l.substring(0,cursor_col-1); var e = l.substring(cursor_col); setLine(b+e); cursor_col--; showAt(topLine); } break; case curses.key.KEY_ENTER: var l = lines[cursor_line].real; var b = l.substring(0,cursor_col); var e = l.substring(cursor_col); setLine(b); insertLine(e); cursor_col = 0; showAt(topLine); break; case curses.key.KEY_DL: if (cursor_col < lines[cursor_line].real.length) { var l = lines[cursor_line].real; var b = l.substring(0,cursor_col); var e = l.substring(cursor_col+1); setLine(b+e); showAt(topLine); } break; default: if (typeof key === 'string' && key.length == 1) { var l = lines[cursor_line].real; var b = l.substring(0,cursor_col); var e = l.substring(cursor_col); setLine(b+key+e); cursor_col++; showAt(topLine); } } } curses.getch(input); } function main(argc,argv) { for (var i=1; i