forked from Botanical/BotanJS
		
	Fixed cursor mis-positioned on tab characters
This commit is contained in:
		| @@ -60,7 +60,7 @@ | |||||||
| 		} | 		} | ||||||
| 		this.__msg = ""; | 		this.__msg = ""; | ||||||
| 		this.__rec( "", true ); | 		this.__rec( "", true ); | ||||||
| 		this.__cursor.moveX( -1 ); | 		this.__cursor.moveX( -1, false, false, true ); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	INSERT.prototype.__rec = function( c, newRec ) | 	INSERT.prototype.__rec = function( c, newRec ) | ||||||
| @@ -197,7 +197,7 @@ | |||||||
| 		{ | 		{ | ||||||
| 			this.__realizeIndent(); | 			this.__realizeIndent(); | ||||||
| 			feeder.pan(); | 			feeder.pan(); | ||||||
| 			cur.moveX( inputChar == "\t" ? feeder.firstBuffer.tabWidth : 1, false, true ); | 			cur.moveX( inputChar == "\t" ? feeder.firstBuffer.tabWidth : 1, false, true, true ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); | 		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); | ||||||
| @@ -262,7 +262,7 @@ | |||||||
|  |  | ||||||
| 			feeder.softReset(); | 			feeder.softReset(); | ||||||
| 			feeder.pan(); | 			feeder.pan(); | ||||||
| 			cur.moveX( i * feeder.firstBuffer.tabWidth, false, true ); | 			cur.moveX( i, false, true ); | ||||||
|  |  | ||||||
| 			var a = []; | 			var a = []; | ||||||
| 			a[ IN_START ] = f; | 			a[ IN_START ] = f; | ||||||
|   | |||||||
| @@ -345,7 +345,7 @@ | |||||||
| 			f(); | 			f(); | ||||||
| 			// Offset correction after REDO / UNDO | 			// Offset correction after REDO / UNDO | ||||||
| 			cur.moveTo( recStart ); | 			cur.moveTo( recStart ); | ||||||
| 			cur.lineStart(); | 			cur.lineStart( true ); | ||||||
| 		} ); | 		} ); | ||||||
|  |  | ||||||
| 		cur.moveTo( recStart ); | 		cur.moveTo( recStart ); | ||||||
|   | |||||||
| @@ -220,13 +220,13 @@ | |||||||
|  |  | ||||||
| 				if( cur.aPos == startLine.aPos ) | 				if( cur.aPos == startLine.aPos ) | ||||||
| 				{ | 				{ | ||||||
| 					cur.moveTo( r.open, true ); | 					cur.moveTo( r.open, true, false, true ); | ||||||
| 					this.__reset( cur ); | 					this.__reset( cur ); | ||||||
| 					startLine = this.__startLine; | 					startLine = this.__startLine; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				cur.unsuppressEvent(); | 				cur.unsuppressEvent(); | ||||||
| 				cur.moveTo( r.close, true ); | 				cur.moveTo( r.close, true, false, true ); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			var currAp = cur.aPos; | 			var currAp = cur.aPos; | ||||||
|   | |||||||
| @@ -259,9 +259,17 @@ | |||||||
| 		{ | 		{ | ||||||
| 			case SHIFT + A: // Append at the line end | 			case SHIFT + A: // Append at the line end | ||||||
| 				ccur.lineEnd(); | 				ccur.lineEnd(); | ||||||
| 			case A: // Append | 				ccur.moveX( 1, true, true, true ); | ||||||
| 				ccur.moveX( 1, true, true ); | 				ccur.openAction( "INSERT", e ); | ||||||
|  | 				break; | ||||||
| 			case I: // Insert | 			case I: // Insert | ||||||
|  | 				ccur.moveX( -1 ); | ||||||
|  | 			case A: // Append | ||||||
|  | 				ccur.moveX( 1, true, true, true ); | ||||||
|  | 				ccur.openAction( "INSERT", e ); | ||||||
|  | 				break; | ||||||
|  | 			case SHIFT + I: // Append at line start | ||||||
|  | 				ccur.lineStart( true ); | ||||||
| 				ccur.openAction( "INSERT", e ); | 				ccur.openAction( "INSERT", e ); | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| @@ -515,11 +523,11 @@ | |||||||
| 			case SHIFT + L: // Last line buffer | 			case SHIFT + L: // Last line buffer | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			case _0: // Really - line Start | 			case _0: // Really line Start | ||||||
| 				ccur.lineStart(); | 				ccur.lineStart(); | ||||||
| 				break; | 				break; | ||||||
| 			case SHIFT + _6: // ^, line Start, XXX: skip tabs | 			case SHIFT + _6: // ^, line Start at word | ||||||
| 				ccur.lineStart(); | 				ccur.lineStart( true ); | ||||||
| 				break; | 				break; | ||||||
| 			case SHIFT + _4: // $, End | 			case SHIFT + _4: // $, End | ||||||
| 				ccur.lineEnd( ccur.pSpace ); | 				ccur.lineEnd( ccur.pSpace ); | ||||||
|   | |||||||
| @@ -103,7 +103,7 @@ | |||||||
| 	Cursor.prototype.Vim; | 	Cursor.prototype.Vim; | ||||||
|  |  | ||||||
| 	// Move to an absolute position | 	// Move to an absolute position | ||||||
| 	Cursor.prototype.moveTo = function( aPos, phantomSpace ) | 	Cursor.prototype.moveTo = function( aPos, phantomSpace, skipTabs ) | ||||||
| 	{ | 	{ | ||||||
| 		var content = this.feeder.content; | 		var content = this.feeder.content; | ||||||
| 		var pline = this.getLine(); | 		var pline = this.getLine(); | ||||||
| @@ -133,19 +133,18 @@ | |||||||
| 		var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart; | 		var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart; | ||||||
|  |  | ||||||
| 		jumpX += Math.ceil( jumpX / pline.cols ) - 1; | 		jumpX += Math.ceil( jumpX / pline.cols ) - 1; | ||||||
| 		jumpX += occurence( content.substring( lineStart + 1, aPos ), "\t" ) * ( pline.tabWidth - 1 ); |  | ||||||
|  |  | ||||||
| 		if( jumpY ) this.moveY( jumpY ); | 		if( jumpY ) this.moveY( jumpY ); | ||||||
|  |  | ||||||
| 		// This is needed because first line does not contain the first "\n" character | 		// This is needed because first line does not contain the first "\n" character | ||||||
| 		if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --; | 		if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --; | ||||||
|  |  | ||||||
| 		this.moveX( - Number.MAX_VALUE ); | 		this.moveX( - Number.MAX_VALUE, false, false, true ); | ||||||
| 		this.moveX( jumpX, false, phantomSpace ); | 		this.moveX( jumpX, false, phantomSpace, skipTabs ); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	// 0 will be treated as default ( 1 ) | 	// 0 will be treated as default ( 1 ) | ||||||
| 	Cursor.prototype.moveX = function( d, penetrate, phantomSpace ) | 	Cursor.prototype.moveX = function( d, penetrate, phantomSpace, skipTab ) | ||||||
| 	{ | 	{ | ||||||
| 		var x = this.pX; | 		var x = this.pX; | ||||||
| 		var updatePx = Boolean( d ); | 		var updatePx = Boolean( d ); | ||||||
| @@ -177,6 +176,8 @@ | |||||||
|  |  | ||||||
| 		/** @type {Components.Vim.LineBuffer} */ | 		/** @type {Components.Vim.LineBuffer} */ | ||||||
| 		var line = this.getLine(); | 		var line = this.getLine(); | ||||||
|  | 		var tabStep = line.tabWidth - 1; | ||||||
|  | 		var rline = this.rawLine; | ||||||
| 		var content = line.visualLines.join( "\n" ); | 		var content = line.visualLines.join( "\n" ); | ||||||
| 		var cLen = content.length; | 		var cLen = content.length; | ||||||
|  |  | ||||||
| @@ -190,8 +191,7 @@ | |||||||
| 		{ | 		{ | ||||||
| 			// Begin check if this line contains phantomSpace | 			// Begin check if this line contains phantomSpace | ||||||
| 			// hasPhantomSpace = 0 < ( rawLine.displayLength ) % cols | 			// hasPhantomSpace = 0 < ( rawLine.displayLength ) % cols | ||||||
| 			var rline = this.rawLine; | 			hasPhantomSpace = 0 < ( rline.length + occurence( rline, "\t" ) * tabStep ) % line.cols; | ||||||
| 			hasPhantomSpace = 0 < ( rline.length + occurence( rline, "\t" ) * ( line.tabWidth - 1 ) ) % line.cols; |  | ||||||
|  |  | ||||||
| 			if( hasPhantomSpace ) | 			if( hasPhantomSpace ) | ||||||
| 			{ | 			{ | ||||||
| @@ -203,6 +203,56 @@ | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// Hacky tab compensations | ||||||
|  | 		if( !skipTab ) | ||||||
|  | 		{ | ||||||
|  | 			var s = this.aX; | ||||||
|  | 			var a = rline[ s + d ]; | ||||||
|  | 			var e = s; | ||||||
|  | 			if( d < 0 ) | ||||||
|  | 			{ | ||||||
|  | 				if( rline[ s ] == "\t" ) | ||||||
|  | 				{ | ||||||
|  | 					x -= tabStep; | ||||||
|  | 					if( x < 0 ) | ||||||
|  | 						x = tabStep; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				s += d; | ||||||
|  |  | ||||||
|  | 				var ntabs = occurence( rline.substring( s, e ), "\t" ) - 1; | ||||||
|  | 				if( 0 < ntabs ) x -= ntabs * tabStep; | ||||||
|  | 			} | ||||||
|  | 			else if( updatePx ) // && 0 < d ( assuming d can never be 0 ) | ||||||
|  | 			{ | ||||||
|  | 				// Going from one line to next | ||||||
|  | 				// linebreaks are *invisible* | ||||||
|  | 				var isLF = ( content[ x ] == "\n" ) ? 1 : 0; | ||||||
|  |  | ||||||
|  | 				if( s == 0 ) | ||||||
|  | 				{ | ||||||
|  | 					x = 1; | ||||||
|  | 					if ( rline[ 0 ] == "\t" ) | ||||||
|  | 					{ | ||||||
|  | 						x += tabStep; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				e += d; | ||||||
|  |  | ||||||
|  | 				var ntabs = occurence( rline.substring( s + 1, e + 1 ), "\t" ); | ||||||
|  | 				x += ntabs * tabStep + isLF; | ||||||
|  | 				if( 1 < d ) x += d - 1; | ||||||
|  | 			} | ||||||
|  | 			else // jk, non-X navigation. i.e., pX does not change | ||||||
|  | 			{ | ||||||
|  | 				// s = 0, which is unused here | ||||||
|  | 				e = x + d; | ||||||
|  | 				x += ( occurence( rline.substring( 0, e ), "\t" ) ) * tabStep; | ||||||
|  | 				if( 1 < d ) x += d - 1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		var c = content[ x ]; | 		var c = content[ x ]; | ||||||
|  |  | ||||||
| 		// Whether x is at line boundary | 		// Whether x is at line boundary | ||||||
| @@ -227,22 +277,31 @@ | |||||||
|  |  | ||||||
| 		if( updatePx ) | 		if( updatePx ) | ||||||
| 		{ | 		{ | ||||||
| 			this.pX = x; | 			this.pX = this.aX; | ||||||
| 			this.updatePosition(); | 			this.updatePosition(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Cursor.prototype.lineStart = function() | 	Cursor.prototype.lineStart = function( atWord ) | ||||||
| 	{ | 	{ | ||||||
| 		this.pX = 0; | 		if( atWord ) | ||||||
|  | 		{ | ||||||
|  | 			var a = this.rawLine.match( /^[ \t]+/g ); | ||||||
|  | 			this.pX = a ? a[0].length : 0; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			this.pX = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		this.moveX(); | 		this.moveX(); | ||||||
| 		this.updatePosition(); | 		this.updatePosition(); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Cursor.prototype.lineEnd = function( phantomSpace ) | 	Cursor.prototype.lineEnd = function( phantomSpace ) | ||||||
| 	{ | 	{ | ||||||
| 		this.moveX( Number.MAX_VALUE, false, phantomSpace ); | 		this.moveX( Number.MAX_VALUE, false, phantomSpace, true ); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Cursor.prototype.updatePosition = function() | 	Cursor.prototype.updatePosition = function() | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ VIMRE_VERSION = "1.0.0b"; | |||||||
| 		"INSERT": "-- INSERT --" | 		"INSERT": "-- INSERT --" | ||||||
| 		, "REPLACE": "-- REPLACE --" | 		, "REPLACE": "-- REPLACE --" | ||||||
| 		, "MORE": "-- MORE --" | 		, "MORE": "-- MORE --" | ||||||
| 		, "VISUAL": "-- VISUAL  --" | 		, "VISUAL": "-- VISUAL --" | ||||||
| 		, "VISLINE": "-- VISUAL LINE --" | 		, "VISLINE": "-- VISUAL LINE --" | ||||||
| 		, "REGISTERS": "--- Registers ---" | 		, "REGISTERS": "--- Registers ---" | ||||||
| 		, "WRITE": "\"%1\" %2L, %3C written" | 		, "WRITE": "\"%1\" %2L, %3C written" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user