From af2da6e023b43d2049e5c3490d7985dc61bdedd3 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: Thu, 31 Mar 2016 23:37:44 +0800 Subject: [PATCH] Added YANK --- botanjs/src/Components/Vim/Actions/DELETE.js | 24 ++-- botanjs/src/Components/Vim/Actions/PUT.js | 30 +++- botanjs/src/Components/Vim/Actions/YANK.js | 136 +++++++++++++++++- botanjs/src/Components/Vim/Controls.js | 4 + botanjs/src/Components/Vim/State/Registers.js | 33 +++-- botanjs/src/Components/Vim/_this.js | 5 +- .../externs/Components.Vim.State.Registers.js | 8 +- 7 files changed, 207 insertions(+), 33 deletions(-) diff --git a/botanjs/src/Components/Vim/Actions/DELETE.js b/botanjs/src/Components/Vim/Actions/DELETE.js index 1f05cbb..16daab5 100644 --- a/botanjs/src/Components/Vim/Actions/DELETE.js +++ b/botanjs/src/Components/Vim/Actions/DELETE.js @@ -10,6 +10,7 @@ var Stack = __import( "Components.Vim.State.Stack" ); var Mesg = __import( "Components.Vim.Message" ); + var beep = __import( "Components.Vim.Beep" ); var occurence = __import( "System.utils.Perf.CountSubstr" ); @@ -21,13 +22,15 @@ this.__nline = 0; this.__startX = Cursor.aPos; this.__panY = this.__cursor.feeder.panY; + + Cursor.suppressEvent(); }; DELETE.prototype.allowMovement = true; DELETE.prototype.dispose = function() { - + this.__cursor.unsuppressEvent(); }; DELETE.prototype.handler = function( e, sp ) @@ -43,6 +46,7 @@ var feeder = cur.feeder; var Triggered = false; + var newLine = false; if( sp == undefined ) { @@ -50,8 +54,6 @@ sp = this.__startX; - cur.suppressEvent(); - var currAp = cur.aPos; if( this.__startX != currAp ) { @@ -73,6 +75,7 @@ // Remove the current and the following line else if( e.kMap( "j" ) ) { + newLine = true; cur.lineEnd( true ); sp = cur.aPos; cur.moveY( -1 ); @@ -82,6 +85,7 @@ // Remove the current and the preceding line else if( e.kMap( "k" ) ) { + newLine = true; cur.moveY( 1 ); cur.lineEnd( true ); sp = cur.aPos; @@ -102,6 +106,7 @@ { if( e.kMap( "d" ) ) { + newLine = true; cur.lineEnd( true ); sp = cur.aPos; cur.lineStart(); @@ -124,12 +129,10 @@ } else { - cur.unsuppressEvent(); - return false; + beep(); + return true; } } - - cur.unsuppressEvent(); } var c = feeder.content; @@ -144,7 +147,7 @@ } var removed = c.substring( s, e + 1 ); - reg.change( removed ); + reg.change( removed, newLine ); this.__nline = occurence( removed, "\n" ); @@ -156,7 +159,6 @@ ? this.__panY - feeder.panY : undefined ); - cur.moveTo( s ); var stator = new Stator( cur, s ); @@ -165,9 +167,7 @@ c = c[ e + 1 ]; if( c == "\n" || c == undefined ) { - cur.suppressEvent(); cur.moveX( -1 ); - cur.unsuppressEvent(); } var f = stator.save( 0, removed ); @@ -186,7 +186,7 @@ { if( this.__nline ) { - return Mesg( "LINE_FEWER", this.__nline ); + return Mesg( "LINES_FEWER", this.__nline ); } return ""; diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js index 164899b..81ff721 100644 --- a/botanjs/src/Components/Vim/Actions/PUT.js +++ b/botanjs/src/Components/Vim/Actions/PUT.js @@ -16,14 +16,15 @@ { /** @type {Components.Vim.Cursor} */ this.__cursor = Cursor; - this.__stator = new Stator( Cursor ); this.__msg = ""; + Cursor.suppressEvent(); }; PUT.prototype.allowMovement = false; PUT.prototype.dispose = function() { + this.__cursor.unsuppressEvent(); }; PUT.prototype.handler = function( e ) @@ -42,38 +43,55 @@ var cur = this.__cursor; var feeder = cur.feeder; + var newLine = cput.newLine; + if( newLine ) + { + cur.moveY( 1 ); + cur.lineStart(); + } + + var stator = new Stator( cur ); var aP = cur.aPos; feeder.content = feeder.content.substring( 0, aP ) + cput + feeder.content.substring( aP ); - cur.suppressEvent(); feeder.pan(); cur.moveTo( 0 < nLines ? aP : aP + clen, true ); var stack = new Stack(); - stack.store( this.__stator.save( clen, "" ) ); + if( newLine ) + { + var f = stator.save( clen, "" ); + stack.store( function() + { + f(); + cur.moveY( -1 ); + } ); + } + else + { + stack.store( stator.save( clen, "" ) ); + } cur.rec.record( stack ); this.__put = cput; if( nLines ) { - this.__msg = Mesg( "LINE_MORE", nLines ); + this.__msg = Mesg( "LINES_MORE", nLines ); } cur.moveX( -1 ); - cur.unsuppressEvent(); return true; }; PUT.prototype.getMessage = function() { - console.log( this.__msg ); return this.__msg; }; diff --git a/botanjs/src/Components/Vim/Actions/YANK.js b/botanjs/src/Components/Vim/Actions/YANK.js index ba987d7..12f7a5c 100644 --- a/botanjs/src/Components/Vim/Actions/YANK.js +++ b/botanjs/src/Components/Vim/Actions/YANK.js @@ -1,31 +1,161 @@ (function(){ var ns = __namespace( "Components.Vim.Actions" ); + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + var Mesg = __import( "Components.Vim.Message" ); + var beep = __import( "Components.Vim.Beep" ); + + var occurence = __import( "System.utils.Perf.CountSubstr" ); /** @type {Components.Vim.Cursor.IAction} */ var YANK = function( Cursor ) { /** @type {Components.Vim.Cursor} */ this.__cursor = Cursor; + this.__startX = Cursor.aPos; + this.__msg = ""; + + Cursor.suppressEvent(); }; YANK.prototype.allowMovement = true; YANK.prototype.dispose = function() { - + this.__cursor.unsuppressEvent(); }; - YANK.prototype.handler = function( e ) + YANK.prototype.handler = function( e, sp ) { e.preventDefault(); + if( e.ModKeys || e.kMap( "i" ) ) return; + + /** @type {Components.Vim.State.Registers} */ + var reg = e.target.registers; + + var cur = this.__cursor; + var feeder = cur.feeder; + + var Triggered = false; + + var newLine = false; + if( sp == undefined ) + { + Triggered = true; + + sp = this.__startX; + + var currAp = cur.aPos; + if( this.__startX != currAp ) + { + // Remove to start + if( e.kMap( "^" ) ) + { + sp --; + } + // Remove char in cursor + else if( e.kMap( "l" ) ) + { + cur.moveX( -1 ); + } + // Remove char before cursor + else if( e.kMap( "h" ) ) + { + sp = currAp; + } + // Remove the current and the following line + else if( e.kMap( "j" ) ) + { + newLine = true; + cur.lineEnd( true ); + sp = cur.aPos; + cur.moveY( -1 ); + cur.lineStart(); + this.__startX = cur.aPos; + } + // Remove the current and the preceding line + else if( e.kMap( "k" ) ) + { + newLine = true; + cur.moveY( 1 ); + cur.lineEnd( true ); + sp = cur.aPos; + cur.moveY( -1 ); + cur.lineStart(); + } + else if( this.__startX < currAp ) + { + // Swap the movement + // This is to move the REDO / UNDO Cursor + // position to the earlier position + sp = currAp; + cur.moveTo( this.__startX ); + } + } + // Remove the current line + else + { + if( e.kMap( "y" ) ) + { + newLine = true; + cur.lineEnd( true ); + sp = cur.aPos; + cur.lineStart(); + } + else if( e.range ) + { + sp = e.range.close; + cur.moveTo( e.range.open, true ); + } + else if( e.kMap( "^" ) ) + { + // Do nothing as nothing can be removed + // since there is no successful movement + return true; + } + // this is the same as kMap( "h" ) above + else if( e.kMap( "$" ) ) + { + sp = cur.aPos; + } + else + { + beep(); + return true; + } + } + } + + var s = sp; + var e = cur.aPos; + + if( e < s ) + { + s = cur.aPos; + e = sp; + } + + cur.moveTo( s ); + + var yText = cur.feeder.content.substring( s, e + 1 ); + + reg.yank( yText, newLine ); + + var nline = occurence( yText, "\n" ); + if( nline ) + { + this.__msg = Mesg( "LINES_YANKED", nline ); + } + + return Triggered; }; YANK.prototype.getMessage = function() { - return " YANK COMMAND"; + return this.__msg; }; ns[ NS_EXPORT ]( EX_CLASS, "YANK", YANK ); diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js index 522e35d..1163433 100644 --- a/botanjs/src/Components/Vim/Controls.js +++ b/botanjs/src/Components/Vim/Controls.js @@ -189,9 +189,13 @@ case CTRL + R: // Redo ccur.openRunAction( "REDO", e ); break; + case D: // Del with motion ccur.openAction( "DELETE" ); break; + case Y: // Yank with motion + ccur.openAction( "YANK" ); + break; case P: // Put ccur.suppressEvent(); diff --git a/botanjs/src/Components/Vim/State/Registers.js b/botanjs/src/Components/Vim/State/Registers.js index 48ca4a3..ec6335b 100644 --- a/botanjs/src/Components/Vim/State/Registers.js +++ b/botanjs/src/Components/Vim/State/Registers.js @@ -15,25 +15,41 @@ */ var ns = __namespace( "Components.Vim.State" ); + var Register = function( str, n ) + { + this.__str = str + ""; + this.newLine = Boolean( n ); + }; + + Register.prototype.newLine = false; + + Register.prototype.toString = function() { return this.__str; }; + Register.prototype.indexOf = function( a, b ) { return this.__str.indexOf( a, b ); }; + + __readOnly( Register.prototype, "length", function() { return this.__str.length; } ); + + var Registers = function() { this.__registers = {}; }; - Registers.prototype.unnamed = function( str ) + Registers.prototype.__unnamed = function( reg ) { - this.__registers[ "\"" ] = str; + this.__registers[ "\"" ] = reg; }; - Registers.prototype.yank = function( str ) + Registers.prototype.yank = function( str, newLine ) { - this.unnamed( str ); - this.__registers[ 0 ] = str; + var reg = new Register( str, newLine ); + this.__unnamed( reg ); + this.__registers[ 0 ] = reg; }; - Registers.prototype.change = function( str ) + Registers.prototype.change = function( str, newLine ) { - this.unnamed( str ); + var reg = new Register( str, newLine ); + this.__unnamed( reg ); var r = this.__registers; for( var i = 9; 1 < i; i -- ) { @@ -43,7 +59,7 @@ } } - r[ 1 ] = str; + r[ 1 ] = reg; }; Registers.prototype.get = function( r ) @@ -55,4 +71,5 @@ }; ns[ NS_EXPORT ]( EX_CLASS, "Registers", Registers ); + })(); diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js index 8a5b199..e387304 100644 --- a/botanjs/src/Components/Vim/_this.js +++ b/botanjs/src/Components/Vim/_this.js @@ -18,8 +18,9 @@ , "UNDO_LIMIT": "Already at oldest change" , "REDO_LIMIT": "Already at newest change" - , "LINE_FEWER": "%1 fewer lines" - , "LINE_MORE": "%1 more lines" + , "LINES_FEWER": "%1 fewer line(s)" + , "LINES_MORE": "%1 more line(s)" + , "LINES_YANKED": "%1 line(s) yanked" }; var errors = { diff --git a/botanjs/src/externs/Components.Vim.State.Registers.js b/botanjs/src/externs/Components.Vim.State.Registers.js index 75b9c13..61bdfc7 100644 --- a/botanjs/src/externs/Components.Vim.State.Registers.js +++ b/botanjs/src/externs/Components.Vim.State.Registers.js @@ -5,5 +5,9 @@ Components.Vim.State.Registers = function(){}; Components.Vim.State.Registers.change; /** @type Function */ Components.Vim.State.Registers.yank; -/** @type Function */ -Components.Vim.State.Registers.unnamed; + +/** @constructor */ +Components.Vim.State.Register = function(){}; + +/** @type Boolean */ +Components.Vim.State.Register.newLine;