commit c7249c071c9b3aa6787b930e0d9c4ce3e5dd42b1
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2016-04-02T06:25:25Z |
| subject | Search Ex Draft |
commit c7249c071c9b3aa6787b930e0d9c4ce3e5dd42b1
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2016-04-02T06:25:25Z
Search Ex Draft
---
botanjs/src/Components/Vim/Actions/PUT.js | 2 -
botanjs/src/Components/Vim/Controls.js | 123 ++++++++++++++++---
botanjs/src/Components/Vim/Cursor.js | 6 +-
botanjs/src/Components/Vim/Ex/Search.js | 150 ++++++++++++++++++++++++
botanjs/src/Components/Vim/StatusBar.js | 5 +
botanjs/src/Components/Vim/VimArea.js | 5 +-
botanjs/src/externs/Components.Vim.StatusBar.js | 2 +
7 files changed, 268 insertions(+), 25 deletions(-)
diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js
index 2dbb263..e58c9f9 100644
--- a/botanjs/src/Components/Vim/Actions/PUT.js
+++ b/botanjs/src/Components/Vim/Actions/PUT.js
@@ -1,8 +1,6 @@
(function(){
var ns = __namespace( "Components.Vim.Actions" );
- var Mesg = __import( "Components.Vim.Message" );
-
/** @type {Components.Vim.State.Stator} */
var Stator = __import( "Components.Vim.State.Stator" );
/** @type {Components.Vim.State.Stack} */
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 587cda3..e129357 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -3,6 +3,10 @@
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
+
+ /** @type {Components.Vim.Ex.Search} */
+ var ExSearch = __import( "Components.Vim.Ex.Search" );
+
var beep = ns[ NS_INVOKE ]( "Beep" );
var SHIFT = 1 << 9;
@@ -14,8 +18,12 @@
var KEY_ALT = 18;
var BACKSPACE = 8;
+ var TAB = 9;
+ var ENTER = 13;
var DELETE = 46;
+ var UP = 38; var DOWN = 40; var LEFT = 37; var RIGHT = 39;
+
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;
@@ -70,6 +78,13 @@
{
case "BS": kCode = Mod + BACKSPACE; break;
case "Del": kCode = Mod + DELETE; break;
+ case "Enter": kCode = Mod + ENTER; break;
+ case "Tab": kCode = Mod + TAB; break;
+
+ case "Up": kCode = Mod + UP; break;
+ case "Down": kCode = Mod + DOWN; break;
+ case "Left": kCode = Mod + LEFT; break;
+ case "Right": kCode = Mod + RIGHT; break;
case "A": Mod = SHIFT; case "a": kCode = Mod + A; break;
case "B": Mod = SHIFT; case "b": kCode = Mod + B; break;
@@ -127,6 +142,10 @@
this.__sfeeder = vimArea.statusFeeder;
this.__ccur = this.__cfeeder.cursor;
+
+ // Dived composite command handler
+ // Has full control of the key input, except Esc
+ this.__divedCCmd = null;
};
Controls.prototype.__composite = function( e, handler )
@@ -183,6 +202,19 @@
case I: // Insert
ccur.openAction( "INSERT" );
break;
+
+ case SHIFT + O: // new line before insert
+ ccur.lineStart();
+ ccur.openAction( "INSERT" );
+ ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
+ ccur.moveY( -1 );
+ break;
+ case O: // new line insert
+ ccur.lineEnd( true );
+ ccur.openAction( "INSERT" );
+ ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
+ break;
+
case U: // Undo
ccur.openRunAction( "UNDO", e );
break;
@@ -205,9 +237,15 @@
ccur.openRunAction( "PUT", e );
break;
- case X: // Del
- break;
case SHIFT + X: // Delete before
+ if( !this.__cMoveX( -1 ) ) break;
+ case X: // Del
+ if( ccur.getLine().content == "" )
+ {
+ beep();
+ break;
+ }
+ ccur.openRunAction( "DELETE", e, ccur.aPos );
break;
case SHIFT + U: // Undo previous changes in oneline
break;
@@ -240,7 +278,12 @@
var x = ccur.X;
ccur.moveX( a, b, c || ccur.pSpace );
- if( ccur.X == x ) beep();
+ if( ccur.X == x )
+ {
+ beep();
+ return false;
+ }
+ return true;
};
Controls.prototype.__cMoveY = function( a )
@@ -252,16 +295,18 @@
ccur.moveY( a );
if( y == ( ccur.Y + cfeeder.panY ) )
{
- if( 0 < a && !cfeeder.EOF ) return;
+ if( 0 < a && !cfeeder.EOF ) return true;
beep();
}
+
+ return false;
};
Controls.prototype.__cursorCommand = function( e )
{
var kCode = e.keyCode;
- if( this.__cMovement && this.__composite )
+ if( this.__cMovement )
{
if( !e.ModKeys )
{
@@ -396,9 +441,11 @@
}, _8 );
break;
- case SLASH: // "/" Seach movement
case SLASH: // "/" Seach movement
this.__cMovement = true;
+
+ this.__divedCCmd = new ExSearch( ccur );
+ this.__divedCCmd.handler( e );
break;
default:
cursorHandled = false;
@@ -420,12 +467,39 @@
) return;
// Clear composite command
- if( e.Escape && this.__compositeReg )
+ if( e.Escape )
{
- this.__compositeReg = null;
+ var b = false;
this.__cMovement = false;
- beep();
- return;
+
+ if( this.__compositeReg )
+ {
+ b = true;
+ this.__compositeReg = null;
+ }
+ else if( this.__divedCCmd )
+ {
+ b = true;
+ this.__divedCCmd.dispose();
+ this.__divedCCmd = null;
+ }
+
+ if( b )
+ {
+ beep();
+ return;
+ }
+ }
+
+ if( this.__divedCCmd )
+ {
+ if( this.__divedCCmd.handler( e ) )
+ {
+ this.__divedCCmd.dispose();
+ this.__cMovement = false;
+ this.__divedCCmd = null;
+ }
+ else return;
}
var cfeeder = this.__cfeeder;
@@ -470,19 +544,30 @@
var InputEvent = function( sender, e )
{
- this.__e = e;
this.__target = sender;
- var c = this.__e.keyCode;
+ if( typeof( e ) == "string" )
+ {
+ this.__key = e;
+ this.__modKeys = 0;
+ this.__kCode = Map( e );
+ this.__escape = this.__kCode == ESC;
+ }
+ else
+ {
+ this.__e = e;
- this.__escape = c == ESC || ( e.ctrlKey && c == C );
- this.__kCode = c
- + ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
- + ( e.ctrlKey ? CTRL : 0 )
- + ( e.altKey ? ALT : 0 );
+ var c = this.__e.keyCode;
- this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
- this.__key = e.key;
+ this.__escape = c == ESC || ( e.ctrlKey && c == C );
+ this.__kCode = c
+ + ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
+ + ( e.ctrlKey ? CTRL : 0 )
+ + ( e.altKey ? ALT : 0 );
+
+ this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
+ this.__key = e.key;
+ }
this.__range = null;
};
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index be80a42..bd1967d 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -396,11 +396,11 @@
};
// Open, Run, then close an action
- Cursor.prototype.openRunAction = function( name, e )
+ Cursor.prototype.openRunAction = function( name, e, arg1 )
{
/** @type {Components.Vim.IAction} */
var action = new (Actions[ name ])( this );
- action.handler( e );
+ action.handler( e, arg1 );
this.__pulseMsg = action.getMessage();
action.dispose();
@@ -497,6 +497,8 @@
return p;
} );
+ __readOnly( Cursor.prototype, "face", function() { return "\u2588"; } );
+
__readOnly( Cursor.prototype, "message", function()
{
if( this.__pulseMsg )
diff --git a/botanjs/src/Components/Vim/Ex/Search.js b/botanjs/src/Components/Vim/Ex/Search.js
new file mode 100644
index 0000000..169f5a5
--- /dev/null
+++ b/botanjs/src/Components/Vim/Ex/Search.js
@@ -0,0 +1,150 @@
+(function(){
+ var ns = __namespace( "Components.Vim.Ex" );
+
+ /** @type {System.Cycle} */
+ var Cycle = __import( "System.Cycle" );
+ /** @type {System.Debug} */
+ var debug = __import( "System.Debug" );
+ /** @type {System.utils.Perf} */
+ var Perf = __import( "System.utils.Perf" );
+
+ var Mesg = __import( "Components.Vim.Message" );
+
+ /** @type {Components.Vim.Cursor.IAction} */
+ var Search = function( Cursor )
+ {
+ var _self = this;
+
+ /** @type {Components.Vim.Cursor} */
+ this.__cursor = Cursor;
+
+ this.__statusBar = Cursor.Vim.statusBar;
+
+ this.__command = [];
+ this.__blinkId = "ExSearchBlinkCycle" + Perf.uuid;
+ this.__curPos = 0;
+
+ this.__disp = function()
+ {
+ };
+
+ var feeder = Cursor.feeder;
+
+ var __blink = false;
+ var __holdBlink = false;
+ this.__blink = function()
+ {
+ __blink = true;
+ __holdBlink = true
+ };
+
+ Cycle.perma( this.__blinkId, function()
+ {
+ if( __holdBlink ) __holdBlink = false;
+ else __blink = !__blink;
+
+ feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+ }, 600 );
+
+ this.__doBlink = function()
+ {
+ var c = "";
+ var comm = _self.__command;
+ var pos = _self.__curPos;
+ var cLen = comm.length;
+ var faced = true;
+
+ for( var i = 0; i < cLen; i ++ )
+ {
+ var v = comm[i];
+ if( __blink && i == pos )
+ {
+ face = true;
+ v = Cursor.face + v.substr( 1 );
+ }
+
+ c+= v;
+ }
+
+ if( __blink && cLen <= pos )
+ {
+ c += Cursor.face;
+ }
+
+ return c;
+ };
+
+ this.__statusBar.override = this.__doBlink;
+ };
+
+ Search.prototype.dispose = function()
+ {
+ this.__statusBar.override = null;
+
+ Cycle.permaRemove( this.__blinkId );
+ var feeder = this.__cursor.feeder;
+ feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+ };
+
+ Search.prototype.handler = function( e )
+ {
+ e.preventDefault();
+
+ if( e.ModKeys ) return;
+
+ this.__blink();
+
+ var InputKey = null;
+
+ if( e.kMap( "Tab" ) )
+ {
+ InputKey = "^I";
+ }
+ else if( e.kMap( "C-v" ) )
+ {
+ this.__direct = true;
+ }
+ else if( e.kMap( "BS" ) )
+ {
+ this.__command.splice( --this.__curPos, 1 );
+ if( this.__command.length == 0 ) return true;
+ }
+ else if( e.kMap( "Del" ) )
+ {
+ this.__command.splice( this.__curPos, 1 );
+ }
+ else if( e.kMap( "Enter" ) )
+ {
+ return true;
+ }
+ else if( e.kMap( "Up" ) ) // History navigations
+ {
+ }
+ else if( e.kMap( "Down" ) )
+ {
+ }
+ else if( e.kMap( "Left" ) )
+ {
+ if( 0 < this.__curPos ) this.__curPos --;
+ }
+ else if( e.kMap( "Right" ) )
+ {
+ if( this.__curPos < this.__command.length )
+ this.__curPos ++;
+ }
+ else
+ {
+ InputKey = e.key;
+ }
+
+ if( InputKey != null )
+ {
+ this.__command.splice( this.__curPos ++, 0, InputKey );
+ }
+
+ var feeder = this.__cursor.feeder;
+ feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+ }
+
+ ns[ NS_EXPORT ]( EX_CLASS, "Search", Search );
+})();
diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js
index 1a57d5c..81af357 100644
--- a/botanjs/src/Components/Vim/StatusBar.js
+++ b/botanjs/src/Components/Vim/StatusBar.js
@@ -10,6 +10,7 @@
{
this.cols = cols;
this.statStamp = {};
+ this.override = null;
};
StatusBar.prototype.stamp = function( pos, func )
@@ -17,8 +18,12 @@
this.statStamp[ pos ] = func;
};
+ StatusBar.prototype.override;
+
__readOnly( StatusBar.prototype, "statusText", function()
{
+ if( this.override ) return this.override();
+
var display = "";
var l = this.cols;
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 95b02c6..c5480ec 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -123,9 +123,10 @@
{
sfeeder.init( statusBar.statusText );
+ var sLine = sfeeder.linesOccupied;
element.value =
- cfeeder.render( 0, r - sfeeder.linesOccupied )
- + "\n" + sfeeder.render();
+ cfeeder.render( 0, r - sLine )
+ + "\n" + sfeeder.render( 0, sLine < r ? sLine : r );
_self.__blink = false;
_self.select( cfeeder.cursor.position );
diff --git a/botanjs/src/externs/Components.Vim.StatusBar.js b/botanjs/src/externs/Components.Vim.StatusBar.js
index 356c980..8e43a79 100644
--- a/botanjs/src/externs/Components.Vim.StatusBar.js
+++ b/botanjs/src/externs/Components.Vim.StatusBar.js
@@ -3,5 +3,7 @@ Components.Vim.StatusBar = function(){};
/** @type Function */
Components.Vim.StatusBar.stamp;
+/** @type Function */
+Components.Vim.StatusBar.override;
/** @type String */
Components.Vim.StatusBar.statusText;