From f4dc0e7d9c584d8d1598faf8bdbba410758af7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 3 Apr 2016 05:23:26 +0800 Subject: [PATCH 1/3] Some placeholder commands, working substitution --- botanjs/src/Components/Vim/Actions/DELETE.js | 2 +- .../Components/Vim/Actions/EDITOR_COMMAND.js | 165 +++++++++++ botanjs/src/Components/Vim/Actions/FIND.js | 63 +++-- botanjs/src/Components/Vim/Actions/INSERT.js | 2 +- .../src/Components/Vim/Actions/PRINT_HEX.js | 2 +- botanjs/src/Components/Vim/Actions/PUT.js | 2 +- botanjs/src/Components/Vim/Actions/REDO.js | 2 +- botanjs/src/Components/Vim/Actions/REPLACE.js | 260 ++++++++++++++++++ botanjs/src/Components/Vim/Actions/UNDO.js | 2 +- botanjs/src/Components/Vim/Actions/VISUAL.js | 6 +- botanjs/src/Components/Vim/Actions/YANK.js | 2 +- botanjs/src/Components/Vim/Controls.js | 21 ++ botanjs/src/Components/Vim/Cursor.js | 12 +- botanjs/src/Components/Vim/Ex/Command.js | 6 +- botanjs/src/Components/Vim/LineFeeder.js | 64 ++--- botanjs/src/Components/Vim/StatusBar.js | 2 + botanjs/src/Components/Vim/VimArea.js | 2 +- botanjs/src/Components/Vim/_this.js | 14 +- botanjs/src/externs/Components.Vim.Actions.js | 8 + 19 files changed, 573 insertions(+), 64 deletions(-) create mode 100644 botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js create mode 100644 botanjs/src/Components/Vim/Actions/REPLACE.js create mode 100644 botanjs/src/externs/Components.Vim.Actions.js diff --git a/botanjs/src/Components/Vim/Actions/DELETE.js b/botanjs/src/Components/Vim/Actions/DELETE.js index 1683c32..30cb180 100644 --- a/botanjs/src/Components/Vim/Actions/DELETE.js +++ b/botanjs/src/Components/Vim/Actions/DELETE.js @@ -14,7 +14,7 @@ var occurence = __import( "System.utils.Perf.CountSubstr" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var DELETE = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js b/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js new file mode 100644 index 0000000..1b4450d --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js @@ -0,0 +1,165 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + var VimError = __import( "Components.Vim.Error" ); + + var CMD_RANGE = 0; + var CMD_TYPE = 1; + var CMD_ARGS = 2; + var CMD_ERR = 3; + + var ParseCommand = function( pattern ) + { + var i = 1; + + var range = ""; + var out = []; + + if( ".$%".indexOf( pattern[ i ] ) != -1 ) + { + range = pattern[ i ++ ]; + } + else + { + for( ; "0123456789".indexOf( pattern[ i ] ) != -1; i ++ ) + { + range += pattern[ i ]; + } + } + + var command = ""; + + if( "/?".indexOf( pattern[ i ] ) != -1 ) + { + command = pattern[ i ]; + } + else + { + var cmdReg = /\w/g; + for( var j = pattern[ i ]; j = pattern[ i ]; i ++ ) + { + if( j.match( cmdReg ) ) + { + command += j; + } + else break; + } + } + + var allowRange = false; + switch( command ) + { + case "s": + case "su": + case "substitute": + allowRange = true; + out[ CMD_TYPE ] = "REPLACE"; + break; + case "/": + allowRange = true; + out[ CMD_TYPE ] = "FIND"; + break; + + case "buffers": + case "ls": + out[ CMD_TYPE ] = "BUFFERS"; + + break; + case "w": + case "write": + out[ CMD_TYPE ] = "WRITE"; + break; + case "q": + case "quit": + out[ CMD_TYPE ] = "QUIT"; + break; + case "register": + case "registers": + out[ CMD_TYPE ] = "REGISTERS"; + break; + case "ver": + case "version": + out[ CMD_TYPE ] = "VERSION"; + break; + case "h": + case "help": + out[ CMD_TYPE ] = "HELP"; + break; + } + + if( range !== "" ) + { + if( allowRange ) out[ CMD_RANGE ] = range; + else out[ CMD_ERR ] = VimError( "E481" ); + } + + out[ CMD_ARGS ] = pattern.slice( i ); + return out; + }; + + /** @type {Components.Vim.IAction} */ + var EDITOR_COMMAND = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + EDITOR_COMMAND.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + EDITOR_COMMAND.prototype.handler = function( e, p ) + { + e.preventDefault(); + + var cmd = ParseCommand( p ); + + if( cmd[ CMD_ERR ] ) + { + this.__msg = cmd[ CMD_ERR ]; + return true; + } + else if( !cmd[ CMD_TYPE ] ) + { + this.__msg = VimError( "E492", p.slice( 1 ).join( "" ) ); + return true; + } + + try + { + ns[ NS_INVOKE ]( cmd[ CMD_TYPE ] ); + } + catch( ex ) + { + this.__msg = VimError( "TODO", cmd[ CMD_TYPE ] ); + return true; + } + + try + { + this.__cursor.openRunAction( + cmd[ CMD_TYPE ], e, cmd[ CMD_ARGS ], cmd[ CMD_RANGE ] + ); + this.__msg = this.__cursor.message; + } + catch( ex ) + { + debug.Error( ex ); + } + + return true; + }; + + EDITOR_COMMAND.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "EDITOR_COMMAND", EDITOR_COMMAND ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/FIND.js b/botanjs/src/Components/Vim/Actions/FIND.js index c94f4f0..86db51d 100644 --- a/botanjs/src/Components/Vim/Actions/FIND.js +++ b/botanjs/src/Components/Vim/Actions/FIND.js @@ -4,10 +4,11 @@ /** @type {System.Debug} */ var debug = __import( "System.Debug" ); + var VimError = __import( "Components.Vim.Error" ); var Mesg = __import( "Components.Vim.Message" ); // Private static - var PATTERN = ""; + var PATTERN = []; var ParsePattern = function( pattern ) { @@ -23,28 +24,27 @@ break; case "\\": var tok = pattern[ ++ i ]; - debug.Error( "Unknown escaped token: " + tok ); - ++ i; + if( "nrts.[]()^".indexOf( tok ) != -1 ) + { + parsed += "\\" + tok; + } + else + { + throw new Error( "Missing token impl: \"" + tok + "\"" ); + } + break; default: parsed += pattern[ i ]; } } - var RegEx = null; - - try - { - var RegEx = new RegExp( parsed, "gm" ); - } - catch( ex ) - { - debug.Error( ex ); - } + // The root bracket as back ref 0 + var RegEx = new RegExp( "(" + parsed + ")", "g" ); return RegEx; }; - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var FIND = function( Cursor ) { /** @type {Components.Vim.Cursor} */ @@ -62,9 +62,37 @@ { e.preventDefault(); - if( p ) PATTERN = p; + if( p ) + { + if( p.length < 2 ) + { + if( PATTERN.length < 1 ) + { + this.__msg = VimError( "E35" ); + return true; + } + else p = PATTERN; + } - var search = ParsePattern( PATTERN ); + PATTERN = p; + } + + if( PATTERN.length < 1 ) + { + this.__msg = VimError( "E35" ); + return true; + } + + var search; + try + { + search = ParsePattern( PATTERN ); + } + catch( ex ) + { + this.__msg = VimError( "EX1", ex.message ); + return true; + } var content = this.__cursor.feeder.content; @@ -111,6 +139,7 @@ if( Hit == undefined ) { + this.__msg = VimError( "E486", PATTERN.slice( 1 ).join( "" ) ); } else { @@ -123,5 +152,7 @@ return this.__msg; }; + __static_method( FIND, "Pattern", ParsePattern ); + ns[ NS_EXPORT ]( EX_CLASS, "FIND", FIND ); })(); diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js index f119a30..759aec6 100644 --- a/botanjs/src/Components/Vim/Actions/INSERT.js +++ b/botanjs/src/Components/Vim/Actions/INSERT.js @@ -23,7 +23,7 @@ } }; - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var INSERT = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/PRINT_HEX.js b/botanjs/src/Components/Vim/Actions/PRINT_HEX.js index 185bb28..e55c77a 100644 --- a/botanjs/src/Components/Vim/Actions/PRINT_HEX.js +++ b/botanjs/src/Components/Vim/Actions/PRINT_HEX.js @@ -4,7 +4,7 @@ /** @type {System.Debug} */ var debug = __import( "System.Debug" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var PRINT_HEX = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js index e58c9f9..3152444 100644 --- a/botanjs/src/Components/Vim/Actions/PUT.js +++ b/botanjs/src/Components/Vim/Actions/PUT.js @@ -9,7 +9,7 @@ var Mesg = __import( "Components.Vim.Message" ); var occurence = __import( "System.utils.Perf.CountSubstr" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var PUT = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/REDO.js b/botanjs/src/Components/Vim/Actions/REDO.js index da241d9..43ca88b 100644 --- a/botanjs/src/Components/Vim/Actions/REDO.js +++ b/botanjs/src/Components/Vim/Actions/REDO.js @@ -3,7 +3,7 @@ var Mesg = __import( "Components.Vim.Message" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var REDO = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/REPLACE.js b/botanjs/src/Components/Vim/Actions/REPLACE.js new file mode 100644 index 0000000..1acf895 --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/REPLACE.js @@ -0,0 +1,260 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + /** @type {Components.Vim.State.Stack} */ + var Stack = __import( "Components.Vim.State.Stack" ); + + var VimError = __import( "Components.Vim.Error" ); + var Mesg = __import( "Components.Vim.Message" ); + + var occurence = __import( "System.utils.Perf.CountSubstr" ); + + /** @type {Components.Vim.Actions.FIND} */ + var FIND = ns[ NS_INVOKE ]( "FIND" ); + + var REPL_BEFORE = 0; + var REPL_OFFSET = 1; + var REPL_LENGTH = 2; + + var ParseReplace = function( repl ) + { + var parsed = ""; + var l = repl.length; + var rStack = [ "" ] + + for( var i = 1; i < l; i ++ ) + { + switch( repl[ i ] ) + { + case "^I": + parsed += "\t"; + break; + + case "\\": + i ++; + + var j = repl[ i ]; + if( "$nrt\\".indexOf( j ) != -1 ) + { + parsed += JSON.parse( "\"\\" + j + "\"" ); + break; + } + + // 9 is shifted by 0 + // which I think is more important + if( "012345678".indexOf( j ) != -1 ) + { + rStack.push( parsed.length ); + parsed += j; + } + else if( j == "9" ) + { + throw new Error( "Back ref 9 is reserved for back ref 0" ); + } + else + { + throw new Error( "Missing token impl: \"" + tok + "\"" ); + } + break; + + default: + parsed += repl[ i ]; + } + } + + rStack[0] = parsed; + return rStack; + }; + + /** @type {Components.Vim.IAction} */ + var REPLACE = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + + this.__repl = ""; + this.__replLen = 0; + this.__replCallback = this.__replCallback.bind( this ); + + this.__pOffset = 0; + + this.__replacedGroups = []; + + Cursor.suppressEvent(); + }; + + REPLACE.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + REPLACE.prototype.handler = function( e, p, range ) + { + e.preventDefault(); + + var search; + var spattern; + + try + { + var slash = p.indexOf( "/", 0 ); + var secSlash = p.indexOf( "/", slash + 1 ); + if( slash == -1 ) + { + this.__msg = VimError( "MISSING_FEATURE", "REPLACE %s" ); + return true; + } + else if( secSlash == -1 ) + { + search = FIND.Pattern( p ); + spattern = p; + } + else + { + spattern = p.slice( slash, secSlash ); + search = FIND.Pattern( spattern ); + + var thdSlash = p.indexOf( "/", secSlash + 1 ); + if( thdSlash == -1 ) + { + this.__repl = ParseReplace( p.slice( secSlash ) ); + } + else + { + this.__repl = ParseReplace( p.slice( secSlash, thdSlash ) ); + } + + this.__replLen = this.__repl[0].length; + } + } + catch( ex ) + { + this.__msg = VimError( "EX1", ex.message ); + return true; + } + + debug.Info( "Replace: " + search + ", [ " + this.__repl + " ]" ); + + var feeder = this.__cursor.feeder; + var content = feeder.content.slice( 0, -1 ) + .replace( search, this.__replCallback ) + "\n"; + + if( !this.__replacedGroups.length ) + { + this.__msg = VimError( "E486", spattern.join( "" ) ); + } + + feeder.content = content; + + // Record this step for UNDO / REDO + this.__rec(); + + /* Move the cursor to last replaced line + var cur = this.__cursor; + var p = cur.aPos; + */ + + feeder.pan(); + feeder.softReset(); + + return true; + }; + + REPLACE.prototype.__replCallback = function() + { + var match = arguments[0]; + var backRefs = Array.prototype.slice.call( arguments, 1, -2 ); + + var offset = this.__pOffset + arguments[ arguments.length - 2 ]; + + var replacedStr = ""; + var replCand = this.__repl[0]; + + for( var i = 0; i < this.__replLen; i ++ ) + { + var j = this.__repl.indexOf( i, 1 ); + if( j == -1 ) + { + replacedStr += replCand[ i ]; + } + else + { + replacedStr += backRefs[ replCand[ this.__repl[ j ] ] ]; + } + } + + var rLen = replacedStr.length; + this.__pOffset += rLen - match.length; + + var ReplObj = []; + ReplObj[ REPL_BEFORE ] = match; + ReplObj[ REPL_OFFSET ] = offset; + ReplObj[ REPL_LENGTH ] = rLen; + + this.__replacedGroups.push( ReplObj ); + + return replacedStr; + }; + + REPLACE.prototype.__rec = function() + { + var stack = new Stack(); + + var reGroups = this.__replacedGroups; + var l = reGroups.length; + var cur = this.__cursor; + var feeder = cur.feeder; + + stack.store( function() + { + var cont = feeder.content; + var newCont = ""; + var st = 0; + + var curStart = -1; + for( var i = 0; i < l; i ++ ) + { + var grp = reGroups[ i ]; + + var RO = grp[ REPL_OFFSET ]; + var RL = grp[ REPL_LENGTH ]; + var RB = grp[ REPL_BEFORE ]; + + var NRL = RB.length; + newCont += cont.substring( st, RO ) + RB; + + st = grp[ REPL_OFFSET ] + RL; + + grp[ REPL_BEFORE ] = cont.substr( RO, RL ); + + grp[ REPL_OFFSET ] = newCont.length - NRL; + grp[ REPL_LENGTH ] = NRL; + + if( curStart == -1 ) + { + curStart = RO; + } + } + + newCont += cont.substring( st ); + + feeder.content = newCont; + cur.moveTo( curStart ); + feeder.pan(); + + } ); + + cur.rec.record( stack ); + }; + + REPLACE.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "REPLACE", REPLACE ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/UNDO.js b/botanjs/src/Components/Vim/Actions/UNDO.js index 0e47a00..6f81f52 100644 --- a/botanjs/src/Components/Vim/Actions/UNDO.js +++ b/botanjs/src/Components/Vim/Actions/UNDO.js @@ -3,7 +3,7 @@ var Mesg = __import( "Components.Vim.Message" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var UNDO = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js index 6d32caa..bd9085d 100644 --- a/botanjs/src/Components/Vim/Actions/VISUAL.js +++ b/botanjs/src/Components/Vim/Actions/VISUAL.js @@ -6,12 +6,12 @@ var Mesg = __import( "Components.Vim.Message" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var YANK = ns[ NS_INVOKE ]( "YANK" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var DELETE = ns[ NS_INVOKE ]( "DELETE" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var VISUAL = function( Cursor ) { this.__reset( Cursor ); diff --git a/botanjs/src/Components/Vim/Actions/YANK.js b/botanjs/src/Components/Vim/Actions/YANK.js index 12f7a5c..86ba222 100644 --- a/botanjs/src/Components/Vim/Actions/YANK.js +++ b/botanjs/src/Components/Vim/Actions/YANK.js @@ -9,7 +9,7 @@ var occurence = __import( "System.utils.Perf.CountSubstr" ); - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var YANK = function( Cursor ) { /** @type {Components.Vim.Cursor} */ diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js index 19c76bd..b52b7c2 100644 --- a/botanjs/src/Components/Vim/Controls.js +++ b/botanjs/src/Components/Vim/Controls.js @@ -27,6 +27,8 @@ var _0 = 48; var _1 = 49; var _2 = 50; var _3 = 51; var _4 = 52; var _5 = 53; var _6 = 54; var _7 = 55; var _8 = 56; var _9 = 57; + var SEMI_COLON = 59; + var A = 65; var B = 66; var C = 67; var D = 68; var E = 69; var F = 70; var G = 71; var H = 72; var I = 73; var J = 74; var K = 75; var L = 76; var M = 77; var N = 78; var O = 79; @@ -203,6 +205,14 @@ ccur.openAction( "INSERT" ); break; + case S: // Delete Char and start insert + if( ccur.getLine().content != "" ) + { + ccur.openRunAction( "DELETE", e, ccur.aPos ); + } + ccur.openAction( "INSERT" ); + break; + case SHIFT + O: // new line before insert ccur.lineStart(); ccur.openAction( "INSERT" ); @@ -263,6 +273,11 @@ ccur.openAction( "VISUAL_LINE" ); break; + case SHIFT + SEMI_COLON: // ":" Command line + this.__divedCCmd = new ExCommand( ccur, ":" ); + this.__divedCCmd.handler( e ); + break; + case F1: // F1, help break; default: @@ -564,6 +579,12 @@ { this.__e = e; + // KeyCode HotFix + if( e.key == ";" || e.key == ":" ) + { + SEMI_COLON = e.keyCode; + } + var c = this.__e.keyCode; this.__escape = c == ESC || ( e.ctrlKey && c == C ); diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js index bd1967d..2fd9833 100644 --- a/botanjs/src/Components/Vim/Cursor.js +++ b/botanjs/src/Components/Vim/Cursor.js @@ -42,6 +42,13 @@ var l = c.Y + d; var i = c.Y; + if( !line ) + { + line = c.feeder.firstBuffer; + i = 0; + l = d; + } + // First line ( visual ) does not count if( line != c.feeder.firstBuffer ) i --; @@ -396,11 +403,12 @@ }; // Open, Run, then close an action - Cursor.prototype.openRunAction = function( name, e, arg1 ) + Cursor.prototype.openRunAction = function( name, e, arg1, arg2, arg3, arg4, arg5 ) { + debug.Info( "OpenRunAction: " + name ); /** @type {Components.Vim.IAction} */ var action = new (Actions[ name ])( this ); - action.handler( e, arg1 ); + action.handler( e, arg1, arg2, arg3, arg4, arg5 ); this.__pulseMsg = action.getMessage(); action.dispose(); diff --git a/botanjs/src/Components/Vim/Ex/Command.js b/botanjs/src/Components/Vim/Ex/Command.js index d3bfe05..45fdb74 100644 --- a/botanjs/src/Components/Vim/Ex/Command.js +++ b/botanjs/src/Components/Vim/Ex/Command.js @@ -19,7 +19,7 @@ , ":" : Perf.uuid }; - /** @type {Components.Vim.Cursor.IAction} */ + /** @type {Components.Vim.IAction} */ var Command = function( Cursor, Mode ) { var _self = this; @@ -216,9 +216,13 @@ case "/": action = "FIND"; break; + case ":": + action = "EDITOR_COMMAND"; + break; } var cur = this.__cursor; + cur.suppressEvent(); this.__cursor.openRunAction( action, e, this.__command.slice() ); cur.unsuppressEvent(); diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js index 2ead9a0..ee9f881 100644 --- a/botanjs/src/Components/Vim/LineFeeder.js +++ b/botanjs/src/Components/Vim/LineFeeder.js @@ -67,46 +67,46 @@ : function( line ) { return !line.placeholder; } ; - this.__render = function( line, steps ) - { - var display = ( line == undefined ? "" : line ) + ""; - - var atSpace = false; - - for( var i = 0; - line && i < steps && ( line = line.next ) && placeholdCond( line ); - i ++ ) + this.__render = function( line, steps ) { - if( atSpace || ( line.br && steps < ( i + line.visualLines.length ) ) ) + var display = ( line == undefined ? "" : line ) + ""; + + var atSpace = false; + + for( var i = 0; + line && i < steps && ( line = line.next ) && placeholdCond( line ); + i ++ ) { - if( !atSpace ) _self.__clseLine = line; - atSpace = true; - display += "\n@"; - continue; + if( atSpace || ( line.br && steps < ( i + line.visualLines.length ) ) ) + { + if( !atSpace ) _self.__clseLine = line; + atSpace = true; + display += "\n@"; + continue; + } + + display += "\n" + line; } - display += "\n" + line; - } + return display; + }; - return display; - }; - - this.__softRender = function() - { - var line = _self.lineBuffers[ _self.__rStart ]; - var steps = _self.__rLength + 1; - - for( var i = 0; - line && i < steps && ( line = line.next ) && placeholdCond( line ); - i ++ ) + this.__softRender = function() { - if( line.br && steps < ( i + line.visualLines.length ) ) + var line = _self.lineBuffers[ _self.__rStart ]; + var steps = _self.__rLength + 1; + + for( var i = 0; + line && i < steps && ( line = line.next ) && placeholdCond( line ); + i ++ ) { - _self.__clseLine = line; - break; + if( line.br && steps < ( i + line.visualLines.length ) ) + { + _self.__clseLine = line; + break; + } } - } - }; + }; } Feeder.prototype.render = function( start, length ) diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js index 81af357..c524b12 100644 --- a/botanjs/src/Components/Vim/StatusBar.js +++ b/botanjs/src/Components/Vim/StatusBar.js @@ -36,6 +36,8 @@ text = text(); if( text == undefined || text === "" ) continue; + if( i == 0 && l <= text.length ) return text; + display += text.substr( 0, avail ); i = display.length; } diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js index ee76302..f00d1d2 100644 --- a/botanjs/src/Components/Vim/VimArea.js +++ b/botanjs/src/Components/Vim/VimArea.js @@ -125,7 +125,7 @@ var sLine = sfeeder.linesOccupied; element.value = - cfeeder.render( 0, r - sLine ) + cfeeder.render( sLine - 1, r - sLine ) + "\n" + sfeeder.render( 0, sLine < r ? sLine : r ); _self.__blink = false; diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js index 345a882..f97d14a 100644 --- a/botanjs/src/Components/Vim/_this.js +++ b/botanjs/src/Components/Vim/_this.js @@ -24,10 +24,20 @@ , "SEARCH_HIT_BOTTOM": "search hit BOTTOM, continuing at TOP" , "SEARCH_HIT_TOP": "search hit TOP, continuing at BOTTOM" + , "REPLACE": "%1 substitution(s) on %2 line(s)" }; var errors = { - "E486": "E486: Pattern not found: %1" + "E35": "No previous regular expression" + , "E481": "No range allowed" + , "E492": "Not an editor command: %1" + , "E486": "Pattern not found: %1" + + // EXtended Errors + , "EX1": "Pattern Error( %1 )" + + , "TODO": "%1 is not implemented yet" + , "MISSING_FEATURE": "Sorry, I thought this command wasn't useful enough to implement. Please file a feature request titled \"Implement %1\" in github if you think this is important." }; var GetString = function( arr, key, restArgs ) @@ -50,7 +60,7 @@ var Error = function( key ) { var restArgs = Array.prototype.slice.call( arguments, 1 ); - return GetString( errors, key, restArgs ); + return key + ": " + GetString( errors, key, restArgs ); }; var bAudio = new Audio( diff --git a/botanjs/src/externs/Components.Vim.Actions.js b/botanjs/src/externs/Components.Vim.Actions.js new file mode 100644 index 0000000..af2f963 --- /dev/null +++ b/botanjs/src/externs/Components.Vim.Actions.js @@ -0,0 +1,8 @@ +/** @type Object */ +Components.Vim.Actions = {}; + +/** @type constructor */ +Components.Vim.Actions.FIND = function(){}; + +/** @type Function */ +Components.Vim.Actions.FIND.Pattern; From 813cbc949390168f63ddb0e9a472626b0581b208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 3 Apr 2016 07:48:28 +0800 Subject: [PATCH 2/3] Assign Version Number 1.0.0b --- botanjs/src/_this.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/botanjs/src/_this.js b/botanjs/src/_this.js index 18a7c10..5152227 100644 --- a/botanjs/src/_this.js +++ b/botanjs/src/_this.js @@ -1,3 +1,4 @@ +var BOTANJS_VERSION = "1.0.0b"; /*{{{ Shorthand Functions */ var __extends = function( obj, target ) { obj.prototype = Object.create( target.prototype ); @@ -369,7 +370,7 @@ __import = __import || function( ns, noCache ) /* End Import operator }}}*/ window["BotanJS"] = {}; -window["BotanJS"]["version"] = "0.2"; +window["BotanJS"]["version"] = BOTANJS_VERSION; window["BotanJS"]["codename"] = "Botanical framework.js"; window["BotanJS"]["import"] = function( p ) { From be1fc29d392d9d51a63ec6030e26ae6d69ca607d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 3 Apr 2016 07:50:19 +0800 Subject: [PATCH 3/3] Various basic editor commands --- botanjs/src/Components/Vim/Actions/BUFFERS.js | 78 +++++++++++++++++++ .../Components/Vim/Actions/EDITOR_COMMAND.js | 1 - botanjs/src/Components/Vim/Actions/QUIT.js | 60 ++++++++++++++ .../src/Components/Vim/Actions/REGISTERS.js | 64 +++++++++++++++ botanjs/src/Components/Vim/Actions/VERSION.js | 58 ++++++++++++++ botanjs/src/Components/Vim/Actions/WRITE.js | 49 ++++++++++++ botanjs/src/Components/Vim/LineFeeder.js | 1 - botanjs/src/Components/Vim/State/Recorder.js | 10 +++ botanjs/src/Components/Vim/VimArea.js | 75 ++++++++++++++---- botanjs/src/Components/Vim/_this.js | 5 +- .../externs/Components.Vim.State.Recorder.js | 5 ++ botanjs/src/externs/Components.Vim.VimArea.js | 10 ++- 12 files changed, 394 insertions(+), 22 deletions(-) create mode 100644 botanjs/src/Components/Vim/Actions/BUFFERS.js create mode 100644 botanjs/src/Components/Vim/Actions/QUIT.js create mode 100644 botanjs/src/Components/Vim/Actions/REGISTERS.js create mode 100644 botanjs/src/Components/Vim/Actions/VERSION.js create mode 100644 botanjs/src/Components/Vim/Actions/WRITE.js diff --git a/botanjs/src/Components/Vim/Actions/BUFFERS.js b/botanjs/src/Components/Vim/Actions/BUFFERS.js new file mode 100644 index 0000000..e02dc78 --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/BUFFERS.js @@ -0,0 +1,78 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + /** @type {Dandelion} */ + var Dand = __import( "Dandelion" ); + + var Mesg = __import( "Components.Vim.Message" ); + + var occurance = __import( "System.utils.Perf.CountSubstr" ); + + var shadowImport = __import; + + var ESCAPE = function( reg ) + { + var str = reg.toString(); + return str.replace( "\t", "^I" ).replace( "\n", "^J" ); + }; + + /** @type {Components.Vim.IAction} */ + var BUFFERS = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + BUFFERS.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + BUFFERS.prototype.handler = function( e, p ) + { + e.preventDefault(); + + var areas = Dand.tag( "textarea" ); + + var cur = this.__cursor; + var Vim = cur.Vim; + var Insts = VimArea.Instances; + + + var msg = ":buffers"; + + for( var i in Insts ) + { + /** @type {Components.Vim.VimArea} */ + var inst = Insts[ i ]; + + var b = inst.index + " "; + var icur = inst.contentFeeder.cursor; + b += ( inst == Vim ? "%a" : " " ) + " "; + b += ( icur.rec.changed ? "+" : " " ) + " "; + + b += "\"" + inst.stage.element.id + "\"" + " line " + ( icur.getLine().lineNum + 1 ); + + + msg += "\n " + b; + } + + var lastLine = Mesg( "WAIT_FOR_INPUT" ); + + var l = this.__cursor.feeder.firstBuffer.cols; + for( var i = msg.length; i < l; i ++ ) msg += " "; + + this.__msg = msg + "\n" + lastLine; + }; + + BUFFERS.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "BUFFERS", BUFFERS ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js b/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js index 1b4450d..d4de6dd 100644 --- a/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js +++ b/botanjs/src/Components/Vim/Actions/EDITOR_COMMAND.js @@ -66,7 +66,6 @@ case "buffers": case "ls": out[ CMD_TYPE ] = "BUFFERS"; - break; case "w": case "write": diff --git a/botanjs/src/Components/Vim/Actions/QUIT.js b/botanjs/src/Components/Vim/Actions/QUIT.js new file mode 100644 index 0000000..a32631d --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/QUIT.js @@ -0,0 +1,60 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + var VimError = __import( "Components.Vim.Error" ); + + var occurance = __import( "System.utils.Perf.CountSubstr" ); + + var ESCAPE = function( reg ) + { + var str = reg.toString(); + return str.replace( "\t", "^I" ).replace( "\n", "^J" ); + }; + + /** @type {Components.Vim.IAction} */ + var QUIT = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + QUIT.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + QUIT.prototype.handler = function( e, p ) + { + e.preventDefault(); + + var cur = this.__cursor; + var Vim = cur.Vim; + + if( cur.rec.changed ) + { + var msg = VimError( "E37" ); + + var l = this.__cursor.feeder.firstBuffer.cols; + for( var i = msg.length; i < l; i ++ ) msg += " "; + + this.__msg = msg; + } + else + { + Vim.dispose(); + return true; + } + }; + + QUIT.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "QUIT", QUIT ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/REGISTERS.js b/botanjs/src/Components/Vim/Actions/REGISTERS.js new file mode 100644 index 0000000..48f19d0 --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/REGISTERS.js @@ -0,0 +1,64 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + var VimError = __import( "Components.Vim.Error" ); + var Mesg = __import( "Components.Vim.Message" ); + + var ESCAPE = function( reg ) + { + var str = reg.toString(); + return str.replace( "\t", "^I" ).replace( "\n", "^J" ); + }; + + /** @type {Components.Vim.IAction} */ + var REGISTERS = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + REGISTERS.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + REGISTERS.prototype.handler = function( e, p ) + { + e.preventDefault(); + + /** @type {Components.Vim.State.Registers} */ + var reg = e.target.registers; + + var msg = ":register"; + msg += "\n" + Mesg( "REGISTERS" ); + + var regs = "\"0123456789-.:%/="; + for( var i = 0, j = regs[ i ]; j != undefined; i ++, j = regs[ i ] ) + { + var r = reg.get( j ); + if( r ) + { + msg += "\n\"" + j + " " + ESCAPE( r ); + } + } + + var lastLine = Mesg( "WAIT_FOR_INPUT" ); + + var l = this.__cursor.feeder.firstBuffer.cols; + for( var i = msg.length; i < l; i ++ ) msg += " "; + + this.__msg = msg + "\n" + lastLine; + }; + + REGISTERS.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "REGISTERS", REGISTERS ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/VERSION.js b/botanjs/src/Components/Vim/Actions/VERSION.js new file mode 100644 index 0000000..e87dde4 --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/VERSION.js @@ -0,0 +1,58 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + var VimError = __import( "Components.Vim.Error" ); + var Mesg = __import( "Components.Vim.Message" ); + + var ESCAPE = function( reg ) + { + var str = reg.toString(); + return str.replace( "\t", "^I" ).replace( "\n", "^J" ); + }; + + /** @type {Components.Vim.IAction} */ + var VERSION = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + VERSION.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + VERSION.prototype.handler = function( e, p ) + { + e.preventDefault(); + + /** @type {Components.Vim.State.Registers} */ + var reg = e.target.registers; + + var msg = ":version"; + msg += "\nVim;Re - Vim; Reverse Engineered for textarea v" + VIMRE_VERSION; + msg += "\n + BotanJS - v" + BOTANJS_VERSION; + msg += "\nProject home - https://github.com/tgckpg/BotanJS-vim"; + msg += "\n by \u659F\u914C\u9D6C\u5144 (penguin) - https://blog.astropenguin.net/"; + msg += "\n"; + + var lastLine = Mesg( "WAIT_FOR_INPUT" ); + + var l = this.__cursor.feeder.firstBuffer.cols; + for( var i = msg.length; i < l; i ++ ) msg += " "; + + this.__msg = msg + "\n" + lastLine; + }; + + VERSION.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "VERSION", VERSION ); +})(); diff --git a/botanjs/src/Components/Vim/Actions/WRITE.js b/botanjs/src/Components/Vim/Actions/WRITE.js new file mode 100644 index 0000000..e961735 --- /dev/null +++ b/botanjs/src/Components/Vim/Actions/WRITE.js @@ -0,0 +1,49 @@ +(function(){ + var ns = __namespace( "Components.Vim.Actions" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + + var Mesg = __import( "Components.Vim.Message" ); + + var occurance = __import( "System.utils.Perf.CountSubstr" ); + + /** @type {Components.Vim.IAction} */ + var WRITE = function( Cursor ) + { + /** @type {Components.Vim.Cursor} */ + this.__cursor = Cursor; + this.__msg = ""; + Cursor.suppressEvent(); + }; + + WRITE.prototype.dispose = function() + { + this.__cursor.unsuppressEvent(); + }; + + WRITE.prototype.handler = function( e, p ) + { + e.preventDefault(); + + var cur = this.__cursor; + var Vim = cur.Vim; + Vim.content = cur.feeder.content.slice( 0, -1 ); + + var msg = Mesg( "WRITE", Vim.stage.element.id, occurance( Vim.content, "\n" ), Vim.content.length ); + + cur.rec.save(); + + var l = this.__cursor.feeder.firstBuffer.cols; + for( var i = msg.length; i < l; i ++ ) msg += " "; + + this.__msg = msg; + }; + + WRITE.prototype.getMessage = function() + { + return this.__msg; + }; + + ns[ NS_EXPORT ]( EX_CLASS, "WRITE", WRITE ); +})(); diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js index ee9f881..07a2bec 100644 --- a/botanjs/src/Components/Vim/LineFeeder.js +++ b/botanjs/src/Components/Vim/LineFeeder.js @@ -245,7 +245,6 @@ } } - return pos; } ); diff --git a/botanjs/src/Components/Vim/State/Recorder.js b/botanjs/src/Components/Vim/State/Recorder.js index 8e095f4..b95a775 100644 --- a/botanjs/src/Components/Vim/State/Recorder.js +++ b/botanjs/src/Components/Vim/State/Recorder.js @@ -7,6 +7,7 @@ this.__stacks = []; this.__i = 0; this.__j = 0; + this.__saved = 0; }; Recorder.prototype.undo = function() @@ -31,6 +32,11 @@ return null; }; + Recorder.prototype.save = function() + { + this.__saved = this.__i; + }; + Recorder.prototype.record = function( StateObj ) { this.__steps[ this.__i ++ ] = StateObj; @@ -41,5 +47,9 @@ StateObj.id = this.__j; }; + __readOnly( Recorder.prototype, "changed", function() { + return this.__saved != this.__i; + } ); + ns[ NS_EXPORT ]( EX_CLASS, "Recorder", Recorder ); })(); diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js index f00d1d2..3614809 100644 --- a/botanjs/src/Components/Vim/VimArea.js +++ b/botanjs/src/Components/Vim/VimArea.js @@ -2,18 +2,20 @@ var ns = __namespace( "Components.Vim" ); /** @type {Dandelion.IDOMElement} */ - var IDOMElement = __import( "Dandelion.IDOMElement" ); + var IDOMElement = __import( "Dandelion.IDOMElement" ); /** @type {System.utils.DataKey} */ - var DataKey = __import( "System.utils.DataKey" ); + var DataKey = __import( "System.utils.DataKey" ); + /** @type {System.utils.EventKey} */ + var EventKey = __import( "System.utils.EventKey" ); /** @type {System.Cycle} */ - var Cycle = __import( "System.Cycle" ); + var Cycle = __import( "System.Cycle" ); /** @type {System.Debug} */ - var debug = __import( "System.Debug" ); + var debug = __import( "System.Debug" ); /** @type {Components.Vim.State.Registers} */ - var Registers = __import( "Components.Vim.State.Registers" ); + var Registers = __import( "Components.Vim.State.Registers" ); /** @type {Components.Vim.Syntax.Analyzer} */ - var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" ); + var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" ); /** @type {Components.Vim.LineFeeder} */ var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" ); @@ -25,6 +27,7 @@ var mesg = ns[ NS_INVOKE ]( "Message" ); var Insts = []; + var InstIndex = 0; var KeyHandler = function( sender, handler ) { @@ -61,14 +64,21 @@ var _self = this; - stage.addEventListener( "Focus", function() { _self.__active = true; } ); - stage.addEventListener( "Blur", function() { _self.__active = false; } ); + this.__stagedEvents = [ + new EventKey( "Focus", function() { _self.__active = true; } ) + , new EventKey( "Blur", function() { _self.__active = false; } ) + ]; + + this.__removeText // Init this.VisualizeVimFrame( element.value ); + // Set buffer index + this.__instIndex = InstIndex ++; + // Push this instance - Insts.push( this ); + Insts[ this.__instIndex ] = this; }; VimArea.prototype.select = function( sel ) @@ -86,6 +96,7 @@ VimArea.prototype.VisualizeVimFrame = function( content ) { var _self = this; + this.content = content; var element = this.stage.element; var r = this.rows; @@ -135,6 +146,8 @@ cfeeder.dispatcher.addEventListener( "VisualUpdate", Update ); Update(); + this.__visualUpdate = Update; + this.contentFeeder = cfeeder; this.contentAnalyzer = contentAnalyzer; this.statusFeeder = sfeeder; @@ -154,18 +167,48 @@ }, 600 ); var controls = new VimControls( this ); - this.stage.addEventListener( - "KeyDown" - , KeyHandler( this, controls.handler.bind( controls ) ) + + this.__stagedEvents.push( + new EventKey( "KeyDown", KeyHandler( this, controls.handler.bind( controls ) ) ) ); + + this.stage.addEventListeners( this.__stagedEvents ); }; - __readOnly( VimArea, "Instances", function() { - return Insts.slice(); + VimArea.prototype.dispose = function() + { + var stage = this.stage; + var evts = this.__stagedEvents; + var feeder = this.contentFeeder; + + var id = stage.element.id; + + debug.Info( "Destroy instance: " + id ); + + feeder.dispatcher.removeEventListener( "VisualUpdate", this.__visualUpdate ); + + stage.removeAttribute( "data-vimarea" ); + + Cycle.permaRemove( "VimCursorBlinkCycle" + id ); + for( var i in evts ) + { + stage.removeEventListener( evts[ i ] ); + } + + stage.element.value = this.content; + + delete Insts[ this.__instIndex ]; + }; + + __readOnly( VimArea.prototype, "index", function() + { + return this.__instIndex + 1; } ); - __readOnly( VimArea.prototype, "content", function() { - return this.contentFeeder.content.slice( 0, -1 ); + __readOnly( VimArea, "Instances", function() { + var clone = []; + for( var i in Insts ) clone.push( Insts[ i ] ); + return clone; } ); ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea ); diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js index f97d14a..d55ec63 100644 --- a/botanjs/src/Components/Vim/_this.js +++ b/botanjs/src/Components/Vim/_this.js @@ -1,3 +1,4 @@ +VIMRE_VERSION = "1.0.0b"; (function(){ var ns = __namespace( "Components.Vim" ); @@ -7,8 +8,9 @@ , "MORE": "-- MORE --" , "VISUAL": "-- VISUAL --" , "VISLINE": "-- VISUAL LINE --" + , "REGISTERS": "--- Registers ---" , "WRITE": "\"%1\" %2L, %3C written" - , "CONTINUE": "Press ENTER or type command to continue" + , "WAIT_FOR_INPUT": "Press ENTER or type command to continue" , "SEARCH_HIT_BOTTOM": "Seach hit BOTTOM, contining at TOP" , "TOP": "Top" , "BOTTOM": "Bot" @@ -29,6 +31,7 @@ var errors = { "E35": "No previous regular expression" + , "E37": "No write since last change (add ! to override)" , "E481": "No range allowed" , "E492": "Not an editor command: %1" , "E486": "Pattern not found: %1" diff --git a/botanjs/src/externs/Components.Vim.State.Recorder.js b/botanjs/src/externs/Components.Vim.State.Recorder.js index b39cbf9..543b3d8 100644 --- a/botanjs/src/externs/Components.Vim.State.Recorder.js +++ b/botanjs/src/externs/Components.Vim.State.Recorder.js @@ -7,3 +7,8 @@ Components.Vim.State.Recorder.undo; Components.Vim.State.Recorder.redo; /** @type Function */ Components.Vim.State.Recorder.record; +/** @type Function */ +Components.Vim.State.Recorder.save; + +/** @type Boolean */ +Components.Vim.State.Recorder.changed; diff --git a/botanjs/src/externs/Components.Vim.VimArea.js b/botanjs/src/externs/Components.Vim.VimArea.js index 51c9825..6d40d52 100644 --- a/botanjs/src/externs/Components.Vim.VimArea.js +++ b/botanjs/src/externs/Components.Vim.VimArea.js @@ -10,9 +10,13 @@ Components.Vim.VimArea.statusFeeder; /** @type {Components.Vim.StatusBar} */ Components.Vim.VimArea.statusBar; -/** @type {Number} */ +/** @type Number */ +Components.Vim.VimArea.index; +/** @type Number */ Components.Vim.VimArea.rows; -/** @type {Number} */ +/** @type Number */ Components.Vim.VimArea.cols; -/** @type {Array} */ +/** @type Array */ Components.Vim.VimArea.Instances; +/** @type Function */ +Components.Vim.VimArea.dispose;