@@ -32,7 +32,9 @@ import {
3232} from './types' ;
3333import { Pattern , SearchDirection } from '../pattern' ;
3434import { escapeRegExp , isInteger } from 'lodash' ;
35- import { integerParser } from '../parserUtils' ;
35+ import { VimState } from '../../state/vimState' ;
36+ import { Position } from 'vscode' ;
37+ import { isVisualMode } from '../../mode/mode' ;
3638
3739// ID of next lambda; incremented each time one is created
3840let lambdaNumber = 1 ;
@@ -146,9 +148,14 @@ export type VariableStore = Map<string, Variable>;
146148export class EvaluationContext {
147149 private static globalVariables : VariableStore = new Map ( ) ;
148150
151+ private vimState : VimState | undefined ;
149152 private localScopes : VariableStore [ ] = [ ] ;
150153 private errors : string [ ] = [ ] ;
151154
155+ constructor ( vimState : VimState | undefined ) {
156+ this . vimState = vimState ;
157+ }
158+
152159 /**
153160 * Fully evaluates the given expression and returns the resulting value.
154161 * May throw a variety of VimErrors if the expression is semantically invalid.
@@ -677,6 +684,33 @@ export class EvaluationContext {
677684 this . errors . push ( msg ) ;
678685 return int ( 1 ) ;
679686 } ;
687+
688+ const getpos = ( arg : string ) => {
689+ const pos : Position | undefined = ( ( ) => {
690+ if ( arg === '.' ) {
691+ return this . vimState ! . cursorStopPosition ;
692+ } else if ( arg === '$' ) {
693+ return new Position ( this . vimState ! . document . lineCount , 0 ) ;
694+ } else if ( arg . startsWith ( "'" ) && arg . length === 2 ) {
695+ const mark = this . vimState ! . historyTracker . getMark ( arg [ 1 ] ) ;
696+ return mark ?. position ;
697+ } else if ( arg === 'w0' ) {
698+ return new Position ( this . vimState ! . editor . visibleRanges [ 0 ] . start . line , 0 ) ;
699+ } else if ( arg === 'w$' ) {
700+ return new Position ( this . vimState ! . editor . visibleRanges [ 0 ] . end . line , 0 ) ;
701+ } else if ( arg === 'v' ) {
702+ return this . vimState ! . cursorStartPosition ;
703+ }
704+ return undefined ;
705+ } ) ( ) ;
706+ return {
707+ bufnum : 0 , // TODO
708+ lnum : ( pos ?. line ?? - 1 ) + 1 ,
709+ col : ( pos ?. character ?? - 1 ) + 1 ,
710+ off : 0 ,
711+ } ;
712+ } ;
713+
680714 const getArgs = ( min : number , max ?: number ) => {
681715 if ( max === undefined ) {
682716 max = min ;
@@ -830,6 +864,10 @@ export class EvaluationContext {
830864 const [ x ] = getArgs ( 1 ) ;
831865 return float ( Math . ceil ( toFloat ( x ! ) ) ) ;
832866 }
867+ case 'col' : {
868+ const [ s ] = getArgs ( 1 ) ;
869+ return int ( getpos ( toString ( s ! ) ) . col ) ;
870+ }
833871 case 'copy' : {
834872 const [ x ] = getArgs ( 1 ) ;
835873 switch ( x ?. type ) {
@@ -891,6 +929,7 @@ export class EvaluationContext {
891929 }
892930 return int ( count ) ;
893931 }
932+ // TODO: cursor()
894933 case 'deepcopy' : {
895934 // TODO: real deep copy once references are implemented
896935 const [ x ] = getArgs ( 1 ) ;
@@ -1028,6 +1067,11 @@ export class EvaluationContext {
10281067 }
10291068 // TODO: getcurpos()
10301069 // TODO: getline()
1070+ case 'getpos' : {
1071+ const [ s ] = getArgs ( 1 ) ;
1072+ const { bufnum, lnum, col, off } = getpos ( toString ( s ! ) ) ;
1073+ return list ( [ int ( bufnum ) , int ( lnum ) , int ( col ) , int ( off ) ] ) ;
1074+ }
10311075 // TODO: getreg()
10321076 // TODO: getreginfo()
10331077 // TODO: getregtype()
@@ -1199,6 +1243,10 @@ export class EvaluationContext {
11991243 throw VimError . fromCode ( ErrorCode . InvalidTypeForLen ) ;
12001244 }
12011245 }
1246+ case 'line' : {
1247+ const [ s , winid ] = getArgs ( 1 , 2 ) ;
1248+ return int ( getpos ( toString ( s ! ) ) . lnum ) ;
1249+ }
12021250 case 'localtime' : {
12031251 return int ( Date . now ( ) / 1000 ) ;
12041252 }
@@ -1354,6 +1402,7 @@ export class EvaluationContext {
13541402 // Halfway between integers, Math.round() rounds toward infinity while Vim's round() rounds away from 0.
13551403 return float ( _x < 0 ? - Math . round ( - _x ) : Math . round ( _x ) ) ;
13561404 }
1405+ // TODO: setpos()
13571406 // TODO: setreg()
13581407 case 'sin' : {
13591408 const [ x ] = getArgs ( 1 ) ;
@@ -1476,6 +1525,7 @@ export class EvaluationContext {
14761525 const [ x ] = getArgs ( 1 ) ;
14771526 return float ( Math . tanh ( toFloat ( x ! ) ) ) ;
14781527 }
1528+ // TODO: timer*()
14791529 case 'tolower' : {
14801530 const [ s ] = getArgs ( 1 ) ;
14811531 return str ( toString ( s ! ) . toLowerCase ( ) ) ;
0 commit comments