1 | /****************************** Module Header *******************************
|
---|
2 | *
|
---|
3 | * Module Name: assist.e
|
---|
4 | *
|
---|
5 | * Copyright (c) Netlabs EPM Distribution Project 2002
|
---|
6 | *
|
---|
7 | * $Id: assist.e 4348 2020-12-17 09:43:13Z aschn $
|
---|
8 | *
|
---|
9 | * ===========================================================================
|
---|
10 | *
|
---|
11 | * This file is part of the Netlabs EPM Distribution package and is free
|
---|
12 | * software. You can redistribute it and/or modify it under the terms of the
|
---|
13 | * GNU General Public License as published by the Free Software
|
---|
14 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
15 | * Netlabs EPM Distribution. This library is distributed in the hope that it
|
---|
16 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
---|
17 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
18 | * General Public License for more details.
|
---|
19 | *
|
---|
20 | ****************************************************************************/
|
---|
21 |
|
---|
22 | /*****************************************************************************/
|
---|
23 | /* Assist interface for E3 Ralph Yozzo, Larry Margolis */
|
---|
24 | /* */
|
---|
25 | /* This macro is intended for use with programming language */
|
---|
26 | /* which have tokens which must be balanced to compile correctly. */
|
---|
27 | /* We shall call these tokens "balanceable tokens" or BalTok for */
|
---|
28 | /* short. */
|
---|
29 | /* */
|
---|
30 | /* The functions provided include moving from an opening token */
|
---|
31 | /* (e.g., (, {, [ ) to a closing token (e.g., ), }, ] ) and vice versa. */
|
---|
32 | /* */
|
---|
33 | /* KEYS: */
|
---|
34 | /* Ctrl-[, Ctrl-], Ctrl-8 -- move to corresponding BalTok) */
|
---|
35 | /* */
|
---|
36 | /* CONSTANTS: */
|
---|
37 | /* gold -BalTok tokens are defined in the const gold and additional */
|
---|
38 | /* tokens may be added. */
|
---|
39 | /* */
|
---|
40 | /* Example: */
|
---|
41 | /* if ((c=getch())=='c' */
|
---|
42 | /* &&(d=complicatedisntit(e))){ */
|
---|
43 | /* lookforbracket(); */
|
---|
44 | /* } */
|
---|
45 | /* In the above program segment if one places the cursor on an opening */
|
---|
46 | /* parenthesis and presses Ctrl-[ the cursor will move to the corresponding */
|
---|
47 | /* closing parenthesis if one exists. Pressing Ctrl-[ again will reverse */
|
---|
48 | /* the process. */
|
---|
49 | /* */
|
---|
50 | /* Modified by Larry Margolis to use the GREP option of Locate to search */
|
---|
51 | /* for either the opening or closing token, rather than checking a line at */
|
---|
52 | /* a time. I also changed the key from Ctrl-A to Ctrl-[ or -], which are */
|
---|
53 | /* newly allowed as definable keys, and deleted the matching of /* and */. */
|
---|
54 | /* (The GREP search is much faster than the way Ralph did it, but doesn't */
|
---|
55 | /* let you match either of 2 strings.) Finally, the user's previous search */
|
---|
56 | /* arguments are saved and restored, so Ctrl-F (repeatfind) will not be */
|
---|
57 | /* affected by this routine. */
|
---|
58 | /* */
|
---|
59 | /* Updated by LAM to use EGREP to also handle #if, #endif, etc. and COMPILE */
|
---|
60 | /* IF, COMPILE ENDIF, etc. */
|
---|
61 | /* */
|
---|
62 | /* 1995/02/21 Updated by LAM to also handle SCRIPT list tags and /* */. */
|
---|
63 | /* 1995/02/22 Updated by LAM to also handle SGML tags. */
|
---|
64 | /* */
|
---|
65 | /* 1999/03/15 Updated by Petr Mikulik, http://www.sci.muni.cz/~mikulik/, to */
|
---|
66 | /* also handle TeX tokens: \if... \else \fi; \begin... \end...; */
|
---|
67 | /* \if... \else \fi; \begin{ \end{; \left \right */
|
---|
68 | /* This patch is part of the "pmCSTeX for EPM" package, see */
|
---|
69 | /* http://www.sci.muni.cz/~mikulik/os2/pmCSTeX.html */
|
---|
70 | /*****************************************************************************/
|
---|
71 |
|
---|
72 | ; Included TeX extensions for the pAssist procedure by Petr Mikulik from his
|
---|
73 | ; PMCSTeX package.
|
---|
74 |
|
---|
75 | ; 2006 changes: JBS
|
---|
76 | ; A major rework of the code:
|
---|
77 | ; o Bugs were fixed.
|
---|
78 | ; o More tokens are balanced, including the start and end points of
|
---|
79 | ; multi-line comments.
|
---|
80 | ; o More modes supported (PASCAL, FORTRAN77, JAVA, WARPIN).
|
---|
81 | ; o Added initial stages of support for ADA, CSS, PERL, PHP.
|
---|
82 | ; o Code was added to ensure tokens found within comments or literals were
|
---|
83 | ; not matched.
|
---|
84 | ; o Better variable names and code documentation.
|
---|
85 | ; o Contains procs that return if a position is within a multi-line commemt,
|
---|
86 | ; single-line comment or literal.
|
---|
87 | ; o Added a multi-line comment (MLC) array to speed up searching and for
|
---|
88 | ; making MLC matching for modes with nested MLCs reliable.
|
---|
89 |
|
---|
90 | ; After that: aschn
|
---|
91 | ; o Commented out debug messages (minor speed improvement).
|
---|
92 | ; o Replaced searching in the MLC array (big speed improvement).
|
---|
93 | ; o Renamed procs and vars.
|
---|
94 | ; o Added more procs for use from outside.
|
---|
95 | ; o Added optional line and col parameters for querying another than
|
---|
96 | ; current position.
|
---|
97 | ; o Use the comment and literal procs now by tags and syntax expansion.
|
---|
98 |
|
---|
99 | ; 2020 changes: aschn
|
---|
100 | ; o Building the multi-line comment (MLC) array takes much time for longer
|
---|
101 | ; files. For MatchFindOnMove (matching brackets while moving the cursor),
|
---|
102 | ; a simple method is used instead to keep cursor movement fluently. For
|
---|
103 | ; modes that support nested MLCs (E and REXX), the MLC array has to be
|
---|
104 | ; built to determine the within-comment state.
|
---|
105 | ; o That simple method just checks if the previous found MLC string is a
|
---|
106 | ; start or end string. From that, the in-MLC state is determined.
|
---|
107 | ; o If a valid MLC array exists, that one is always used with precedence.
|
---|
108 | ; o The MLC array method is also used for other cases than MatchFindOnMove.
|
---|
109 | ; By the way: For larger files and e.g. TagScan, the array method is
|
---|
110 | ; multiple (something like ten) times faster.
|
---|
111 |
|
---|
112 | ; Ideas:
|
---|
113 | ; o Use attributes for marking MLCs and scan only that region that has
|
---|
114 | ; changed.
|
---|
115 | ; o Use attributes for tags and scan only that region that has changed.
|
---|
116 |
|
---|
117 | compile if not defined( SMALL) -- If compiled separately
|
---|
118 | EA_comment 'Linkable bracket-matching routines.'
|
---|
119 |
|
---|
120 | define
|
---|
121 | INCLUDING_FILE = 'ASSIST.E'
|
---|
122 |
|
---|
123 | include 'stdconst.e'
|
---|
124 | const
|
---|
125 | tryinclude 'mycnf.e'
|
---|
126 | const
|
---|
127 | compile if not defined( NLS_LANGUAGE)
|
---|
128 | NLS_LANGUAGE = 'ENGLISH'
|
---|
129 | compile endif
|
---|
130 | include NLS_LANGUAGE'.e'
|
---|
131 |
|
---|
132 | defmain
|
---|
133 | 'Assist'
|
---|
134 | compile endif -- not defined(SMALL)
|
---|
135 |
|
---|
136 | ; ---------------------------------------------------------------------------
|
---|
137 | const
|
---|
138 | -- NOTE: The logic below relies on GOLD being defined with the left
|
---|
139 | -- "brackets" in the odd positions and the right "brackets" in
|
---|
140 | -- the even positions.
|
---|
141 | GOLD = '(){}[]<>' -- Parens, braces, brackets & angle brackets
|
---|
142 |
|
---|
143 | ASSIST_RC_MLC_MATCHED = -1
|
---|
144 | ASSIST_RC_NO_ERROR = 0
|
---|
145 | ASSIST_RC_IN_ONELINE_COMMENT = 1
|
---|
146 | ASSIST_RC_IN_MULTILINE_COMMENT = 2
|
---|
147 | ASSIST_RC_IN_LITERAL = 3
|
---|
148 | ASSIST_RC_NOT_ON_A_TOKEN = 4
|
---|
149 | ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN = 5
|
---|
150 | ASSIST_RC_BAD_FORTRAN77_CURSOR = 6
|
---|
151 | ASSIST_RC_MODE_NOT_SUPPORTED = 7
|
---|
152 | ASSIST_RC_TOO_MANY_LINES = 8
|
---|
153 | ASSIST_RC_TOO_MANY_LOOPS = 9
|
---|
154 |
|
---|
155 | EGREP_METACHARACTERS = '\[]()?+*^$.|' -- JBSQ: This may need to changed if the grep code
|
---|
156 | -- ever supports {, } and possibly other egrep metacharacters
|
---|
157 |
|
---|
158 | -- JBSQ: The following constants 'hard-code' the versions of NMAKE and
|
---|
159 | -- FORTRAN77 for which pAssist works. Perhaps there is a better way
|
---|
160 | -- that would allow this to be selected by the user?
|
---|
161 | compile if not defined( USE_NMAKE32)
|
---|
162 | USE_NMAKE32 = 1 -- 0 means do not accept NMAKE32-specific directives
|
---|
163 | compile endif
|
---|
164 | compile if not defined( USE_FORTRAN90_SLC)
|
---|
165 | USE_FORTRAN90_SLC = 1 -- 0 means disregard FORTRAN90 SLC: '!'
|
---|
166 | compile endif
|
---|
167 |
|
---|
168 | compile if not defined( ASSIST_DEFAULT_MAX_LINES)
|
---|
169 | ASSIST_DEFAULT_MAX_LINES = 2000
|
---|
170 | compile endif
|
---|
171 | compile if not defined( ASSIST_DEFAULT_MAX_LOOPS)
|
---|
172 | ASSIST_DEFAULT_MAX_LOOPS = 500
|
---|
173 | compile endif
|
---|
174 |
|
---|
175 | ; ---------------------------------------------------------------------------
|
---|
176 | ; Syntax: Assist [quiet] [[<max_lines>] <max_loops>]
|
---|
177 | defc Assist
|
---|
178 | universal vepm_pointer
|
---|
179 |
|
---|
180 | parse arg args
|
---|
181 | wp = wordpos( 'QUIET', upcase( args))
|
---|
182 | fQuiet = (wp > 0)
|
---|
183 | if wp then
|
---|
184 | args = delword( args, wp, 1)
|
---|
185 | endif
|
---|
186 | if fQuiet then
|
---|
187 | VerboseLevel = 0 -- 0 = quiet, no 'Invalid:' etc. messages (0 also disables pointer change)
|
---|
188 | else
|
---|
189 | VerboseLevel = 1 -- 1 = normal
|
---|
190 | endif
|
---|
191 | parse value args with MaxLines MaxLoops
|
---|
192 | MaxLines = strip( MaxLines)
|
---|
193 | MaxLoops = strip( MaxLoops)
|
---|
194 |
|
---|
195 | if VerboseLevel <> 0 then
|
---|
196 | mouse_setpointer WAIT_POINTER
|
---|
197 | endif
|
---|
198 | fHighlight = 1
|
---|
199 | fUseArray = 1
|
---|
200 | call pAssist( VerboseLevel, fHighlight, MaxLines, MaxLoops, fUseArray)
|
---|
201 | if VerboseLevel <> 0 then
|
---|
202 | mouse_setpointer vepm_pointer
|
---|
203 | endif
|
---|
204 |
|
---|
205 | ; ---------------------------------------------------------------------------
|
---|
206 | ; id = found word under cursor (or beneath the cursor in some cases)
|
---|
207 | ; fIntermediate = set to 1 if id is an intermediate conditional token
|
---|
208 | ; (e.g. 'else', but not 'if' or 'endif')
|
---|
209 | ; fForward = a flag to indicate which direction to search
|
---|
210 | ; 1 = forward, 0 = backward
|
---|
211 | ; SearchStr = string for locate command, without seps and options,
|
---|
212 | ; egrep will be used
|
---|
213 | ; clist = a space delimited list of substrings to match on. Usually this
|
---|
214 | ; is a single substring. An example of multiple substrings in
|
---|
215 | ; clist would be that an "end" in REXX mode can match up with
|
---|
216 | ; either a "do" or a "select" statement. If fForward = 1 then
|
---|
217 | ; these substrings should identify the starting token(s) of the
|
---|
218 | ; bracketed code. If fForward = 0 then these substrings should
|
---|
219 | ; identify the ending token(s).
|
---|
220 | ; coffset = offset from cursor pos after the search to substring to match
|
---|
221 | ; The cursor pos, specified with \c in the regex, marks also
|
---|
222 | ; the begin of the highlighted string.
|
---|
223 | ; clen = the length of the substrings in clist
|
---|
224 | ; hcol = the start pos of the highlighted string for intermediate
|
---|
225 | ; tokens (e.g. else, elseif). The first search is suppressed
|
---|
226 | ; for them, so that no search data exists for them. If not
|
---|
227 | ; specified, the start is determined from the id at the
|
---|
228 | ; cursor.
|
---|
229 | ; hlen = the length of the highlighted string for intermediate
|
---|
230 | ; tokens (e.g. else, elseif). The first search is suppressed
|
---|
231 | ; for them, so that no search data exists for them. If not
|
---|
232 | ; specified, the length is determined from the id at the
|
---|
233 | ; cursor.
|
---|
234 | ; nestlevel = counter for nesting of matched tokens. On nestlevel = 0,
|
---|
235 | ; the matched token was found.
|
---|
236 | ; startcol = the pos of id start in current line
|
---|
237 | ; endcol = the pos of id end (last char of id)
|
---|
238 | ; TexEnvStr = a string to submit the searched TEX environment, surrounded
|
---|
239 | ; by braces and preceded by '\begin' or \'end'.
|
---|
240 | ; fEExcludeCompile = a flag to indicate if an E condition is not preceded by
|
---|
241 | ; 'compile'.
|
---|
242 | ; 1 = 'compile' excluded, 0 = not excluded or not a condition.
|
---|
243 | ; 'compile if|...' uses 0, 'if|...' uses 1.
|
---|
244 | defproc pAssist
|
---|
245 | universal lastassistpos
|
---|
246 |
|
---|
247 | call pSave_Pos( savepos) -- Save the cursor location
|
---|
248 | getsearch search_command -- Save user's search command.
|
---|
249 |
|
---|
250 | StartLineNum = .line
|
---|
251 | VerboseLevel = arg( 1) -- 0 = quiet (default), 1 = normal
|
---|
252 | fHighlight = arg( 2) -- 1 = highlighting of matching expression and scrolling
|
---|
253 | -- 0 = no highlighting (default)
|
---|
254 | MaxLines = arg( 3)
|
---|
255 | MaxLoops = arg( 4)
|
---|
256 | fUseArray = arg( 5)
|
---|
257 | if VerboseLevel < 1 then
|
---|
258 | VerboseLevel = 0
|
---|
259 | endif
|
---|
260 | if fHighlight <> 1 then
|
---|
261 | fHighlight = 0
|
---|
262 | endif
|
---|
263 | if MaxLines = '' then
|
---|
264 | MaxLines = ASSIST_DEFAULT_MAX_LINES
|
---|
265 | endif
|
---|
266 | if MaxLoops = '' then
|
---|
267 | MaxLoops = ASSIST_DEFAULT_MAX_LOOPS
|
---|
268 | endif
|
---|
269 | if not wordpos( fUseArray, '0 1') then
|
---|
270 | fUseArray = 1 -- default value
|
---|
271 | endif
|
---|
272 | -- The non-array version can not be used for retrieving pos. data or for
|
---|
273 | -- finding the matching MLC string. It should only be used for
|
---|
274 | -- MatchFindOnMove. For repeated use and long texts, the array version
|
---|
275 | -- is much faster. It causes a short delay to scan the entire file and
|
---|
276 | -- leads to non-fluently cursor move.
|
---|
277 | call SetAvar( 'assist.fUseArray', fUseArray)
|
---|
278 | SearchLimitData = StartLineNum MaxLines MaxLoops -- Use one arg for AssistSearch to save args
|
---|
279 |
|
---|
280 | case = 'e' -- respect case is default
|
---|
281 | coffset = 0 -- cursor offset for clist keyword(s) after the search
|
---|
282 | clen = 1
|
---|
283 | hcol = 0
|
---|
284 | hlen = 0
|
---|
285 | fIntermediate = 0
|
---|
286 | fForward = 1
|
---|
287 | nestlevel = 1
|
---|
288 | TexEnvStr = ''
|
---|
289 | fEExcludeCompile = 0
|
---|
290 |
|
---|
291 | id = '' -- token under cursor
|
---|
292 | startcol = 1 -- start column of id/token
|
---|
293 | endcol = 1 -- end column of id/token
|
---|
294 | SearchStr = ''
|
---|
295 |
|
---|
296 | -- Init search position data for highlighting
|
---|
297 | HighlightLine = .line
|
---|
298 | HighlightCol = .col
|
---|
299 | HighlightLen = 1
|
---|
300 |
|
---|
301 | --#dprintf( "pAssist", "------------------------------------------------------------")
|
---|
302 | --#dprintf( "pAssist", "Initial cursor: ".line",".col)
|
---|
303 | CurMode = NepmdGetMode()
|
---|
304 | lastassistpos = '0 0 0'
|
---|
305 |
|
---|
306 | -- These are MLCs in E and just be better used as variables to allow
|
---|
307 | -- using them as MLCs in E:
|
---|
308 | SlashStar = '/'||'*'
|
---|
309 | StarSlash = '*'||'/'
|
---|
310 |
|
---|
311 | do once = 1 to 1
|
---|
312 | assist_rc = InsideComment2( CurMode, CommentData)
|
---|
313 | -- InsideComment2 -> LocateMLC may have changed fUseArray for modes
|
---|
314 | -- that support nested MLCs
|
---|
315 | fUseArray = GetAvar( 'assist.fUseArray')
|
---|
316 |
|
---|
317 | --#dprintf( "pAssist", "comment return:" assist_rc CommentData)
|
---|
318 | if assist_rc = ASSIST_RC_IN_MULTILINE_COMMENT then
|
---|
319 | parse value CommentData with CommentStartLine CommentStartCol CommentStartLen CommentEndLine CommentEndCol CommentEndLen
|
---|
320 |
|
---|
321 | if fUseArray then
|
---|
322 | if .line = CommentStartLine & .col - CommentStartCol < CommentStartLen then -- if cursor on start
|
---|
323 | .line = CommentEndLine -- move to the end
|
---|
324 | .col = CommentEndCol
|
---|
325 | HighlightLine = CommentStartLine
|
---|
326 | HighlightCol = CommentStartCol
|
---|
327 | HighlightLen = CommentStartLen
|
---|
328 | elseif .line = CommentEndLine & .col >= CommentEndCol then -- if cursor on end
|
---|
329 | .line = CommentStartLine -- move to the start
|
---|
330 | .col = CommentStartCol
|
---|
331 | HighlightLine = CommentEndLine
|
---|
332 | HighlightCol = CommentEndCol
|
---|
333 | HighlightLen = CommentEndLen
|
---|
334 | endif
|
---|
335 | endif
|
---|
336 |
|
---|
337 | assist_rc = ASSIST_RC_MLC_MATCHED
|
---|
338 | leave
|
---|
339 | endif
|
---|
340 |
|
---|
341 | if InsideLiteral( CurMode) then
|
---|
342 | assist_rc = ASSIST_RC_IN_LITERAL
|
---|
343 | leave
|
---|
344 | endif
|
---|
345 |
|
---|
346 | getline LineStr
|
---|
347 | CurChar = substr( LineStr, .col, 1)
|
---|
348 | /*
|
---|
349 | -- Make Assist work if the cursor is just after a keyword
|
---|
350 | -- If c = space, then try it 1 col left
|
---|
351 | if (CurChar == ' ' | CurChar == \t) & .col > 1 then
|
---|
352 | left
|
---|
353 | CurChar = substr( LineStr, .col, 1)
|
---|
354 | endif
|
---|
355 | */
|
---|
356 |
|
---|
357 | -- Determine SearchStr and vars for brackets
|
---|
358 | BracketChar = pos( CurChar, GOLD) -- '(){}[]<>'
|
---|
359 | -- Braces, '{}', can be matched with BEGIN and END in RC files.
|
---|
360 | -- So they need to be handled separately.
|
---|
361 | if BracketChar then
|
---|
362 | if pos( CurChar, '{}') & CurMode = 'RC' then
|
---|
363 | BracketChar = 0
|
---|
364 | endif
|
---|
365 | endif
|
---|
366 | -- If BracketChar, then set SearchStr to the corresponding char out of GOLD
|
---|
367 | if BracketChar then
|
---|
368 | leftbracket = substr( GOLD, (BracketChar + 1) % 2 * 2 - 1, 1)
|
---|
369 | rightbracket = substr( GOLD, (BracketChar + 1) % 2 * 2, 1)
|
---|
370 | -- Escape brackets with '\'
|
---|
371 | SearchStr = '[\'leftbracket'\'rightbracket']'
|
---|
372 | clist = CurChar
|
---|
373 | fForward = BracketChar // 2
|
---|
374 | leave
|
---|
375 | endif
|
---|
376 |
|
---|
377 | -- Build the separator list for find_token
|
---|
378 | if CurMode = 'FORTRAN77' then
|
---|
379 | seps = "+-*/=().,':$"
|
---|
380 | else
|
---|
381 | seps = ' ~`!.%^&*()-+=][{}|\;?<>,''"'\t
|
---|
382 | endif
|
---|
383 |
|
---|
384 | if CurMode = 'TEX' then
|
---|
385 | -- Move cursor right if it is on \backslash
|
---|
386 | if substr( LineStr, .col, 1) = '\' then
|
---|
387 | right
|
---|
388 | endif
|
---|
389 | endif
|
---|
390 |
|
---|
391 | -- Get the word under cursor and return startcol and endcol
|
---|
392 | -- Stop at separators = arg( 3)
|
---|
393 | -- Stop at double char separators = arg( 4)
|
---|
394 | -- Checking for SlashStar and StarSlash is not required here, because of
|
---|
395 | -- the MLC search above.
|
---|
396 | if not Find_Token( startcol, endcol, seps, 'NONE:') then
|
---|
397 | assist_rc = ASSIST_RC_NOT_ON_A_TOKEN
|
---|
398 | leave
|
---|
399 | endif
|
---|
400 |
|
---|
401 | --#dprintf( "pAssist", "Initial token start,end: "startcol","endcol)
|
---|
402 | if startcol > 1 then
|
---|
403 | prevchar = substr( LineStr, startcol - 1, 1)
|
---|
404 | if prevchar = '<' then
|
---|
405 | if CurMode = 'HTML' | CurMode = 'WARPIN' /* | CurMode = 'XML' */ then
|
---|
406 | -- Add '<' to found word if it is on the left side of it
|
---|
407 | -- this assumes ALL balanceable tokens for HTML and WARPIN
|
---|
408 | -- start with '<'
|
---|
409 | startcol = startcol - 1
|
---|
410 | endif
|
---|
411 | elseif prevchar = '\' then
|
---|
412 | if CurMode = 'TEX' then
|
---|
413 | --//PM TeX macros are preceded by \backslash which is also separator
|
---|
414 | -- Add '\' to found word if it is on the left side of it
|
---|
415 | startcol = startcol - 1
|
---|
416 | endif
|
---|
417 | endif
|
---|
418 | elseif startcol = 1 then -- if cursor is on the first column of a MAKE directive
|
---|
419 | if leftstr( LineStr, 1) = '!' then -- "shift" the id to the following token
|
---|
420 | if CurMode = 'MAKE' then
|
---|
421 | newstart = verify( LineStr, ' '\t, 'N', 2) -- skip to next non-whitespace
|
---|
422 | if newstart then
|
---|
423 | newend = verify( LineStr' ', ' ', 'M', newstart)
|
---|
424 | if newend then
|
---|
425 | startcol = newstart
|
---|
426 | endcol = newend - 1
|
---|
427 | endif
|
---|
428 | endif
|
---|
429 | endif
|
---|
430 | endif
|
---|
431 | endif
|
---|
432 |
|
---|
433 | -- id = found word
|
---|
434 | id = substr( LineStr, startcol, (endcol - startcol) + 1)
|
---|
435 | --#dprintf( "pAssist", "Token after preprocessing : '"id"' Startcol: "startcol" Endcol: "endcol)
|
---|
436 |
|
---|
437 | -- Set/re-init search position data for highlighting
|
---|
438 | HighlightLine = .line
|
---|
439 | HighlightCol = startcol
|
---|
440 | HighlightLen = endcol - startcol + 1
|
---|
441 |
|
---|
442 | if 0 then
|
---|
443 | -- just a placeholder so the following ELSEIFs can be freely reordered
|
---|
444 |
|
---|
445 | -- Mode(s): E -------------------------------------------------------------------------------
|
---|
446 | elseif CurMode = 'E' then
|
---|
447 |
|
---|
448 | --dprintf( "pAssist", "E Token after : '"id"'")
|
---|
449 | case = 'c' -- Case insensitive for all E tokens
|
---|
450 | id = lowcase( id)
|
---|
451 | LineStr = lowcase( LineStr)
|
---|
452 | if 0 then
|
---|
453 | -- another placeholder
|
---|
454 |
|
---|
455 | ---- E compiler directives: compile if, compile else, compile elseif, compile endif
|
---|
456 | elseif id = 'compile' then
|
---|
457 | temp = substr( LineStr, pos( id, LineStr))
|
---|
458 | --#dprintf( "pAssist", "Initial temp: "temp)
|
---|
459 | do while (pos( SlashStar, temp) > 0) & (pos( StarSlash, temp) > 0)
|
---|
460 | temp = substr( temp, pos( StarSlash, temp))
|
---|
461 | --#dprintf( "pAssist", "Intermediate temp: "temp)
|
---|
462 | enddo
|
---|
463 | --#dprintf( "pAssist", "Final temp: "temp)
|
---|
464 | if (words( temp) = 0) then
|
---|
465 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
466 | else
|
---|
467 | lcword2 = word( temp, 2)
|
---|
468 | --#dprintf( "pAssist", "lcword2: "lcword2)
|
---|
469 | if wordpos( lcword2, 'if endif else elseif') then
|
---|
470 | pcompile = pos( 'compile', LineStr)
|
---|
471 | pcondition = pos( lcword2, LineStr, pcompile + 8)
|
---|
472 | coffset = pcondition - pcompile
|
---|
473 | hcol = pcompile
|
---|
474 | hlen = pcondition + length( lcword2) - pcompile
|
---|
475 | -- compile if/... code (when cursor is on compile
|
---|
476 | SearchStr = '^[ \t]*\ccompile[ \t]*(/\*.*\*/)*[ \t]*(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
477 | clist = leftstr( lcword2, 1)
|
---|
478 | fForward = (clist <> 'e')
|
---|
479 | if fForward then -- move to beginning
|
---|
480 | .col = startcol
|
---|
481 | else -- move to end, so first Locate will hit this instance.
|
---|
482 | endline
|
---|
483 | endif
|
---|
484 | fIntermediate = (substr( lcword2, 2, 1) = 'l')
|
---|
485 | else
|
---|
486 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
487 | endif
|
---|
488 | endif
|
---|
489 |
|
---|
490 | ---- E conditions: (compile) if, (compile) else, (compile) elseif, (compile) endif
|
---|
491 | elseif wordpos( id, 'if endif else elseif') then
|
---|
492 | pcompile = pos( 'compile', LineStr)
|
---|
493 | if pcompile & pcompile <= startcol then
|
---|
494 | -- compile if|endif|else|elseif
|
---|
495 | parse value LineStr with part1 'compile' part2 (id) part3
|
---|
496 | --#dprintf( 'pAssist', 'E if parse: "'part1'"compile"'part2'"'id'"'part3'"')
|
---|
497 | part1 = strip( part1)
|
---|
498 | part2 = strip( part2)
|
---|
499 | if (part1 = '' | ((length( part1) >= 4) & (leftstr( part1, 2) = SlashStar) & (rightstr( part1, 2) = StarSlash))) &
|
---|
500 | (part2 = '' | ((length( part2) >= 4) & (leftstr( part2, 2) = SlashStar) & (rightstr( part2, 2) = StarSlash))) then
|
---|
501 | pcompile = pos( 'compile', LineStr)
|
---|
502 | pcondition = pos( id, LineStr, pcompile + 8)
|
---|
503 | coffset = pcondition - pcompile
|
---|
504 | hcol = pcompile
|
---|
505 | hlen = pcondition + length( id) - pcompile
|
---|
506 | -- compile if/... code (when cursor is on if/...
|
---|
507 | --SearchStr = '^[ \t]*compile[ \t]*(/\*.*\*/)*[ \t]*\c(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
508 | SearchStr = '^[ \t]*\ccompile[ \t]*(/\*.*\*/)*[ \t]*(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
509 | clist = leftstr( id, 1)
|
---|
510 | fForward = (clist <> 'e')
|
---|
511 | if fForward then -- move to beginning
|
---|
512 | .col = length( part1) + 1
|
---|
513 | else -- move to end, so first Locate will hit this instance.
|
---|
514 | endline
|
---|
515 | endif
|
---|
516 | fIntermediate = (substr( id, 2, 1) = 'l')
|
---|
517 | else
|
---|
518 | -- /* compile */ if/... code
|
---|
519 | SearchStr = '(^|[ \t]|(\*/))\c(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
520 | clist = leftstr( id, 1)
|
---|
521 | fForward = (clist <> 'e')
|
---|
522 | if fForward then -- move to beginning
|
---|
523 | .col = startcol
|
---|
524 | else -- move to end, so first Locate will hit this instance.
|
---|
525 | .col = endcol
|
---|
526 | endif
|
---|
527 | fIntermediate = (substr( id, 2, 1) = 'l')
|
---|
528 | endif
|
---|
529 | else
|
---|
530 | -- if|endif (without compile)
|
---|
531 | -- The found line is checked by a 2nd search for a preceding 'compile',
|
---|
532 | -- otherwise the re would have two many parentheses.
|
---|
533 | fEExcludeCompile = 1
|
---|
534 | --SearchStr = '((\*/:o)|(^:o)|(^:o(~compile:w)))\c(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
535 | --SearchStr = '((\*/:o)|(;:o)|(^:o)|(^:o(~compile:w)))\c(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
536 | SearchStr = '(^|[ \t]|(\*/))\c(end)?if([; \t]|(--)|(/\*)|$)'
|
---|
537 | clist = leftstr( id, 1)
|
---|
538 | fForward = (clist <> 'e')
|
---|
539 | if fForward then -- move to beginning
|
---|
540 | .col = startcol
|
---|
541 | else -- move to end, so first Locate will hit this instance.
|
---|
542 | .col = endcol
|
---|
543 | endif
|
---|
544 | fIntermediate = (substr( id, 2, 1) = 'l')
|
---|
545 | endif
|
---|
546 |
|
---|
547 | ---- E loop keywords 1: loop, endloop
|
---|
548 | elseif wordpos( id, 'loop endloop') then
|
---|
549 | SearchStr = '(^|[ \t]|(\*/))\c(end)?loop([; \t]|(--)|(/\*)|$)'
|
---|
550 | clist = leftstr( id, 1)
|
---|
551 | fForward = (clist <> 'e')
|
---|
552 | if fForward then -- move to beginning
|
---|
553 | .col = startcol
|
---|
554 | else -- move to end, so first Locate will hit this instance.
|
---|
555 | .col = endcol
|
---|
556 | endif
|
---|
557 |
|
---|
558 | ---- E loop keywords 2: for, endfor
|
---|
559 | elseif wordpos( id, 'for endfor') then
|
---|
560 | SearchStr = '(^|[ \t]|(\*/))\c(end)?for([; \t]|(--)|(/\*)|$)'
|
---|
561 | clist = leftstr( id, 1)
|
---|
562 | fForward = (clist <> 'e')
|
---|
563 | if fForward then -- move to beginning
|
---|
564 | .col = startcol
|
---|
565 | else -- move to end, so first Locate will hit this instance.
|
---|
566 | .col = endcol
|
---|
567 | endif
|
---|
568 |
|
---|
569 | ---- E loop keywords 3: do, while, end, enddo, endwhile
|
---|
570 | elseif wordpos( id, 'do while end enddo endwhile') then
|
---|
571 | if (id = 'end') then
|
---|
572 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo)([; \t]|(--)|(/\*)|$)'
|
---|
573 | elseif (id = 'enddo') then
|
---|
574 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo)([; \t]|(--)|(/\*)|$)'
|
---|
575 | elseif (id = 'endwhile') then
|
---|
576 | SearchStr = '(^|[ \t]|(\*/))\c(end)?while([; \t]|(--)|(/\*)|$)'
|
---|
577 | else -- check for do and/or while
|
---|
578 | whilepos = wordpos( 'while', LineStr)
|
---|
579 | dopos = wordpos( 'do', LineStr)
|
---|
580 | if (not dopos) | (whilepos & (whilepos < dopos)) then -- while or while ... do?
|
---|
581 | SearchStr = '(^|[ \t]|(\*/))\c(end)?while([; \t]|(--)|(/\*)|$)'
|
---|
582 | startcol = whilepos
|
---|
583 | endcol = whilepos + 4
|
---|
584 | else -- do or do ... while
|
---|
585 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo)([; \t]|(--)|(/\*)|$)'
|
---|
586 | startcol = dopos
|
---|
587 | endcol = dopos + 1
|
---|
588 | endif
|
---|
589 | compile if 0
|
---|
590 | if whilepos & dopos then -- if both
|
---|
591 | if whilepos < dopos then -- while ... do ?
|
---|
592 | SearchStr = '(^|[ \t]|(\*/))\c(end)?while([; \t]|(--)|(/\*)|$)'
|
---|
593 | startcol = whilepos
|
---|
594 | endcol = whilepos + 4
|
---|
595 | else -- do ... while
|
---|
596 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo)([; \t]|(--)|(/\*)|$)'
|
---|
597 | startcol = dopos
|
---|
598 | endcol = dopos + 1
|
---|
599 | endif
|
---|
600 | else
|
---|
601 | if dopos then -- do
|
---|
602 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo)([; \t]|(--)|(/\*)|$)'
|
---|
603 | else -- while
|
---|
604 | SearchStr = '(^|[ \t]|(\*/))\c(end)?while([; \t]|(--)||(/\*)$)'
|
---|
605 | endif
|
---|
606 | endif
|
---|
607 | compile endif
|
---|
608 | --#dprintf( "pAssist", "Whilepos: "whilepos "Dopos: "dopos "SearchStr: "SearchStr)
|
---|
609 | endif
|
---|
610 | clist = leftstr( id, 1)
|
---|
611 | --#dprintf( "pAssist", "clist: "clist)
|
---|
612 | fForward = (clist <> 'e')
|
---|
613 | if fForward then -- move to beginning
|
---|
614 | .col = startcol
|
---|
615 | else -- move to end, so first Locate will hit this instance.
|
---|
616 | .col = endcol
|
---|
617 | endif
|
---|
618 |
|
---|
619 | ---- E loop keywords 4: leave, iterate
|
---|
620 | elseif wordpos( id, 'leave iterate') then
|
---|
621 | SearchStr = '(^|[ \t]|(\*/))\c(do|end|enddo|loop|endloop|for|endfor|endwhile)([; \t]|(--)|(/\*)|$)'
|
---|
622 | fForward = 0
|
---|
623 | clist = 'e'
|
---|
624 | clen = 1
|
---|
625 | .col = endcol
|
---|
626 | fIntermediate = 1
|
---|
627 |
|
---|
628 | else -- not a known balanceable E token
|
---|
629 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
630 | endif
|
---|
631 |
|
---|
632 | -- Mode(s): C, JAVA JAVASCRIPT and RC -------------------------------------------------------
|
---|
633 | elseif wordpos( CurMode, 'C JAVA RC JAVASCRIPT') > 0 then
|
---|
634 |
|
---|
635 | -- C allows for spaces between '#' and keyword, JAVA, RC and JAVASCRIPT don't.
|
---|
636 | if CurMode = 'C' then
|
---|
637 | if wordpos( id, 'if ifdef ifndef endif else elif') > 0 then -- Check for "# if", etc.
|
---|
638 | .col = startcol
|
---|
639 | if NextCodeChar( Mode, .line, .col, '-R') = '#' then
|
---|
640 | id = '#'id
|
---|
641 | startcol = .col
|
---|
642 | endif
|
---|
643 | call pRestore_Pos( savepos)
|
---|
644 | endif
|
---|
645 | endif
|
---|
646 |
|
---|
647 | if 0 then
|
---|
648 | --placeholder
|
---|
649 |
|
---|
650 | ---- Directive(s): #if #ifdef #ifndef #endif #else #elif
|
---|
651 | elseif wordpos( id, '#if #ifdef #ifndef #endif #else #elif') then
|
---|
652 | if CurMode <> 'JAVA' & CurMode <> 'JAVASCRIPT' then
|
---|
653 | SearchStr = '\#[ \t]*\c((if((n?def)?))|endif)([ \t]|$)'
|
---|
654 | if CurMode = 'C' then
|
---|
655 | SearchStr = '^[ \t]*\c'SearchStr
|
---|
656 | elseif startcol = 1 then -- RC directives must start in column one
|
---|
657 | SearchStr = '^'SearchStr
|
---|
658 | else
|
---|
659 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
660 | endif
|
---|
661 | clist = substr( id, 2, 1)
|
---|
662 | fForward = (clist = 'i')
|
---|
663 | if fForward then -- move to beginning
|
---|
664 | .col = startcol
|
---|
665 | else -- move to end, so first Locate will hit this instance.
|
---|
666 | .col = endcol
|
---|
667 | endif
|
---|
668 | fIntermediate = (substr( id, 3, 1) = 'l')
|
---|
669 | else
|
---|
670 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
671 | endif
|
---|
672 |
|
---|
673 | ---- Keyword(s): do, try
|
---|
674 | elseif wordpos( id, 'do try') then
|
---|
675 | -- this code might be expanded to <anytoken> { .... }
|
---|
676 | if CurMode <> 'RC' then
|
---|
677 | setsearch 'xcom l /[{;]/xe+F' -- does following a '{' precede a ';'?
|
---|
678 | clist = '{ ;'
|
---|
679 | case = 'e' -- 'e' = case-sensitive
|
---|
680 | coffset = 0
|
---|
681 | clen = 1
|
---|
682 | nestlevel = -1 -- -1 = stop on first 'hit'
|
---|
683 | assist_rc = AssistSearch( CurMode, clist, case, coffset, clen, nestlevel, SearchLimitData)
|
---|
684 | if assist_rc then
|
---|
685 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
686 | else
|
---|
687 | --#dprintf( "pAssist", "token {} '{;' SearchStr found: "substr( textline( .line), .col, 1))
|
---|
688 | if substr( textline( .line), .col, 1) = '{' then -- found the braces
|
---|
689 | SearchStr = '[{}]'
|
---|
690 | fForward = 1
|
---|
691 | clist = '{'
|
---|
692 | else
|
---|
693 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN -- token without braces
|
---|
694 | endif
|
---|
695 | endif
|
---|
696 | else
|
---|
697 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
698 | endif
|
---|
699 |
|
---|
700 | ---- Keyword(s): while
|
---|
701 | elseif id = 'while' then
|
---|
702 | if CurMode <> 'RC' then
|
---|
703 | setsearch 'xcom l /[()]/xe+F' -- find the end of the conditional
|
---|
704 | clist = '{'
|
---|
705 | case = 'e' -- 'e' = case-sensitive
|
---|
706 | coffset = 0
|
---|
707 | clen = 1
|
---|
708 | nestlevel = 0
|
---|
709 | assist_rc = AssistSearch( CurMode, clist, case, coffset, clen, nestlevel, SearchLimitData)
|
---|
710 | if assist_rc then -- no conditional??
|
---|
711 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
712 | else
|
---|
713 | nextchar = NextCodeChar( CurMode)
|
---|
714 | if not nextchar then
|
---|
715 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
716 | else
|
---|
717 | --#dprintf( "pAssist", "while {; SearchStr found: "nextchar)
|
---|
718 | if nextchar = '{' then -- must be while loop (i.e. NOT do/while) with braces
|
---|
719 | SearchStr = '[{}]'
|
---|
720 | fForward = 1
|
---|
721 | clist = '{'
|
---|
722 | elseif nextchar = ';' then -- cursor is on the 'while' of a do/while loop
|
---|
723 | -- SearchStr = '\{|\}|((^|[ \t])\cdo([ \t]|$))'
|
---|
724 | SearchStr = '[{}]|((^|[ \t])\cdo([ \t]|$))'
|
---|
725 | fForward = 0
|
---|
726 | clist = '}'
|
---|
727 | nestlevel = 2
|
---|
728 | else -- cursor is on a one-statement while loop
|
---|
729 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN -- no braces follow, so JBSQ: unbalanceable?
|
---|
730 | endif
|
---|
731 | endif
|
---|
732 | endif
|
---|
733 | endif
|
---|
734 | /*
|
---|
735 | JBSQ: The following code should work for break/continue statements within
|
---|
736 | nested do and for loops which have braces. Problems arise if there are
|
---|
737 | DOs or FORs without braces between the break/continue and the enclosing
|
---|
738 | loop. Also problems arise if the enclosing loop is a while loop.
|
---|
739 |
|
---|
740 | The solution, if it is worth it, is to code the entire search here so that these different
|
---|
741 | variations of loops can be handled correctly.
|
---|
742 |
|
---|
743 | ---- Keyword(s): break continue
|
---|
744 | elseif wordpos( id, 'break continue' then
|
---|
745 | if CurMode <> 'RC' then
|
---|
746 | SearchStr = '([{}])|((^|[ \t])\c(do|for)([ \t]|$))'
|
---|
747 | fForward = 0
|
---|
748 | clist = '}'
|
---|
749 | fIntermediate = 1
|
---|
750 | else
|
---|
751 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
752 | endif
|
---|
753 | */
|
---|
754 |
|
---|
755 | elseif CurMode = 'RC' then
|
---|
756 | -- All remaining RC tokens here
|
---|
757 | case = 'c' -- RC files are case insensitive, except for direcives (#if, #define, etc.)
|
---|
758 | id = lowcase( id)
|
---|
759 | if wordpos( id, '{ } begin end') then
|
---|
760 | SearchStr = '[{}]|((^|[ \t])\c(begin|end)([ \t;]|$))'
|
---|
761 | fForward = (wordpos( id, '{ begin') > 0)
|
---|
762 | if fForward then -- move to beginning begin
|
---|
763 | .col = startcol
|
---|
764 | clist = '{ b'
|
---|
765 | else -- move to end, so first Locate will hit this instance.
|
---|
766 | .col = endcol
|
---|
767 | clist = '} e'
|
---|
768 | endif
|
---|
769 | else
|
---|
770 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
771 | endif
|
---|
772 |
|
---|
773 | else
|
---|
774 | -- All remaining C/JAVA/JAVASCRIPT tokens here
|
---|
775 | idlist = 'case default default:'
|
---|
776 | if CurMode <> 'C' then
|
---|
777 | idlist = idlist 'finally'
|
---|
778 | endif
|
---|
779 | if wordpos( id, idlist) then
|
---|
780 | SearchStr = '[{}]'
|
---|
781 | fForward = 0
|
---|
782 | clist = '}'
|
---|
783 | fIntermediate = 1
|
---|
784 | else
|
---|
785 | -- This code seems to handle matching the beginning and end of
|
---|
786 | -- a) functions when the cursor is on a token preceding the
|
---|
787 | -- parameter list
|
---|
788 | -- b) 'if' when the 'if' has following braces
|
---|
789 | -- c) 'for' when the 'for' has following braces
|
---|
790 | -- d) 'switch' statements
|
---|
791 | -- e) anything of the structure: token ( ) { ... }
|
---|
792 | -- e.g. catch ( ) { ... }
|
---|
793 |
|
---|
794 | -- JBSQ: Check for NextCodeChar( CurMode) = '(' first?
|
---|
795 | -- (This would force the cursor to actually be on the function
|
---|
796 | -- name. The current code allows the cursor on any nonblank,
|
---|
797 | -- noncomment, nonliteral character preceding the parameter
|
---|
798 | -- list.)
|
---|
799 | setsearch 'xcom l /[()]/xe+F' -- find the ending ')' or ;
|
---|
800 | clist = '{'
|
---|
801 | case = 'e' -- 'e' = case-sensitive
|
---|
802 | coffset = 0
|
---|
803 | clen = 1
|
---|
804 | nestlevel = 0
|
---|
805 | assist_rc = AssistSearch( CurMode, clist, case, coffset, clen, nestlevel, SearchLimitData)
|
---|
806 | --#dprintf( 'pAssist', 'last chance c,... srch_rc line col' assist_rc .line .col)
|
---|
807 | if not assist_rc & substr( textline( .line), .col, 1) = ')' then -- no conditional??
|
---|
808 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
809 | nextchar = NextCodeChar( CurMode)
|
---|
810 | if nextchar then
|
---|
811 | --#dprintf( "pAssist", "Generic token () {; SearchStr found: "nextchar)
|
---|
812 | if nextchar = '{' then -- structure is: token ( ) { ... }
|
---|
813 | SearchStr = '[{}]'
|
---|
814 | fForward = 1
|
---|
815 | clist = '{'
|
---|
816 | assist_rc = ASSIST_RC_NO_ERROR
|
---|
817 | endif
|
---|
818 | endif
|
---|
819 | else
|
---|
820 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
821 | endif
|
---|
822 | endif
|
---|
823 | endif
|
---|
824 |
|
---|
825 | -- Mode(s): REXX ----------------------------------------------------------------------------
|
---|
826 | elseif CurMode = 'REXX' then
|
---|
827 |
|
---|
828 | ---- REXX conditions: if, else
|
---|
829 | case = 'c' -- Case insensitive for all REXX tokens
|
---|
830 | id = lowcase(id)
|
---|
831 | if 0 then
|
---|
832 | -- another placeholder
|
---|
833 |
|
---|
834 | elseif wordpos( id, 'do end select when otherwise') then
|
---|
835 | SearchStr = '(^|[ \t])\c(do|end|select)([; \t]|$)'
|
---|
836 | fForward = (wordpos(id, 'do select') > 0)
|
---|
837 | if fForward then -- move to beginning
|
---|
838 | clist = 'do se'
|
---|
839 | .col = startcol
|
---|
840 | else -- move to end, so first Locate will hit this instance.
|
---|
841 | clist = 'en'
|
---|
842 | .col = endcol
|
---|
843 | endif
|
---|
844 | clen = 2
|
---|
845 | fIntermediate = ((id = 'when') | (id = 'otherwise'))
|
---|
846 |
|
---|
847 | elseif id = 'else' then
|
---|
848 | .col = startcol
|
---|
849 | pchar = NextCodeChar( CurMode, .line, .col, '-R')
|
---|
850 | --#dprintf( "pAssist", 'Previous char:' pchar)
|
---|
851 | if lowcase( pchar) = 'd' then
|
---|
852 | if .col > 2 then
|
---|
853 | .col = .col - 2
|
---|
854 | pword = lowcase( substr( textline( .line), .col, 3))
|
---|
855 | if .col > 1 & substr( textline( .line), .col - 1, 1) <> ' ' then
|
---|
856 | --
|
---|
857 | else
|
---|
858 | --#dprintf( "pAssist", 'Previous word:' pword)
|
---|
859 | if pword = 'end' then
|
---|
860 | display -1
|
---|
861 | call pAssist( VerboseLevel, fHighlight)
|
---|
862 | display 1
|
---|
863 | endcol = .col
|
---|
864 | endif
|
---|
865 | endif
|
---|
866 | endif
|
---|
867 | endif
|
---|
868 | SearchStr = '(^|[ \t])\cif([ \t]|$)'
|
---|
869 | clist = 'i'
|
---|
870 | fForward = 0
|
---|
871 | fIntermediate = 1
|
---|
872 | .col = endcol
|
---|
873 | nestlevel = -1
|
---|
874 |
|
---|
875 | compile if 0
|
---|
876 | elseif wordpos( id, 'if else') then
|
---|
877 | -- JBSQ: How is this supposed to work? IFs don't always have ELSEs
|
---|
878 | SearchStr = '(^|[ \t])(if|else)([ \t]|$)'
|
---|
879 | clist = leftstr( id, 1)
|
---|
880 | fForward = (clist <> 'e')
|
---|
881 | if fForward then -- move to beginning
|
---|
882 | .col = startcol
|
---|
883 | else -- move to end, so first Locate will hit this instance.
|
---|
884 | .col = endcol
|
---|
885 | endif
|
---|
886 | compile endif
|
---|
887 |
|
---|
888 | else -- not a known balanceable REXX token
|
---|
889 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
890 | endif
|
---|
891 |
|
---|
892 | -- Mode(s): IPF -----------------------------------------------------------------------------
|
---|
893 | elseif CurMode = 'IPF' then
|
---|
894 |
|
---|
895 | -- IPF tags start with ':' and end with '.'
|
---|
896 | -- If id = '.', then go 1 col left
|
---|
897 | if id = '.' & .col > 1 then
|
---|
898 | left
|
---|
899 | if Find_Token( startcol, endcol) then
|
---|
900 | id = substr( LineStr, startcol, (endcol - startcol) + 1)
|
---|
901 | endif
|
---|
902 | endif
|
---|
903 |
|
---|
904 | if pos( ':', id) > 1 then -- <text>:tag, separate the :tag
|
---|
905 | id = substr( id, pos( ':', id))
|
---|
906 | endif
|
---|
907 |
|
---|
908 | if length( LineStr) > endcol then
|
---|
909 | if (pos( substr( LineStr, endcol + 1, 1), '. ')) then
|
---|
910 | IPFBeginTags = ':artlink :caution :cgraphic :ctrldef :fn :hide'
|
---|
911 | IPFBeginTags = IPFBegintags ':hp1 :hp2 :hp3 :hp4 :hp5 :hp6 :hp7 :hp8 :hp9'
|
---|
912 | IPFBeginTags = IPFBegintags ':lines :link :nt :userdoc :warning :xmp'
|
---|
913 | IPFEndTags = ':eartlink :ecaution :ecgraphic :ectrldef :efn :ehide'
|
---|
914 | IPFEndTags = IPFEndTags ':ehp1 :ehp2 :ehp3 :ehp4 :ehp5 :ehp6 :ehp7 :ehp8 :ehp9'
|
---|
915 | IPFEndTags = IPFEndTags ':elines :elink :ent :euserdoc :ewarning :exmp'
|
---|
916 | IPFTags = IPFBeginTags IPFEndTags
|
---|
917 | --#dprintf( "pAssist", "IPF ID wordpos: "wordpos( id, IPFTags))
|
---|
918 | --#dprintf( "pAssist", "IPF Tags: "IPFTags)
|
---|
919 | coffset = 1 -- omit the leading ':' in words of clist
|
---|
920 |
|
---|
921 | if wordpos( id, IPFTags) then
|
---|
922 | clist = substr( id, 2, 1) -- Character to check to see if it's an end tag
|
---|
923 | fForward = (clist <> 'e') -- fForward = 1 if searching forward; 0 if backwards
|
---|
924 | if fForward then -- move to beginning
|
---|
925 | .col = startcol
|
---|
926 | id = substr( id, 2)
|
---|
927 | else -- move to end, so first Locate will hit this instance.
|
---|
928 | .col = endcol + 1
|
---|
929 | id = substr( id, 3)
|
---|
930 | endif
|
---|
931 | SearchStr = '\:e?'id'(\.| )'
|
---|
932 |
|
---|
933 | elseif wordpos( id, ':ol :ul :sl :eol :eul :esl :li :lp') then
|
---|
934 | fIntermediate = (id = ':li' | id = ':lp')
|
---|
935 | fForward = (wordpos( id, ':ol :ul :sl') > 0) -- fForward = 1 if searching forward; 0 if backwards
|
---|
936 | if fForward then -- move to beginning
|
---|
937 | .col = startcol
|
---|
938 | id = substr( id, 2)
|
---|
939 | clist = 'ol ul sl'
|
---|
940 | clen = 2
|
---|
941 | else -- move to end, so first Locate will hit this instance.
|
---|
942 | .col = endcol + 1
|
---|
943 | id = substr( id, 3)
|
---|
944 | clist = 'eol eul esl'
|
---|
945 | clen = 3
|
---|
946 | endif
|
---|
947 | SearchStr = '\:e?(o|u|s)l(\.| )'
|
---|
948 |
|
---|
949 | elseif wordpos( id, ':table :etable :row :c') then
|
---|
950 | fIntermediate = (id = ':row' | id = ':c')
|
---|
951 | fForward = (id = ':table') -- fForward = 1 if searching forward; 0 if backwards
|
---|
952 | if fForward then -- move to beginning
|
---|
953 | .col = startcol
|
---|
954 | clist = 'table'
|
---|
955 | clen = 5
|
---|
956 | id = substr( id, 2)
|
---|
957 | else -- move to end, so first Locate will hit this instance.
|
---|
958 | .col = endcol + 1
|
---|
959 | clist = 'etable'
|
---|
960 | clen = 6
|
---|
961 | id = substr( id, 3)
|
---|
962 | endif
|
---|
963 | SearchStr = '\:e?table(\.| )'
|
---|
964 |
|
---|
965 | elseif wordpos( id, ':parml :eparml :pt :pd') then
|
---|
966 | fIntermediate = (id = ':pt' | id = ':pd')
|
---|
967 | fForward = (id = ':parml') -- fForward = 1 if searching forward; 0 if backwards
|
---|
968 | if fForward then -- move to beginning
|
---|
969 | .col = startcol
|
---|
970 | id = substr( id, 2)
|
---|
971 | clist = 'parml'
|
---|
972 | clen = 5
|
---|
973 | else -- move to end, so first Locate will hit this instance.
|
---|
974 | .col = endcol + 1
|
---|
975 | id = substr( id, 3)
|
---|
976 | clist = 'eparml'
|
---|
977 | clen = 6
|
---|
978 | endif
|
---|
979 | SearchStr = '\:e?parml(\.| )'
|
---|
980 |
|
---|
981 | elseif wordpos( id, ':dl :dthd :ddhd :dt :dd :edl') then
|
---|
982 | fIntermediate = (wordpos( id, ':dthd :ddhd :dt :dd') > 0)
|
---|
983 | fForward = (id = ':dl') -- fForward = 1 if searching forward; 0 if backwards
|
---|
984 | if fForward then -- move to beginning
|
---|
985 | .col = startcol
|
---|
986 | id = substr( id, 2)
|
---|
987 | clist = 'dl'
|
---|
988 | clen = 2
|
---|
989 | else -- move to end, so first Locate will hit this instance.
|
---|
990 | .col = endcol + 1
|
---|
991 | id = substr( id, 3)
|
---|
992 | clist = 'edl'
|
---|
993 | clen = 3
|
---|
994 | endif
|
---|
995 | SearchStr = '\:e?dl(\.| )'
|
---|
996 |
|
---|
997 | elseif wordpos( id, ':fig :efig :figcap') then
|
---|
998 | fIntermediate = (id = ':figcap')
|
---|
999 | fForward = (id = ':fig') -- fForward = 1 if searching forward; 0 if backwards
|
---|
1000 | if fForward then -- move to beginning
|
---|
1001 | .col = startcol
|
---|
1002 | id = substr( id, 2)
|
---|
1003 | else -- move to end, so first Locate will hit this instance.
|
---|
1004 | .col = endcol + 1
|
---|
1005 | id = substr( id, 3)
|
---|
1006 | endif
|
---|
1007 | SearchStr = '\:e?fig(\.| )'
|
---|
1008 |
|
---|
1009 | else -- not a known balanceable IPF token
|
---|
1010 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1011 | endif
|
---|
1012 |
|
---|
1013 | else -- not a known balanceable IPF token
|
---|
1014 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1015 | endif
|
---|
1016 | else -- not a known balanceable IPF token
|
---|
1017 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1018 | endif
|
---|
1019 |
|
---|
1020 | -- Mode(s): HTML, WARPIN --------------------------------------------------------------------
|
---|
1021 | elseif (CurMode = 'HTML' | CurMode = 'WARPIN') then
|
---|
1022 |
|
---|
1023 | case = 'c'
|
---|
1024 | ---- HTML tags: <...,</...>
|
---|
1025 | if leftstr( id, 1) = '<' then
|
---|
1026 | clist = substr( id, 2, 1) -- Character to check to see if it's the same or the other
|
---|
1027 | fForward = (clist <> '/') -- fForward = 1 if searching forward; 0 if backwards
|
---|
1028 | if fForward then -- move to beginning
|
---|
1029 | id = substr( id, 2) -- Strip off the '<'
|
---|
1030 | clist = id
|
---|
1031 | .col = startcol
|
---|
1032 | else -- move to end, so first Locate will hit this instance.
|
---|
1033 | id = substr( id, 3) -- Strip off the '</'
|
---|
1034 | clist = '/'id
|
---|
1035 | .col = endcol + 1 -- +1 for the '>' after the tag
|
---|
1036 | endif
|
---|
1037 | SearchStr = '<\c/?'id'(>| )' -- Use \c to not put cursor on angle bracket.
|
---|
1038 | clen = length( clist)
|
---|
1039 | else -- not a known balanceable HTML token
|
---|
1040 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1041 | endif
|
---|
1042 |
|
---|
1043 | -- Mode(s): MAKE ----------------------------------------------------------------------------
|
---|
1044 | elseif CurMode = 'MAKE' then
|
---|
1045 |
|
---|
1046 | case = 'c' -- Case insensitive for all MAKE tokens
|
---|
1047 | id = lowcase( id)
|
---|
1048 | -- Currently ALL balanceable MAKE tokens must be on a line with
|
---|
1049 | -- '!' in column 1 and if there are any characters between the '!'
|
---|
1050 | -- and the token they must be whitespace.
|
---|
1051 | if leftstr( LineStr, 1) = '!' then
|
---|
1052 | if startcol > 2 then -- Are there characters between '!' and token?
|
---|
1053 | if verify( substr( LineStr, 2, startcol - 2), ' '\t) then
|
---|
1054 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1055 | id = '' -- Disable further processing
|
---|
1056 | endif
|
---|
1057 | endif
|
---|
1058 | if 0 then
|
---|
1059 | -- placeholder
|
---|
1060 |
|
---|
1061 | compile if USE_NMAKE32
|
---|
1062 | elseif wordpos( id, 'if ifdef ifndef endif else elif elseif') then
|
---|
1063 | compile else
|
---|
1064 | elseif wordpos( id, 'if ifdef ifndef endif else') then
|
---|
1065 | compile endif
|
---|
1066 | SearchStr = '^![ \t]*\c(if((n?def)?)|endif)([ \t]|$)'
|
---|
1067 | clist = leftstr( id, 1)
|
---|
1068 | fForward = (clist = 'i')
|
---|
1069 | if fForward then -- move to beginning
|
---|
1070 | .col = 1
|
---|
1071 | else -- move to end, so first Locate will hit this instance.
|
---|
1072 | .col = endcol
|
---|
1073 | endif
|
---|
1074 | fIntermediate = (substr( id, 2, 1) = 'l')
|
---|
1075 |
|
---|
1076 | compile if USE_NMAKE32
|
---|
1077 | elseif wordpos( id, 'foreach endfor') then -- NMAKE32
|
---|
1078 | SearchStr = '^![ \t]*\c(foreach|endfor)([ \t]|$)'
|
---|
1079 | clist = leftstr( id, 1)
|
---|
1080 | fForward = (clist = 'f')
|
---|
1081 | if fForward then -- move to beginning
|
---|
1082 | .col = 1
|
---|
1083 | else -- move to end, so first Locate will hit this instance.
|
---|
1084 | .col = endcol
|
---|
1085 | endif
|
---|
1086 | fIntermediate = (wordpos( id, 'else elif elseif') > 0)
|
---|
1087 | compile endif
|
---|
1088 |
|
---|
1089 | else
|
---|
1090 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1091 | endif
|
---|
1092 | else
|
---|
1093 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1094 | endif
|
---|
1095 |
|
---|
1096 | -- Mode(s): Pascal --------------------------------------------------------------------------
|
---|
1097 | elseif CurMode = 'PASCAL' then
|
---|
1098 |
|
---|
1099 | case = 'c' -- case insensitive for PASCAL
|
---|
1100 | id = lowcase( id)
|
---|
1101 | PascalStartBlockTokens = 'begin record try asm case unit object class' -- interface?
|
---|
1102 |
|
---|
1103 | if wordpos( id, PascalStartBlockTokens 'end except finally') then
|
---|
1104 | SearchStr = '(^|[^a-zA_Z0-9_])\c('translate( PascalStartBlockTokens, '|', ' ')'|end)([;. \t]|$)'
|
---|
1105 | fForward = (wordpos( id, PascalStartBlockTokens) > 0)
|
---|
1106 | clen = 3
|
---|
1107 | if fForward then
|
---|
1108 | .col = startcol
|
---|
1109 | clist = ''
|
---|
1110 | do i = 1 to words( PascalStartBlockTokens)
|
---|
1111 | clist = clist leftstr( word( PascalStartBlockTokens, i), 3)
|
---|
1112 | enddo
|
---|
1113 | else
|
---|
1114 | .col = endcol
|
---|
1115 | clist = 'end'
|
---|
1116 | endif
|
---|
1117 | fIntermediate = (id = 'except' | id = 'finally')
|
---|
1118 |
|
---|
1119 | elseif wordpos( id, 'repeat until') then
|
---|
1120 | SearchStr = '(^|[ \t])\c(repeat|until)([ \t]|$)'
|
---|
1121 | fForward = (id = 'repeat')
|
---|
1122 | if fForward then
|
---|
1123 | .col = startcol
|
---|
1124 | clist = 'r'
|
---|
1125 | else
|
---|
1126 | .col = endcol
|
---|
1127 | clist = 'u'
|
---|
1128 | endif
|
---|
1129 |
|
---|
1130 | elseif wordpos( id, 'while for') then
|
---|
1131 | -- Check for begin before ';' (i.e a block loop instead of a
|
---|
1132 | -- single statement loop)
|
---|
1133 | setsearch 'xcom l /[ \t]\cdo([ \t]|$)/x'case'c+F' -- find the end of following 'do'
|
---|
1134 | clist = 'd'
|
---|
1135 | coffset = 0
|
---|
1136 | clen = 1
|
---|
1137 | nestlevel = -1 -- -1 = stop on first 'hit'
|
---|
1138 | assist_rc = AssistSearch( CurMode, clist, case, coffset, clen, nestlevel, SearchLimitData)
|
---|
1139 | do once2 = 1 to 1
|
---|
1140 | if assist_rc then -- no 'do'??
|
---|
1141 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1142 | leave
|
---|
1143 | endif
|
---|
1144 | .col = .col + 2
|
---|
1145 | nextchar = NextCodeChar( CurMode)
|
---|
1146 | if not nextchar then
|
---|
1147 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1148 | leave
|
---|
1149 | endif
|
---|
1150 | do once3 = 1 to 1
|
---|
1151 | --#dprintf( "pAssist", "while/for 'do' SearchStr found: "nextchar)
|
---|
1152 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN -- assume bad
|
---|
1153 | if lowcase( nextchar) <> 'b' then
|
---|
1154 | leave
|
---|
1155 | endif
|
---|
1156 | tmpline = textline( .line)
|
---|
1157 | tmpline_len = length( tmpline)
|
---|
1158 | --#dprintf( "pAssist", "col: ".col "len: "tmpline_len "line: "tmpline)
|
---|
1159 | if tmpline_len < .col + 4 then
|
---|
1160 | leave
|
---|
1161 | endif
|
---|
1162 | if lowcase( substr( tmpline, .col, 5)) <> 'begin' then
|
---|
1163 | leave
|
---|
1164 | endif
|
---|
1165 | if (tmpline_len > .col + 4) then
|
---|
1166 | nextchar = substr( tmpline, .col + 5, 1)
|
---|
1167 | --#dprintf( "pAssist", "charafter: '"nextchar"'")
|
---|
1168 | if nextchar = ' ' | nextchar = \9 then
|
---|
1169 | assist_rc = ASSIST_RC_NO_ERROR
|
---|
1170 | endif
|
---|
1171 | else
|
---|
1172 | assist_rc = ASSIST_RC_NO_ERROR
|
---|
1173 | endif
|
---|
1174 | if not assist_rc then
|
---|
1175 | SearchStr = '(^|[ \t])\cbegin|end([;. \t]|$)'
|
---|
1176 | fForward = 1
|
---|
1177 | clist = 'b'
|
---|
1178 | endif
|
---|
1179 | enddo
|
---|
1180 | enddo
|
---|
1181 | else
|
---|
1182 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1183 | endif
|
---|
1184 |
|
---|
1185 | -- Mode(s): TEX -----------------------------------------------------------------------------
|
---|
1186 | elseif CurMode = 'TEX' then
|
---|
1187 |
|
---|
1188 | -- NOTE: There is some special code for \begin and \end which depends
|
---|
1189 | -- on 'clist' being set to 'be' or 'en'. If it becomes necessary
|
---|
1190 | -- to use these values for 'clist' for other TEX tokens, then the
|
---|
1191 | -- special code for \begin and \end will break.
|
---|
1192 | coffset = 1 -- omit the leading '\' in words of clist
|
---|
1193 |
|
---|
1194 | -- //PM additions: balanceable tokens for (La)TeX
|
---|
1195 |
|
---|
1196 | ---- TeX conditions: \if, \else, \fi
|
---|
1197 | if substr( id, 1, 3) = '\if' | wordpos( id, '\else \fi') then --// \if.. \else \fi
|
---|
1198 | SearchStr = '\\(if|fi)'
|
---|
1199 | clist = substr( id, 2, 1)
|
---|
1200 | fForward = (clist = 'i') -- fForward=1: forward, fForward=0 backward search
|
---|
1201 | if fForward then -- move cursor so that the first Locate will hit this instance
|
---|
1202 | .col = startcol -- \if: move to beginning
|
---|
1203 | else
|
---|
1204 | .col = endcol -- \else,\fi: move to end
|
---|
1205 | endif
|
---|
1206 | fIntermediate = (id = '\else')
|
---|
1207 |
|
---|
1208 | ---- TeX environment: \begin..., \end...
|
---|
1209 | elseif id = '\begin' | id = '\end' then --// \begin.. \end..
|
---|
1210 | SearchStr = '\\(begin|end)[ \t]*'
|
---|
1211 | ---- LaTeX environment: \begin{...}, \end{...}
|
---|
1212 | .col = endcol
|
---|
1213 | if NextCodeChar( CurMode) == '{' then
|
---|
1214 | --#dprintf( 'pAssist', 'TEX: found } at '.line .col)
|
---|
1215 | temp = substr( textline( .line), .col)
|
---|
1216 | p = pos( '}', temp)
|
---|
1217 | if p > 0 then
|
---|
1218 | TexEnvStr = leftstr( temp, p)
|
---|
1219 | endif
|
---|
1220 | endif
|
---|
1221 | call pRestore_Pos( savepos)
|
---|
1222 | clist = substr( id, 2, 2)
|
---|
1223 | clen = 2
|
---|
1224 | fForward = (clist = 'be')
|
---|
1225 | if fForward then
|
---|
1226 | .col = startcol
|
---|
1227 | else
|
---|
1228 | .col = endcol
|
---|
1229 | endif
|
---|
1230 |
|
---|
1231 | elseif id = '\bgroup' | id = '\egroup' then
|
---|
1232 | SearchStr = '\\(bgroup|egroup)'
|
---|
1233 | clist = substr( id, 2, 1)
|
---|
1234 | fForward = (clist = 'b')
|
---|
1235 | if fForward then
|
---|
1236 | .col = startcol
|
---|
1237 | else
|
---|
1238 | .col = endcol
|
---|
1239 | endif
|
---|
1240 |
|
---|
1241 | elseif id = '\begingroup' | id = '\endgroup' then
|
---|
1242 | SearchStr = '\\(begingroup|endgroup)'
|
---|
1243 | clist = substr( id, 2, 1)
|
---|
1244 | fForward = (clist = 'b')
|
---|
1245 | if fForward then
|
---|
1246 | .col = startcol
|
---|
1247 | else
|
---|
1248 | .col = endcol
|
---|
1249 | endif
|
---|
1250 |
|
---|
1251 | elseif id = '\makeatletter' | id = '\makeatother' then
|
---|
1252 | SearchStr = '\\makeat(letter|other)'
|
---|
1253 | clist = substr( id, 8, 1)
|
---|
1254 | fForward = (clist = 'l')
|
---|
1255 | if fForward then
|
---|
1256 | .col = startcol
|
---|
1257 | else
|
---|
1258 | .col = endcol
|
---|
1259 | endif
|
---|
1260 | coffset = 7
|
---|
1261 |
|
---|
1262 | elseif id = '\[' | id = '\]' then
|
---|
1263 | SearchStr = '\\(\[|\])'
|
---|
1264 | clist = substr( id, 2, 1)
|
---|
1265 | fForward = (clist = '[')
|
---|
1266 | if fForward then
|
---|
1267 | .col = startcol
|
---|
1268 | else
|
---|
1269 | .col = endcol
|
---|
1270 | endif
|
---|
1271 |
|
---|
1272 | elseif id = '\(' | id = '\)' then
|
---|
1273 | SearchStr = '\\(\(|\))'
|
---|
1274 | clist = substr( id, 2, 1)
|
---|
1275 | fForward = (clist = '(')
|
---|
1276 | if fForward then
|
---|
1277 | .col = startcol
|
---|
1278 | else
|
---|
1279 | .col = endcol
|
---|
1280 | endif
|
---|
1281 |
|
---|
1282 | ---- TeX math
|
---|
1283 | elseif wordpos( id, '\left \right') then
|
---|
1284 | SearchStr = '\\(left|right)'
|
---|
1285 | clist = substr( id, 2, 1)
|
---|
1286 | fForward = (clist = 'l')
|
---|
1287 | if fForward then
|
---|
1288 | .col = startcol
|
---|
1289 | else
|
---|
1290 | .col = endcol
|
---|
1291 | endif
|
---|
1292 |
|
---|
1293 | ---- TeX environment: \begin{env}, \end{env} when cursor is on {env}
|
---|
1294 | else
|
---|
1295 | fEnvFound = 0
|
---|
1296 | if NextCodeChar( CurMode, .line, endcol) == '}' & NextCodeChar( CurMode, .line, startcol, '-R') == '{' then
|
---|
1297 | -- Find \begin or \end before {env}
|
---|
1298 | call NextCodeChar( CurMode, '', '', '-R')
|
---|
1299 | rcx = Find_Token( bestartcol, beendcol, seps, 'NONE:')
|
---|
1300 | if rcx then
|
---|
1301 | beLineStr = ( textline( .line))
|
---|
1302 | if bestartcol > 1 then
|
---|
1303 | beprevchar = substr( beLineStr, bestartcol - 1, 1)
|
---|
1304 | if beprevchar = '\' then
|
---|
1305 | bestartcol = bestartcol - 1
|
---|
1306 | SearchStr = '\\(begin|end)[ \t]*'
|
---|
1307 | TexEnvStr = '{'id'}'
|
---|
1308 | clist = substr( beLineStr, bestartcol + 1, 2)
|
---|
1309 | clen = 2
|
---|
1310 | fForward = (clist = 'be')
|
---|
1311 | if fForward then
|
---|
1312 | .col = bestartcol - 1
|
---|
1313 | else
|
---|
1314 | .col = beendcol
|
---|
1315 | endif
|
---|
1316 | fEnvFound = 1
|
---|
1317 | endif
|
---|
1318 | endif
|
---|
1319 | endif
|
---|
1320 | endif
|
---|
1321 |
|
---|
1322 | if not fEnvFound then -- not a known balanceable 'TEX' token
|
---|
1323 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1324 | endif
|
---|
1325 | endif
|
---|
1326 |
|
---|
1327 | -- Mode(s): FORTRAN77 -----------------------------------------------------------------------
|
---|
1328 | elseif CurMode = 'FORTRAN77' then
|
---|
1329 |
|
---|
1330 | compile if 1
|
---|
1331 | -- This code disregards the "token" and allows the cursor anywhere
|
---|
1332 | -- within columns 7 ... 72
|
---|
1333 | if .col > 6 & .col < 73 then
|
---|
1334 | statement = Fortran77ExtractText( .line)
|
---|
1335 | do i = .line + 1 to .last
|
---|
1336 | temp = textline( i)
|
---|
1337 | if pos( substr( temp, 6, 1), ' 0') then
|
---|
1338 | leave
|
---|
1339 | elseif not pos( leftstr( temp, 1), 'C*') then
|
---|
1340 | statement = statement''Fortran77ExtractText( i)
|
---|
1341 | endif
|
---|
1342 | enddo
|
---|
1343 | statement = Fortran77RemoveSpaces( statement)
|
---|
1344 |
|
---|
1345 | if leftstr( statement, 2) = 'DO' then
|
---|
1346 | equalpos = pos( '=', statement, 4)
|
---|
1347 | commapos = pos( ',', statement, 6)
|
---|
1348 | if equalpos & commapos then -- DO loop of some kind?
|
---|
1349 | fForward = 1
|
---|
1350 | clist = 'D'
|
---|
1351 | .col = pos( 'D', LineStr, 7)
|
---|
1352 | p = verify( statement, '0123456789', 'N', 3)
|
---|
1353 | if p > 3 then -- DO <labelnum>,... loop
|
---|
1354 | label = substr( statement, 3, p - 3)
|
---|
1355 | --#dprintf( 'pAssist', 'label as string: 'label)
|
---|
1356 | label = label + 0
|
---|
1357 | --#dprintf( 'pAssist', 'label as number: 'label)
|
---|
1358 | temp = ''
|
---|
1359 | do i = length( label) to 4
|
---|
1360 | temp = temp'[ 0]?'
|
---|
1361 | enddo
|
---|
1362 | SearchStr = '^('temp''label'[ 0]?[ ]*\c[^0])'
|
---|
1363 | --#dprintf( "pAssist", "DO <label> search: "SearchStr)
|
---|
1364 | 'xcom l /'SearchStr'/x'
|
---|
1365 | if rc = 0 then
|
---|
1366 | assist_rc = -1
|
---|
1367 | else
|
---|
1368 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1369 | endif
|
---|
1370 | --#dprintf( 'pAssist', 'F77 search rc: 'rc)
|
---|
1371 | else
|
---|
1372 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1373 | endif
|
---|
1374 | else
|
---|
1375 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1376 | endif
|
---|
1377 |
|
---|
1378 | else
|
---|
1379 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1380 | endif
|
---|
1381 | else
|
---|
1382 | assist_rc = ASSIST_RC_BAD_FORTRAN77_CURSOR -- Cursor before col 7 or after col 72
|
---|
1383 | endif
|
---|
1384 |
|
---|
1385 | compile else
|
---|
1386 |
|
---|
1387 | -- This code disregards the "token" and allows the cursor anywhere
|
---|
1388 | -- within columns 7 ... 72
|
---|
1389 | if .col > 6 & .col < 73 then
|
---|
1390 | statement = Fortran77ExtractText( .line)
|
---|
1391 | do i = .line + 1 to .last
|
---|
1392 | temp = textline( i)
|
---|
1393 | if pos( substr( temp, 6, 1), ' 0') then
|
---|
1394 | leave
|
---|
1395 | elseif not pos( leftstr( temp, 1), 'C*') then
|
---|
1396 | statement = statement''Fortran77ExtractText( i)
|
---|
1397 | endif
|
---|
1398 | enddo
|
---|
1399 | statement = Fortran77RemoveSpaces( statement)
|
---|
1400 |
|
---|
1401 | if leftstr( statement, 2) = 'DO' then
|
---|
1402 | equalpos = pos( '=', statement, 4)
|
---|
1403 | commapos = pos( ',', statement, 6)
|
---|
1404 | if equalpos & commapos then -- DO loop of some kind?
|
---|
1405 | fForward = 1
|
---|
1406 | clist = 'D'
|
---|
1407 | .col = pos( 'D', LineStr, 7)
|
---|
1408 | p = verify( statement, '0123456789', 'N', 3)
|
---|
1409 | if p > 3 then -- DO <labelnum>,... loop
|
---|
1410 | label = substr( statement, 3, p - 3)
|
---|
1411 | --#dprintf( 'pAssist', 'label as string: 'label)
|
---|
1412 | label = label + 0
|
---|
1413 | --#dprintf( 'pAssist', 'label as number: 'label)
|
---|
1414 | temp = ''
|
---|
1415 | do i = length( label) to 4
|
---|
1416 | temp = temp'[ 0]?'
|
---|
1417 | enddo
|
---|
1418 | SearchStr = '^('temp''label'[ 0]?[ ]*\c[^0])'
|
---|
1419 | --#dprintf( "pAssist", "DO <label> search: "SearchStr)
|
---|
1420 | 'xcom l /'SearchStr'/x'
|
---|
1421 | if rc = 0 then
|
---|
1422 | assist_rc = -1
|
---|
1423 | else
|
---|
1424 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1425 | endif
|
---|
1426 | --#dprintf( 'pAssist', 'F77 search rc: 'rc)
|
---|
1427 | -- DO/ENDDO is not FORTRAN77 but the code (esp. the regex
|
---|
1428 | -- search string) for future use
|
---|
1429 | else -- DO var = xx,limit loop
|
---|
1430 | SearchStr = '^[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].[ ]*\c((D[ ]*O[ ]*[A-Z][A-Z0-9]*[ ]*=.+,)|(E[ ]*N[ ]*D[ ]*D[ ]*O))'
|
---|
1431 | endif
|
---|
1432 | else
|
---|
1433 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1434 | endif
|
---|
1435 |
|
---|
1436 | -- o FORTRAN77 support (beyond the generic ()[]{}-matching and
|
---|
1437 | -- do <label> ...) is disabled.
|
---|
1438 | -- o The code below tries to match "Block" IFs (i.e.
|
---|
1439 | -- IF(<condiiton>)THEN ... ENDIF)
|
---|
1440 | -- o But FORTRAN allows statements to be contiued. This means
|
---|
1441 | -- that for "IF (confition) THEN" the IF and the THEN might
|
---|
1442 | -- be on different lines.
|
---|
1443 | -- o For long conditions, the use of continuations can make
|
---|
1444 | -- stylistic sense. For example:
|
---|
1445 | -- IF( CARDS(I)(2:2) .EQ. 'J'
|
---|
1446 | -- 1 .OR. CARDS(I)(2:2) .EQ. 'Q'
|
---|
1447 | -- 2 .OR. CARDS(I)(2:2) .EQ. 'K' )THEN
|
---|
1448 | -- o Unless grep searches start supporting searches across
|
---|
1449 | -- multiple lines, the only way to implement matching with
|
---|
1450 | -- this kind of code is
|
---|
1451 | -- 1) Create a temporary file
|
---|
1452 | -- 2) Rewrite the original file in to the temp file, "merging"
|
---|
1453 | -- the continuation lines in the process
|
---|
1454 | -- 3) Somehow keep track of which columns of the merged lines
|
---|
1455 | -- came from which lines and columns of the original file
|
---|
1456 | -- 4) Perform a search on the temp file
|
---|
1457 | -- 5) Use the data from #3 to map the location of the "found"
|
---|
1458 | -- string back into the original file
|
---|
1459 | -- 6) Discard the temp file
|
---|
1460 | -- o At this time the effort need to make this work was deemed
|
---|
1461 | -- not worth the "value" of matching
|
---|
1462 |
|
---|
1463 | -- "Block" IFs in FORTRAN.
|
---|
1464 | elseif leftstr( statement, 3) = 'IF(' then
|
---|
1465 | if pos( ')THEN', statement) then -- Assume ')THEN' is NOT in a literal?
|
---|
1466 | SearchStr = '^[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].[ ]*\c((I[ ]*F[ ]*(.*)[ ]*T[ ]*H[ ]*E[ ]*N)|(E[ ]*N[ ]*D[ ]*I[ ]*F))'
|
---|
1467 | fForward = 1
|
---|
1468 | clist = 'I'
|
---|
1469 | .col = pos( 'I', LineStr, 7)
|
---|
1470 | else
|
---|
1471 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN -- IF without THEN is unbalanceable
|
---|
1472 | endif
|
---|
1473 |
|
---|
1474 | elseif leftstr( statement, 7) = 'ELSEIF(' then
|
---|
1475 | if pos( ')THEN', statement) then -- Assume ')THEN' is NOT in a literal?
|
---|
1476 | SearchStr = '^[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].[ ]*\c((I[ ]*F[ ]*(.*)[ ]*T[ ]*H[ ]*E[ ]*N)|(E[ ]*N[ ]*D[ ]*I[ ]*F))'
|
---|
1477 | fForward = 0
|
---|
1478 | fIntermediate = 1
|
---|
1479 | clist = 'E'
|
---|
1480 | .col = pos( 'E', LineStr, 7)
|
---|
1481 | else
|
---|
1482 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN -- ELSEIF without THEN is unbalanceable
|
---|
1483 | endif
|
---|
1484 |
|
---|
1485 | elseif statement = 'ENDIF' then
|
---|
1486 | SearchStr = '^[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9][ 0]+\c((I[ ]*F[ ]*\(.*\)T[ ]*H[ ]*E[ ]*N)|(E[ ]*N[ ]*D[ ]*I[ ]*F))'
|
---|
1487 | fForward = 0
|
---|
1488 | clist = 'E'
|
---|
1489 | .col = pos( 'E', LineStr, 7)
|
---|
1490 |
|
---|
1491 | -- FORTRAN77 does not require END of program/subroutine/function
|
---|
1492 | -- statements, nor is a PROGRAM statement required
|
---|
1493 | elseif not pos( '=', statement) & statement <> '' then -- remaining matchable tokens require this
|
---|
1494 | function_pos = pos( 'FUNCTION', statement)
|
---|
1495 | punc_pos = verify( statement, "+-*/=().,':$!", 'M')
|
---|
1496 | function_statement = (function_pos > 0 & (punc_pos = 0 | function_pos < punc_pos))
|
---|
1497 | if leftstr( statement, 7) = 'PROGRAM' |
|
---|
1498 | leftstr( statement, 10) = 'SUBROUTINE' |
|
---|
1499 | leftstr( statement, 9) = 'BLOCKDATA' |
|
---|
1500 | function_statement |
|
---|
1501 | strip( statement) = 'END' then
|
---|
1502 | SearchStr = '^[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].[ ]*((('
|
---|
1503 | SearchStr = SearchStr'(\cP[ ]*R[ ]*O[ ]*G[ ]*R[ ]*A[ ]*M)|'
|
---|
1504 | SearchStr = SearchStr'(\cS[ ]*U[ ]*B[ ]*R[ ]*O[ ]*U[ ]*T[ ]*I[ ]*N[ ]*E)|'
|
---|
1505 | SearchStr = SearchStr'(\cB[ ]*L[ ]*O[ ]*C[ ]*K[ ]*D[ ]*A[ ]*T[ ]*A)|'
|
---|
1506 | SearchStr = SearchStr'([A-Z][A-Z0-9]*[ ]*\cF[ ]*U[ ]*N[ ]*C[ ]*T[ ]*I[ ]*O[ ]*N))'
|
---|
1507 | SearchStr = SearchStr'[ ]*(~[=])*)|(\cE[ ]*N[ ]*D[ ]*$))'
|
---|
1508 | fForward = (strip( statement) <> 'END')
|
---|
1509 | if function_statement then
|
---|
1510 | .col = pos( 'FUNCTION', LineStr, 7)
|
---|
1511 | else
|
---|
1512 | .col = verify( LineStr, ' ', 'N', 7)
|
---|
1513 | endif
|
---|
1514 | if fForward then
|
---|
1515 | clist = 'P S B F'
|
---|
1516 | else
|
---|
1517 | clist = 'E'
|
---|
1518 | endif
|
---|
1519 | else
|
---|
1520 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1521 | endif
|
---|
1522 |
|
---|
1523 | else
|
---|
1524 | assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1525 | endif
|
---|
1526 | else
|
---|
1527 | assist_rc = ASSIST_RC_BAD_FORTRAN77_CURSOR -- Cursor before col 7 or after col 72
|
---|
1528 | endif
|
---|
1529 | compile endif
|
---|
1530 |
|
---|
1531 | -- End of mode defs -------------------------------------------------------------------------
|
---|
1532 |
|
---|
1533 | -- For all modes: SearchStr may be a bracket
|
---|
1534 | elseif SearchStr = '' then -- not a known balanceable token or a mode that is not yet supported
|
---|
1535 | assist_rc = ASSIST_RC_MODE_NOT_SUPPORTED
|
---|
1536 | endif
|
---|
1537 |
|
---|
1538 | enddo -- do once = 1 to 1
|
---|
1539 |
|
---|
1540 | -- Search logic:
|
---|
1541 | -- o The first search finds the string at the cursor.
|
---|
1542 | -- o From the second search on, it is searched for the matching string
|
---|
1543 | -- of the previous search.
|
---|
1544 | -- o Note that the extended grep option is used. The var SearchStr
|
---|
1545 | -- contains the matching start and end strings with the egrep syntax.
|
---|
1546 | -- o The string at the cursor is highlighted.
|
---|
1547 | -- o For an 'else' or 'elseif' condition string at the cursor: the
|
---|
1548 | -- start string of the condition is highlighted.
|
---|
1549 | -- o The cursor is placed at the matching string of the highlighted one.
|
---|
1550 | if not assist_rc then
|
---|
1551 | if fForward then
|
---|
1552 | direction = '+F'
|
---|
1553 | else
|
---|
1554 | direction = '-R'
|
---|
1555 | endif
|
---|
1556 | SearchCall = 'xcom l '\1''SearchStr\1'x'case''direction
|
---|
1557 | --#dprintf( "pAssist", "id clist fForward fIntermediate:" id "'"clist"'" fForward fIntermediate)
|
---|
1558 | --#dprintf( "pAssist", 'search: 'SearchCall)
|
---|
1559 |
|
---|
1560 | if fIntermediate then -- if cursor is on 'else' or 'elseif' etc.
|
---|
1561 | -- Search begin of condition
|
---|
1562 | setsearch SearchCall
|
---|
1563 |
|
---|
1564 | HighlightLine = .line
|
---|
1565 | if hcol > 0 then
|
---|
1566 | HighlightCol = hcol
|
---|
1567 | endif
|
---|
1568 | if hlen > 0 then
|
---|
1569 | HighlightLen = hlen
|
---|
1570 | endif
|
---|
1571 | else
|
---|
1572 | -- This is the first search
|
---|
1573 | SearchCall
|
---|
1574 |
|
---|
1575 | -- Workaround for missing col at highlight_match call:
|
---|
1576 | -- Compose the CircleIt data already here and submit it to
|
---|
1577 | -- Highlight_Match.
|
---|
1578 | HighlightLine = .line
|
---|
1579 | HighlightCol = getpminfo( EPMINFO_SEARCHPOS)
|
---|
1580 | HighlightLen = getpminfo( EPMINFO_LSLENGTH)
|
---|
1581 | if HighlightLen then
|
---|
1582 | -- If the SearchStr includes spaces or MLCs as separator, then
|
---|
1583 | -- HighlightCol or HighlightLen are too wide.
|
---|
1584 | -- This tries to split at least the leading chars. Therefore
|
---|
1585 | -- the cursor pos in the regex must be set to the start of
|
---|
1586 | -- the token:
|
---|
1587 | if .col > HighlightCol then
|
---|
1588 | HighlightLen = Max( 0, HighlightLen - (.col - HighlightCol)) -- must come before changing HighlightCol
|
---|
1589 | HighlightCol = .col
|
---|
1590 | endif
|
---|
1591 | -- (The cursor offset (coffset) has to be adjusted, if the
|
---|
1592 | -- token includes leading e.g. '\' or ':' chars while the
|
---|
1593 | -- search strings in clist don't.)
|
---|
1594 | -- Other spaces are stripped with the fStripBlanks option of
|
---|
1595 | -- Highlight_Match.
|
---|
1596 | endif
|
---|
1597 | --dprintf( 'pAssist: SearchCall 1 = 'SearchCall', rc = 'rc', line col len = 'HighlightLine HighlightCol HighlightLen', prevline prevcol = 'HighlightLine HighlightCol)
|
---|
1598 | endif
|
---|
1599 |
|
---|
1600 | -- This is the search loop from the second search on. It also
|
---|
1601 | -- o checks if the cursor is within a comment or a literal,
|
---|
1602 | -- o alters nestlevel, the counter for matching expressions,
|
---|
1603 | -- o checks for too many processed lines and
|
---|
1604 | -- o does additional search for the modes E and TEX.
|
---|
1605 | assist_rc = AssistSearch( CurMode, clist, case, coffset, clen, nestlevel, SearchLimitData, TexEnvStr, fEExcludeCompile)
|
---|
1606 | endif -- if OK to search
|
---|
1607 |
|
---|
1608 | if assist_rc > 0 then
|
---|
1609 | call pRestore_Pos( savepos)
|
---|
1610 | if VerboseLevel <> 0 then
|
---|
1611 | if assist_rc = ASSIST_RC_IN_ONELINE_COMMENT then
|
---|
1612 | sayerror "Invalid: One-line comment starts in column "CommentData
|
---|
1613 | elseif assist_rc = ASSIST_RC_IN_MULTILINE_COMMENT then
|
---|
1614 | sayerror "Invalid: Multi-line comment starting at "CommentStartLine","CommentStartCol" and ending at "CommentEndLIne","CommentEndCol
|
---|
1615 | elseif assist_rc = ASSIST_RC_IN_LITERAL then
|
---|
1616 | sayerror "Invalid: Cursor located within a literal."
|
---|
1617 | elseif assist_rc = ASSIST_RC_NOT_ON_A_TOKEN then
|
---|
1618 | sayerror "Invalid: Cursor is not located on a token."
|
---|
1619 | elseif assist_rc = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN then
|
---|
1620 | sayerror UNBALANCED_TOKEN__MSG
|
---|
1621 | elseif assist_rc = ASSIST_RC_MODE_NOT_SUPPORTED then
|
---|
1622 | sayerror "Token balancing not yet supported for mode: "CurMode
|
---|
1623 | elseif assist_rc = ASSIST_RC_TOO_MANY_LINES then
|
---|
1624 | sayerror "Assist: More than "MaxLines" lines reached. Further processing might get slow."
|
---|
1625 | elseif assist_rc = ASSIST_RC_TOO_MANY_LOOPS then
|
---|
1626 | sayerror "Assist: More than "MaxLoops" times searched. Further processing might get slow."
|
---|
1627 | else
|
---|
1628 | sayerror "Unknown rc: "assist_rc
|
---|
1629 | endif
|
---|
1630 | endif
|
---|
1631 | else
|
---|
1632 | if VerboseLevel <> 0 then
|
---|
1633 | sayerror 1
|
---|
1634 | endif
|
---|
1635 |
|
---|
1636 | call pSave_Pos( lpos)
|
---|
1637 | -- Save the found position as universal
|
---|
1638 | lastassistpos = HighlightLine HighlightCol HighlightLen
|
---|
1639 | if fHighlight then
|
---|
1640 | if pos( '-', direction) > 0 then
|
---|
1641 | ScrollToTopBot = 'T'
|
---|
1642 | else
|
---|
1643 | ScrollToTopBot = 'B'
|
---|
1644 | endif
|
---|
1645 | call ScrollAfterLocate( savepos, lpos, ScrollToTopBot, '-4 -4')
|
---|
1646 |
|
---|
1647 | -- At this time, getpminfo( EPMINFO_SEARCHPOS) has the value 0, not
|
---|
1648 | -- the col after the last search. Additionally, the second search
|
---|
1649 | -- was executed, so the position data of the first search has
|
---|
1650 | -- changed. Therefore submit the data from after the starting seach
|
---|
1651 | -- to CircleIt as arg:
|
---|
1652 | fStripBlanks = 1
|
---|
1653 | call Highlight_Match( HighlightLine HighlightCol HighlightLen, fStripBlanks)
|
---|
1654 | endif
|
---|
1655 | endif
|
---|
1656 |
|
---|
1657 | -- Invalidation of the MLC array was moved to NextCmdAltersText().
|
---|
1658 | -- The MLC array is now re-used until a command or a key is executed that
|
---|
1659 | -- calls NextCmdAltersText().
|
---|
1660 |
|
---|
1661 | -- Restores user's command so Ctrl-F works.
|
---|
1662 | setsearch search_command
|
---|
1663 |
|
---|
1664 | return assist_rc
|
---|
1665 |
|
---|
1666 | ; ---------------------------------------------------------------------------
|
---|
1667 | ; Performs the actual search for the matching token (which is NOT located
|
---|
1668 | ; within a comment or literal).
|
---|
1669 | defproc AssistSearch( Mode, clist, case, coffset, clen, nestlevel, SearchLimitData)
|
---|
1670 | parse value SearchLimitData with StartLineNum MaxLines MaxLoops
|
---|
1671 | TexEnvStr = arg( 8)
|
---|
1672 | fEExcludeCompile = arg( 9)
|
---|
1673 | if fEExcludeCompile = '' then
|
---|
1674 | fEExcludeCompile = 0
|
---|
1675 | endif
|
---|
1676 | retval = 0
|
---|
1677 | getsearch ThisSearch
|
---|
1678 | fForward = (rightstr( ThisSearch, 2) = '+F')
|
---|
1679 | LoopCount = 1 -- The first search is done by xcom l
|
---|
1680 |
|
---|
1681 | -- This is the search loop from the second search on.
|
---|
1682 | do forever
|
---|
1683 | --#dprintf( "pAssist", "- - - - -")
|
---|
1684 | --#dprintf( "pAssist", "before search pos: ".line",".col "nestlevel = "nestlevel)
|
---|
1685 | display -8 -- suppress writing to MsgBox
|
---|
1686 | repeatfind
|
---|
1687 | lrc = rc
|
---|
1688 | display 8
|
---|
1689 |
|
---|
1690 | if lrc then
|
---|
1691 | retval = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1692 | --#dprintf( 'pAssist', 'AssistSearch: rc = 'lrc)
|
---|
1693 | leave
|
---|
1694 | endif
|
---|
1695 |
|
---|
1696 | --#dprintf( "pAssist", "Match at ".line",".col)
|
---|
1697 | if InsideComment( Mode) then
|
---|
1698 | --#dprintf( 'pAssist', 'InsideComment')
|
---|
1699 | iterate
|
---|
1700 | endif
|
---|
1701 | if InsideLiteral( Mode) then
|
---|
1702 | --#dprintf( 'pAssist', 'InsideLiteral')
|
---|
1703 | iterate
|
---|
1704 | endif
|
---|
1705 |
|
---|
1706 | -- Mode E: Omit conditions with a preceding 'compile', except for
|
---|
1707 | -- conditions that include 'compile' in the search string
|
---|
1708 | if Mode = 'E' & fEExcludeCompile then
|
---|
1709 | -- if|else|elseif|endif (without compile)
|
---|
1710 | LineStr = textline( .line)
|
---|
1711 | leftline = lowcase( leftstr( LineStr, .col - 1))
|
---|
1712 | pcompile = pos( 'compile:w', leftline, 1, 'x')
|
---|
1713 | if pcompile & pcompile <= .col then
|
---|
1714 | iterate
|
---|
1715 | endif
|
---|
1716 | endif
|
---|
1717 |
|
---|
1718 | --#dprintf( "pAssist", "line# ".line" col: ".col" text: "textline( .line))
|
---|
1719 | cword = substr( textline( .line), .col + coffset, clen)
|
---|
1720 | if case = 'c' then
|
---|
1721 | cword = lowcase( cword)
|
---|
1722 | endif
|
---|
1723 | --#dprintf( "pAssist", "CList: "clist "Cword: "cword "Coffset: "coffset "CLen: "clen)
|
---|
1724 | if wordpos( cword, clist) then
|
---|
1725 | nestlevel = nestlevel + 1
|
---|
1726 | else
|
---|
1727 | nestlevel = nestlevel - 1
|
---|
1728 | endif
|
---|
1729 |
|
---|
1730 | --#dprintf( "pAssist", 'after nestlevel = 'nestlevel)
|
---|
1731 | --retval = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN * (rc = sayerror('String not found'))
|
---|
1732 | if nestlevel = 0 then
|
---|
1733 | leave
|
---|
1734 | endif
|
---|
1735 |
|
---|
1736 | -- Check number of searched lines
|
---|
1737 | if fForward then
|
---|
1738 | if .line > StartLineNum + MaxLines then
|
---|
1739 | retval = ASSIST_RC_TOO_MANY_LINES
|
---|
1740 | leave
|
---|
1741 | endif
|
---|
1742 | else
|
---|
1743 | if .line < StartLineNum - MaxLines then
|
---|
1744 | retval = ASSIST_RC_TOO_MANY_LINES
|
---|
1745 | leave
|
---|
1746 | endif
|
---|
1747 | endif
|
---|
1748 |
|
---|
1749 | -- Check number of searched loops
|
---|
1750 | LoopCount = LoopCount + 1
|
---|
1751 | if LoopCount >= MaxLoops then
|
---|
1752 | retval = ASSIST_RC_TOO_MANY_LOOPS
|
---|
1753 | leave
|
---|
1754 | endif
|
---|
1755 | enddo
|
---|
1756 |
|
---|
1757 | if retval = 0 & Mode == 'TEX' & (clist = 'be' | clist = 'en') then
|
---|
1758 | call psave_pos( texsavepos)
|
---|
1759 | if clist = 'be' then
|
---|
1760 | .col = .col + 3
|
---|
1761 | else
|
---|
1762 | .col = .col + 5
|
---|
1763 | endif
|
---|
1764 | nextchar = NextCodeChar( Mode)
|
---|
1765 | --#dprintf( "pAssist", "TEX env: "TexEnvStr" NextChar: "nextchar)
|
---|
1766 | if TexEnvStr <> '' then
|
---|
1767 | if nextchar == '{' then
|
---|
1768 | --#dprintf( "pAssist", "TEX env found { at ".line .col)
|
---|
1769 | if substr( textline( .line), .col, length( TexEnvStr)) == TexEnvStr then
|
---|
1770 | --#dprintf( "pAssist", "TEX env matched")
|
---|
1771 | else
|
---|
1772 | retval = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1773 | endif
|
---|
1774 | else
|
---|
1775 | retval = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1776 | endif
|
---|
1777 | else
|
---|
1778 | if nextchar = '{' then
|
---|
1779 | retval = ASSIST_RC_NOT_ON_A_BALANCEABLE_TOKEN
|
---|
1780 | endif
|
---|
1781 | endif
|
---|
1782 | call prestore_pos( texsavepos)
|
---|
1783 | endif
|
---|
1784 | return retval
|
---|
1785 |
|
---|
1786 | ; ---------------------------------------------------------------------------
|
---|
1787 | ; In FORTRAN the text of interest to pAssist is located only in columns
|
---|
1788 | ; 7 ... 72. (An exception is when FORTRAN90-style SLCs are supported.)
|
---|
1789 | ; This routine extracts and returns the text of interest to the pAssist
|
---|
1790 | ; routine.
|
---|
1791 | defproc Fortran77ExtractText( linenum)
|
---|
1792 | text = substr( textline( linenum), 7, 66) -- columns 7 ... 72
|
---|
1793 | compile if 0 /* USE_FORTRAN90_SLC = 1 */
|
---|
1794 | if pos( "!", text) then
|
---|
1795 | call psave_pos( savepos3)
|
---|
1796 | .line = linenum
|
---|
1797 | .col = 7
|
---|
1798 | setsearch 'xcom l /!/xe+F'
|
---|
1799 | Mode = 'FORTRAN90'
|
---|
1800 | clist = '!'
|
---|
1801 | case = 'e' -- 'e' = case-sensitive
|
---|
1802 | coffset = 0
|
---|
1803 | clen = 1
|
---|
1804 | nestlevel = -1 -- -1 = stop on first 'hit'
|
---|
1805 | fortran90_rc = AssistSearch( Mode, clist, case, coffset, clen, nestlevel)
|
---|
1806 | if not rc then
|
---|
1807 | if .line = linenum & .col > 6 then
|
---|
1808 | if .col = 7 then
|
---|
1809 | text = ''
|
---|
1810 | else
|
---|
1811 | text = substr( linenum, 7, .col - 6)
|
---|
1812 | endif
|
---|
1813 | endif
|
---|
1814 | endif
|
---|
1815 | call prestore_pos( savepos3)
|
---|
1816 | endif
|
---|
1817 | compile endif
|
---|
1818 | return text
|
---|
1819 |
|
---|
1820 | ; ---------------------------------------------------------------------------
|
---|
1821 | ; In FORTRAN, spaces, which are not located within a literal, are irrelevant.
|
---|
1822 | ; This routine removes these insignificant spaces, if any.
|
---|
1823 | defproc Fortran77RemoveSpaces( text)
|
---|
1824 | do once = 1 to 1
|
---|
1825 | if not pos( ' ', text) then
|
---|
1826 | leave
|
---|
1827 | endif
|
---|
1828 |
|
---|
1829 | getfileid fid
|
---|
1830 |
|
---|
1831 | 'xcom e .temp_fortran'
|
---|
1832 | insertline text
|
---|
1833 | p = 0
|
---|
1834 | .col = 1
|
---|
1835 | .line = 1
|
---|
1836 | do forever
|
---|
1837 | p = pos( ' ', textline( 1), p + 1)
|
---|
1838 | if p then
|
---|
1839 | .col = p
|
---|
1840 | if not InsideLiteral( 'FORTRAN77') then
|
---|
1841 | delete_char
|
---|
1842 | p = 0
|
---|
1843 | .col = 1
|
---|
1844 | endif
|
---|
1845 | else
|
---|
1846 | leave
|
---|
1847 | endif
|
---|
1848 | enddo
|
---|
1849 | getline text
|
---|
1850 | .modify = 0
|
---|
1851 | 'xcom quit'
|
---|
1852 |
|
---|
1853 | activatefile fid
|
---|
1854 |
|
---|
1855 | enddo
|
---|
1856 | return text
|
---|
1857 |
|
---|
1858 | ; ---------------------------------------------------------------------------
|
---|
1859 | ; Determines if the cursor is within a comment or within a literal.
|
---|
1860 | ; Return values:
|
---|
1861 | ; 0: the cursor is NOT within a comment NOR within a literal.
|
---|
1862 | ; other: the cursor IS within a comment or within a literal.
|
---|
1863 | defproc InsideCommentLiteral( Mode)
|
---|
1864 | CurLine = arg( 2)
|
---|
1865 | if CurLine = '' then
|
---|
1866 | CurLine = .line
|
---|
1867 | endif
|
---|
1868 | CurCol = arg( 3)
|
---|
1869 | if CurCol = '' then
|
---|
1870 | CurCol = .col
|
---|
1871 | endif
|
---|
1872 | do once = 1 to 1
|
---|
1873 | rc = InsideComment( Mode, CurLine, CurCol)
|
---|
1874 | if rc <> 0 then
|
---|
1875 | leave
|
---|
1876 | endif
|
---|
1877 | rc = InsideLiteral( Mode, CurLine, CurCol)
|
---|
1878 | enddo
|
---|
1879 | return rc
|
---|
1880 |
|
---|
1881 | ; ---------------------------------------------------------------------------
|
---|
1882 | ; A front-end call to InsideLiteral2. This is used when the location of the
|
---|
1883 | ; literal, returned by InsideLiteral2, is not needed.
|
---|
1884 | defproc InsideLiteral( Mode)
|
---|
1885 | CurLine = arg( 2)
|
---|
1886 | if CurLine = '' then
|
---|
1887 | CurLine = .line
|
---|
1888 | endif
|
---|
1889 | CurCol = arg( 3)
|
---|
1890 | if CurCol = '' then
|
---|
1891 | CurCol = .col
|
---|
1892 | endif
|
---|
1893 | return InsideLiteral2( Mode, dummy, CurLine, CurCol)
|
---|
1894 |
|
---|
1895 | ; ---------------------------------------------------------------------------
|
---|
1896 | ; Determines if the cursor is within a literal. Unlike InsideCommentLiteral,
|
---|
1897 | ; this routine does not first determine if the cursor is within a comment.
|
---|
1898 | ; This is called by InsideCommentLiteral and can be
|
---|
1899 | ; called directly if the test for the presence of a comment is unneeded.
|
---|
1900 | ; Return value:
|
---|
1901 | ; 0: cursor is NOT within a literal
|
---|
1902 | ; and LitData is meaningless.
|
---|
1903 | ; 1: cursor IS within a literal
|
---|
1904 | ; and LitData is set to 2 blank-separated words:
|
---|
1905 | ; o the start col and end col of the literal.
|
---|
1906 | defproc InsideLiteral2( Mode, var LitData)
|
---|
1907 | CurLine = arg( 3)
|
---|
1908 | if CurLine = '' then
|
---|
1909 | CurLine = .line
|
---|
1910 | endif
|
---|
1911 | CurCol = arg( 4)
|
---|
1912 | if CurCol = '' then
|
---|
1913 | CurCol = .col
|
---|
1914 | endif
|
---|
1915 | --#dprintf( "lit2", "Entry: "CurLine CurCol)
|
---|
1916 | retval = 0
|
---|
1917 | call psave_pos( savepos)
|
---|
1918 | getsearch search_command -- Save caller's search command.
|
---|
1919 | do once = 1 to 1
|
---|
1920 | LineStr = textline( CurLine)
|
---|
1921 | fexit = 0
|
---|
1922 | FoundStartLitCol = 0
|
---|
1923 | FoundEndLitCol = 0
|
---|
1924 | LitData = FoundStartLitCol FoundEndLitCol
|
---|
1925 | parse value GetLitChars( Mode) with StartLitChars EndLitChars EscapeChars
|
---|
1926 | if StartLitChars = '' then
|
---|
1927 | leave
|
---|
1928 | endif
|
---|
1929 | if LineStr = '' then
|
---|
1930 | -- Start and end not on the same line: This can't be a literal
|
---|
1931 | leave
|
---|
1932 | endif
|
---|
1933 |
|
---|
1934 | EndLitCol = 0
|
---|
1935 | do forever
|
---|
1936 | StartCol = EndLitCol + 1
|
---|
1937 | next = verify( LineStr, StartLitChars, 'M', StartCol) -- find first start-of-literal
|
---|
1938 | --#dprintf( "lit2", "next CurCol LineStr: "next CurCol LineStr)
|
---|
1939 | if not next then -- if none, exit
|
---|
1940 | leave
|
---|
1941 | elseif next > CurCol then -- if past cursor position, exit
|
---|
1942 | leave
|
---|
1943 | endif
|
---|
1944 | StartLitCol = next
|
---|
1945 | FoundStartLitCol = StartLitCol
|
---|
1946 | startq = substr( LineStr, StartLitCol, 1) -- extract start-of-literal char
|
---|
1947 | qpos = pos( startq, StartLitChars) -- determine which start-of-literal char
|
---|
1948 | escapechar = substr( EscapeChars, qpos, 1) -- select matching escape char
|
---|
1949 | endq = substr( EndLitChars, qpos, 1) -- select matching end-of-literal char
|
---|
1950 | EndLitCol = StartLitCol
|
---|
1951 |
|
---|
1952 | do forever
|
---|
1953 | EndLitCol = verify( LineStr, endq''escapechar, 'M', EndLitCol + 1) -- find next end-of-literal or escape char
|
---|
1954 | --#dprintf( "lit2", "startq StartLitCol endq EndLitCol escapechar: "startq StartLitCol endq EndLitCol escapechar)
|
---|
1955 | if EndLitCol >= CurCol then -- JBSQ: Don't care if literal is properly closed?
|
---|
1956 | retval = 1
|
---|
1957 | leave
|
---|
1958 | elseif not EndLitCol then -- No end "quote"??
|
---|
1959 | --#dprintf( "lit2", "Unmatched start-of-literal character: "startq "at "CurLine","StartLitCol)
|
---|
1960 | --retval = 1 -- JBSQ: Return true on unmatched "quote"?
|
---|
1961 | -- Better don't count the rest of the line as literal and leave retval = 0.
|
---|
1962 | fexit = 1
|
---|
1963 | leave
|
---|
1964 | elseif endq = escapechar then -- escape "quote"s case 1: doubled "quotes"
|
---|
1965 | if length( LineStr) > EndLitCol then
|
---|
1966 | if substr( LineStr, EndLitCol + 1, 1) = endq then -- doubled-"quote" escape sequence?
|
---|
1967 | EndLitCol = EndLitCol + 1 -- "jump" past doubled "quote"
|
---|
1968 | --#dprintf( "lit2", "Doubled-quote")
|
---|
1969 | iterate
|
---|
1970 | else -- not escaped and EndLitCol < CurCol
|
---|
1971 | leave -- literal starts and ends before cursor col
|
---|
1972 | endif
|
---|
1973 | else -- end-of-literal at end-of-line
|
---|
1974 | retval = 1
|
---|
1975 | leave
|
---|
1976 | endif
|
---|
1977 | elseif substr( LineStr, EndLitCol, 1) = escapechar then -- escaped char
|
---|
1978 | -- JBSQ: Don't care which char and assume not at end of line?
|
---|
1979 | EndLitCol = EndLitCol + 1
|
---|
1980 | --#dprintf( "lit2", "Escaped char")
|
---|
1981 | iterate
|
---|
1982 | else -- EndLitCol > 0 and EndLitCol < CurCol, i.e. literal starts and ends before CurCol
|
---|
1983 | leave
|
---|
1984 | endif
|
---|
1985 | enddo
|
---|
1986 |
|
---|
1987 | if retval | fexit then
|
---|
1988 | leave
|
---|
1989 | endif
|
---|
1990 | enddo
|
---|
1991 |
|
---|
1992 | FoundEndLitCol = EndLitCol
|
---|
1993 | LitData = FoundStartLitCol FoundEndLitCol
|
---|
1994 | enddo -- once
|
---|
1995 | setsearch search_command -- Restores user's command so Ctrl-F works.
|
---|
1996 | call prestore_pos( savepos)
|
---|
1997 | --#dprintf( "lit2", "Exit: "retval .line .col)
|
---|
1998 | return retval
|
---|
1999 |
|
---|
2000 | ; ---------------------------------------------------------------------------
|
---|
2001 | ; A routine which, given a mode, returns the start-of-literal, end-of-literal
|
---|
2002 | ; and escape characters for that mode.
|
---|
2003 | ; The return value is three "words":
|
---|
2004 | ; o Each character of the first "word" is a start-of-literal character.
|
---|
2005 | ; o The corresponding character in the second "word" is the corresponding
|
---|
2006 | ; end-of-literal character.
|
---|
2007 | ; o The third "word" is a list of the escape characters, if any, which
|
---|
2008 | ; allow a literal to include a start-of-literal, end-of-literal or itself
|
---|
2009 | ; in a literal.
|
---|
2010 | defproc GetLitChars( Mode)
|
---|
2011 | SingleQuote = "'"
|
---|
2012 | DoubleQuote = '"'
|
---|
2013 | StartLitChars = DoubleQuote''SingleQuote
|
---|
2014 | EndLitChars = StartLitChars
|
---|
2015 | EscapeChars = '\\'
|
---|
2016 | if 0 then
|
---|
2017 | -- placeholder
|
---|
2018 | elseif wordpos( Mode, 'REXX E') then
|
---|
2019 | EscapeChars = StartLitChars
|
---|
2020 | elseif wordpos( Mode, 'MAKE RC WARPIN') then
|
---|
2021 | StartLitChars = DoubleQuote
|
---|
2022 | EndLitChars = StartLitChars
|
---|
2023 | if Mode = 'RC' then
|
---|
2024 | EscapeChars = '\\'
|
---|
2025 | else
|
---|
2026 | EscapeChars = \0\0 -- JBSQ: No escape chars for MAKE?
|
---|
2027 | endif
|
---|
2028 | elseif Mode = 'PERL' then
|
---|
2029 | StartLitChars = StartLitChars'`'
|
---|
2030 | EndLitChars = StartLitChars
|
---|
2031 | EscapeChars = '\\\'
|
---|
2032 | ; elseif Mode = 'ADA' then -- JBSQ: ADA strings and chars are default: (" " and ' ')?
|
---|
2033 | ; StartLitChars = DoubleQuote'%'
|
---|
2034 | ; EndLitChars = StartLitChars
|
---|
2035 | ; EscapeChars = \0\0 -- JBSQ: Escape Chars?
|
---|
2036 | elseif wordpos( Mode, 'DEF PASCAL FORTRAN77') > 0 then
|
---|
2037 | StartLitChars = SingleQuote
|
---|
2038 | EndLitChars = SingleQuote
|
---|
2039 | if Mode = 'DEF' then
|
---|
2040 | EscapeChars = \0
|
---|
2041 | else
|
---|
2042 | EscapeChars = SingleQuote
|
---|
2043 | endif
|
---|
2044 | -- other modes here
|
---|
2045 | endif
|
---|
2046 | return StartLitChars EndLitChars EscapeChars
|
---|
2047 |
|
---|
2048 | ; ---------------------------------------------------------------------------
|
---|
2049 | ; A front-end call to InsideComment2. This is used when the location of the
|
---|
2050 | ; comment, returned by InsideComment2, is not needed.
|
---|
2051 | defproc InsideComment( Mode)
|
---|
2052 | CurLine = arg( 2)
|
---|
2053 | if CurLine = '' then
|
---|
2054 | CurLine = .line
|
---|
2055 | endif
|
---|
2056 | CurCol = arg( 3)
|
---|
2057 | if CurCol = '' then
|
---|
2058 | CurCol = .col
|
---|
2059 | endif
|
---|
2060 | return InsideComment2( Mode, dummy, CurLine, CurCol)
|
---|
2061 |
|
---|
2062 | ; ---------------------------------------------------------------------------
|
---|
2063 | ; Determines if the cursor is located within a comment, multi-line or
|
---|
2064 | ; single-line. The input is the mode and a "var" variable
|
---|
2065 | ; (named "CommentData") in which the location of the comment is returned
|
---|
2066 | ; to the caller.
|
---|
2067 | ; Return value:
|
---|
2068 | ; 0: cursor is NOT within a comment
|
---|
2069 | ; and CommentData is meaningless
|
---|
2070 | ; 1: cursor IS within a one-line comment
|
---|
2071 | ; and CommentData is set to the column of the start of one-line
|
---|
2072 | ; comment
|
---|
2073 | ; 2: cursor IS within a multi-line comment
|
---|
2074 | ; and CommentData is set to 6 blank-separated words:
|
---|
2075 | ; o The line, col and length of the starting MLC token and
|
---|
2076 | ; o the line, col and length of the ending MLC token.
|
---|
2077 | defproc InsideComment2( Mode, var CommentData)
|
---|
2078 | CurLine = arg( 3)
|
---|
2079 | if CurLine = '' then
|
---|
2080 | CurLine = .line
|
---|
2081 | endif
|
---|
2082 | CurCol = arg( 4)
|
---|
2083 | if CurCol = '' then
|
---|
2084 | CurCol = .col
|
---|
2085 | endif
|
---|
2086 | display -2
|
---|
2087 | --#dprintf( "comm", "Entry: "CurLine","CurCol)
|
---|
2088 | call psave_pos( savepos)
|
---|
2089 | getsearch search_command -- Save caller's search command.
|
---|
2090 | retval = 0
|
---|
2091 | CommentData = ""
|
---|
2092 | LineStr = textline( CurLine)
|
---|
2093 | if QueryModeKey( Mode, 'CaseSensitive', '1') then
|
---|
2094 | MLCCase = 'e' -- case-sensitive (exact)
|
---|
2095 | else
|
---|
2096 | MLCCase = 'c' -- caseless
|
---|
2097 | endif
|
---|
2098 |
|
---|
2099 | MLCData = LocateMLC( Mode, CurLine, CurCol)
|
---|
2100 | parse value MLCData with BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen
|
---|
2101 | if BestMLCStartLine > 0 then
|
---|
2102 | retval = 2
|
---|
2103 | endif
|
---|
2104 | --#dprintf( "comm", "Retval on exit of outer MLC loop: "retval", cursor: ".line",".col)
|
---|
2105 |
|
---|
2106 | if retval = 0 then
|
---|
2107 | SLCPosition = InsideSLC( Mode, CurLine, CurCol)
|
---|
2108 | CommentData = SLCPosition
|
---|
2109 | retval = (SLCPosition > 0)
|
---|
2110 | else
|
---|
2111 | CommentData = BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen
|
---|
2112 | endif
|
---|
2113 |
|
---|
2114 | setsearch search_command -- Restores user's command so Ctrl-F works.
|
---|
2115 | call prestore_pos( savepos)
|
---|
2116 | display 2
|
---|
2117 | --#dprintf( "comm", "MLC rc CommentData: "retval CommentData)
|
---|
2118 |
|
---|
2119 | --dprintf( 'InsideComment2: retval = 'retval)
|
---|
2120 | return retval
|
---|
2121 |
|
---|
2122 | ; ---------------------------------------------------------------------------
|
---|
2123 | ; A front-end call to LocateMLC. This is used when the location of the
|
---|
2124 | ; comment, returned by LocateMLC, is not needed.
|
---|
2125 | defproc InsideMLC( Mode)
|
---|
2126 | CurLine = arg( 2)
|
---|
2127 | if CurLine = '' then
|
---|
2128 | CurLine = .line
|
---|
2129 | endif
|
---|
2130 | CurCol = arg( 3)
|
---|
2131 | if CurCol = '' then
|
---|
2132 | CurCol = .col
|
---|
2133 | endif
|
---|
2134 | retval = 0
|
---|
2135 | MLCData = LocateMLC( Mode, CurLine, CurCol)
|
---|
2136 | parse value MLCData with BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen
|
---|
2137 | if BestMLCStartLine > 0 then
|
---|
2138 | retval = 1
|
---|
2139 | endif
|
---|
2140 |
|
---|
2141 | --dprintf( retval' = InsideMLC( 'Mode', 'CurLine', 'CurCol'), Start 'MLCStart' = ('MLCStartLine','MLCStartCol'), End = 'MLCEnd' ('MLCEndLine','MLCEndCol')')
|
---|
2142 | return retval
|
---|
2143 |
|
---|
2144 | ; ---------------------------------------------------------------------------
|
---|
2145 | ; Determines if provided location (line, col) is within a multi-line comment
|
---|
2146 | ; (MLC) for the provided mode. The return value is six space-separated
|
---|
2147 | ; numbers representing:
|
---|
2148 | ; - Start line of MLC
|
---|
2149 | ; - Start col of MLC
|
---|
2150 | ; - Length of the Start MLC token
|
---|
2151 | ; - End line of MLC
|
---|
2152 | ; - End col of MLC
|
---|
2153 | ; - Length of the End MLC token
|
---|
2154 | ; All zeroes indicate that the given line, col is NOT within an MLC.
|
---|
2155 | ; Binary search.
|
---|
2156 | defproc LocateMLC( Mode, CurLine, CurCol)
|
---|
2157 | universal curkey
|
---|
2158 | universal prevkey
|
---|
2159 |
|
---|
2160 | --dprintf( 'LocateMLC( 'Mode', 'CurLine', 'CurCol')')
|
---|
2161 | getfileid fid
|
---|
2162 | BestMLCStartLine = 0
|
---|
2163 | BestMLCStartCol = 0
|
---|
2164 | BestMLCStartLen = 0
|
---|
2165 | BestMLCEndLine = 0
|
---|
2166 | BestMLCEndCol = 0
|
---|
2167 | BestMLCEndLen = 0
|
---|
2168 | retval = 0
|
---|
2169 | -- i = counter for MLC pairs
|
---|
2170 | -- j = counter for MLC list items
|
---|
2171 |
|
---|
2172 | -- Must query ModeMLCCount and set the other MLC vars here to handle
|
---|
2173 | -- modes with nested MLCs
|
---|
2174 | ModeMLCCount = GetAVar( 'assist.mode.'Mode'.MLC.0')
|
---|
2175 | if ModeMLCCount = '' then
|
---|
2176 | call GetMLCChars( Mode, MLCStartChars, MLCEndChars, MLCNestList, MLCEndPrioList)
|
---|
2177 | ModeMLCCount = words( MLCStartChars)
|
---|
2178 | call SetAVar( 'assist.mode.'Mode'.MLC.0', ModeMLCCount)
|
---|
2179 | do i = 1 to ModeMLCCount
|
---|
2180 | call SetAVar( 'assist.mode.'Mode'.MLCStart.'i, word( MLCStartChars, i))
|
---|
2181 | call SetAVar( 'assist.mode.'Mode'.MLCEnd.'i, word( MLCEndChars, i))
|
---|
2182 | call SetAVar( 'assist.mode.'Mode'.MLCNest.'i, word( MLCNestList, i))
|
---|
2183 | call SetAVar( 'assist.mode.'Mode'.MLCEndPrio.'i, word( MLCEndPrioList, i))
|
---|
2184 | enddo
|
---|
2185 | endif
|
---|
2186 |
|
---|
2187 | --#dprintf( "array", "Extracted Starts: "MLCStartChars "Ends: "MLCEndChars "Nests: "MLCNestList "Count: "ModeMLCCount)
|
---|
2188 | fArrayValid = (GetAVar( fid'.assist.ArrayValid') = 1)
|
---|
2189 | --#dprintf( "array", "fArrayValid: '"fArrayValid"'")
|
---|
2190 | PrevModify = GetAVar( fid'.assist.Modify')
|
---|
2191 | fModifyChanged = (fid.modify <> PrevModify)
|
---|
2192 | parse value curkey with CurKeyString \1 CurCmd
|
---|
2193 | parse value prevkey with PrevKeyString \1 PrevCmd
|
---|
2194 | fSameCmd = (CurCmd = PrevCmd)
|
---|
2195 | -- For non-repeated keys rebuild the array when .modify has changed
|
---|
2196 | if not fSameCmd & fModifyChanged then
|
---|
2197 | fArrayValid = 0
|
---|
2198 | endif
|
---|
2199 |
|
---|
2200 | fUseArray = GetAvar( 'assist.fUseArray')
|
---|
2201 | -- Modes with nested MLCs must use the array method
|
---|
2202 | fModeSupportsNestedMLCs = 0
|
---|
2203 | do i = 1 to ModeMLCCount
|
---|
2204 | MLCNest = GetAVar( 'assist.mode.'Mode'.MLCNest.'i)
|
---|
2205 | if MLCNest then
|
---|
2206 | fModeSupportsNestedMLCs = 1
|
---|
2207 | leave
|
---|
2208 | endif
|
---|
2209 | enddo
|
---|
2210 | if not fUseArray & fModeSupportsNestedMLCs then
|
---|
2211 | fUseArray = 1
|
---|
2212 | endif
|
---|
2213 | -- If a valid array exists, always prefer this method, because it's faster
|
---|
2214 | if fArrayValid then
|
---|
2215 | fUseArray = 1
|
---|
2216 | endif
|
---|
2217 |
|
---|
2218 | if fUseArray then
|
---|
2219 | if not fArrayValid then
|
---|
2220 | -- Build MLC array
|
---|
2221 | --dprintf( 'BuildMLCArray( 'Mode'), '.filename', 'DateTime())
|
---|
2222 | call BuildMLCArray( Mode)
|
---|
2223 | --#dprintf( "array", "LocateMLC Mode: "Mode CurLine","CurCol "ModeMLCCount: "ModeMLCCount)
|
---|
2224 | endif
|
---|
2225 |
|
---|
2226 | do i = 1 to ModeMLCCount
|
---|
2227 | MLCListcount = GetAVar( fid'.assist.'i'.List.0')
|
---|
2228 | --#dprintf( "array", "Listcount #"i": "MLCListCount)
|
---|
2229 | --dprintf( 'MLCListCount = 'MLCListCount', i = 'i', ModeMLCCount = 'ModeMLCCount)
|
---|
2230 | if MLCListCount = '' then
|
---|
2231 | MLCListCount = 0
|
---|
2232 | endif
|
---|
2233 |
|
---|
2234 | -- Start values
|
---|
2235 | lval = 1
|
---|
2236 | rval = MLCListcount
|
---|
2237 | do forever
|
---|
2238 | if rval < lval then
|
---|
2239 | leave
|
---|
2240 | endif
|
---|
2241 | -- Next list item value
|
---|
2242 | j = (lval + rval) % 2
|
---|
2243 |
|
---|
2244 | -- Query MLC array var value for j.
|
---|
2245 | MLCEntry = GetAVar( fid'.assist.'i'.List.'j)
|
---|
2246 | parse value MLCEntry with MLCStartLine MLCStartCol MLCStartLen MLCEndLine MLCEndCol MLCEndLen MLCNestStartLine MLCNestStartCol .
|
---|
2247 |
|
---|
2248 | -- Check if MLC j ended before the current pos.
|
---|
2249 | fEndBefore = 0
|
---|
2250 | if MLCEndLine < CurLine then
|
---|
2251 | fEndBefore = 1
|
---|
2252 | elseif MLCEndLine = CurLine then
|
---|
2253 | if not (MLCEndCol + MLCEndLen > CurCol) then
|
---|
2254 | fEndBefore = 1
|
---|
2255 | endif
|
---|
2256 | endif
|
---|
2257 | if fEndBefore then
|
---|
2258 | -- Increase lval
|
---|
2259 | lval = j + 1
|
---|
2260 | iterate
|
---|
2261 | endif
|
---|
2262 |
|
---|
2263 | -- Check if MLC j started after the current pos.
|
---|
2264 | fStartAfter = 0
|
---|
2265 | if MLCStartLine > CurLine then
|
---|
2266 | fStartAfter = 1
|
---|
2267 | elseif MLCStartLine = CurLine then
|
---|
2268 | if not (MLCStartCol <= CurCol) then
|
---|
2269 | fStartAfter = 1
|
---|
2270 | endif
|
---|
2271 | endif
|
---|
2272 | if fStartAfter then
|
---|
2273 | -- Decrease rval
|
---|
2274 | rval = j - 1
|
---|
2275 | iterate
|
---|
2276 | endif
|
---|
2277 |
|
---|
2278 | -- Best match found
|
---|
2279 | parse value MLCEntry with BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen .
|
---|
2280 | --dprintf( 'Best: 'MLCEntry)
|
---|
2281 | --#dprintf( "array", " Best, so far" MLCEntry)
|
---|
2282 | leave -- LISTCOMM: with current buildMLC logic, first should be "best"
|
---|
2283 | enddo
|
---|
2284 | enddo
|
---|
2285 |
|
---|
2286 | else
|
---|
2287 | -- Most of the following lines are also used in BuildMLC
|
---|
2288 | if QueryModeKey( Mode, 'CaseSensitive', '1') then
|
---|
2289 | MLCCase = 'e' -- case-sensitive (exact)
|
---|
2290 | else
|
---|
2291 | MLCCase = 'c' -- caseless
|
---|
2292 | endif
|
---|
2293 | ModeMLCCount = GetAVar( 'assist.mode.'Mode'.MLC.0')
|
---|
2294 |
|
---|
2295 | do i = 1 to ModeMLCCount
|
---|
2296 | MLCStart = GetAVar( 'assist.mode.'Mode'.MLCStart.'i)
|
---|
2297 | MLCEnd = GetAVar( 'assist.mode.'Mode'.MLCEnd.'i)
|
---|
2298 | MLCNest = GetAVar( 'assist.mode.'Mode'.MLCNest.'i)
|
---|
2299 | MLCEndPrio = GetAVar( 'assist.mode.'Mode'.MLCEndPrio.'i)
|
---|
2300 |
|
---|
2301 | MLCStartSearch = EscapeSearchChars( MLCStart)
|
---|
2302 | MLCEndSearch = EscapeSearchChars( MLCEnd)
|
---|
2303 | MLCStartLen = length( MLCStart)
|
---|
2304 | MLCEndLen = length( MLCEnd)
|
---|
2305 |
|
---|
2306 | SearchCmdStart = 'xcom l '\1''MLCStartSearch''\1'x'MLCCase
|
---|
2307 | SearchCmdEnd = 'xcom l '\1''MLCEndSearch''\1'x'MLCCase
|
---|
2308 | SearchCmdBoth = 'xcom l '\1'('MLCStartSearch'|'MLCEndSearch')'\1'x'MLCCase
|
---|
2309 |
|
---|
2310 | Direction = '-R' -- Backward
|
---|
2311 | setsearch SearchCmdBoth''Direction
|
---|
2312 | .line = CurLine
|
---|
2313 | .col = CurCol
|
---|
2314 |
|
---|
2315 | MLCStartLine = 0
|
---|
2316 | MLCStartCol = 0
|
---|
2317 | MLCEndLine = 0
|
---|
2318 | MLCEndCol = 0
|
---|
2319 | fSearchFirst = 1
|
---|
2320 | do forever
|
---|
2321 | if fSearchFirst then
|
---|
2322 | -- Get string at the cursor
|
---|
2323 | startcol = .col
|
---|
2324 | rc = 1
|
---|
2325 | LineStr = textline( .line)
|
---|
2326 | do l = 1 to MLCStartLen
|
---|
2327 | if .col = 1 then
|
---|
2328 | leave
|
---|
2329 | endif
|
---|
2330 | .col = startcol - (l - 1)
|
---|
2331 | ThisMLC = substr( LineStr, .col, MLCStartLen)
|
---|
2332 | if ThisMLC = MLCStart then
|
---|
2333 | rc = 0
|
---|
2334 | leave
|
---|
2335 | endif
|
---|
2336 | end
|
---|
2337 |
|
---|
2338 | if rc = 1 then
|
---|
2339 | .col = startcol
|
---|
2340 | repeatfind
|
---|
2341 | endif
|
---|
2342 | fSearchFirst = 0
|
---|
2343 | else
|
---|
2344 | repeatfind
|
---|
2345 | endif
|
---|
2346 |
|
---|
2347 | if rc then
|
---|
2348 | retval = 0
|
---|
2349 | leave
|
---|
2350 | endif
|
---|
2351 | ThisMLC = substr( textline( .line), .col, MLCStartLen)
|
---|
2352 | if ThisMLC = MLCStart then
|
---|
2353 | if InsideSLC( Mode) then
|
---|
2354 | iterate
|
---|
2355 | endif
|
---|
2356 | if InsideLiteral( Mode) then
|
---|
2357 | iterate
|
---|
2358 | endif
|
---|
2359 | -- MLCStart after MLCEnd => within MLC
|
---|
2360 | MLCStartLine = .line
|
---|
2361 | MLCStartCol = .col
|
---|
2362 | retval = 1
|
---|
2363 | leave
|
---|
2364 | else
|
---|
2365 | if MLCEndPrio = 0 then -- 1 = default value
|
---|
2366 | -- 0 = Started MLCs have higher priority than SLCs and strings.
|
---|
2367 | -- That means that for recognizing a MLC end, it can follow a
|
---|
2368 | -- SLC string or a string opener. In between two corresponding
|
---|
2369 | -- MLC strings all other chars are ignored.
|
---|
2370 | if InsideSLC( Mode) then
|
---|
2371 | iterate
|
---|
2372 | endif
|
---|
2373 | if InsideLiteral( Mode) then
|
---|
2374 | iterate
|
---|
2375 | endif
|
---|
2376 | endif
|
---|
2377 |
|
---|
2378 | -- MLCEnd after MLCStart => not within MLC
|
---|
2379 | MLCEndLine = .line
|
---|
2380 | MLCEndCol = .col
|
---|
2381 | retval = 0
|
---|
2382 | leave
|
---|
2383 | endif
|
---|
2384 | enddo
|
---|
2385 | if retval = 1 then
|
---|
2386 | leave
|
---|
2387 | endif
|
---|
2388 | enddo
|
---|
2389 |
|
---|
2390 | if retval = 1 then
|
---|
2391 | -- Make InsideComment2 return 2 and InsideMLC return 1
|
---|
2392 | BestMLCStartLine = 1
|
---|
2393 | endif
|
---|
2394 |
|
---|
2395 | endif
|
---|
2396 |
|
---|
2397 | --dprintf( 'LocateMLC: return = 'BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen)
|
---|
2398 | return BestMLCStartLine BestMLCStartCol BestMLCStartLen BestMLCEndLine BestMLCEndCol BestMLCEndLen
|
---|
2399 |
|
---|
2400 | ; ---------------------------------------------------------------------------
|
---|
2401 | ; Builds an array containing the start and end points of all multi-line
|
---|
2402 | ; comments in the current file.
|
---|
2403 | defproc BuildMLCArray( Mode)
|
---|
2404 | getfileid fid
|
---|
2405 | if QueryModeKey( Mode, 'CaseSensitive', '1') then
|
---|
2406 | MLCCase = 'e' -- case-sensitive (exact)
|
---|
2407 | else
|
---|
2408 | MLCCase = 'c' -- caseless
|
---|
2409 | endif
|
---|
2410 | ModeMLCCount = GetAVar( 'assist.mode.'Mode'.MLC.0')
|
---|
2411 |
|
---|
2412 | --#dprintf( "array", "Build mode: "Mode "MLCCount: "ModeMLCCount)
|
---|
2413 | do once = 1 to 1
|
---|
2414 | call pSave_Pos( savepos)
|
---|
2415 | do i = 1 to ModeMLCCount
|
---|
2416 | MLCStart = GetAVar( 'assist.mode.'Mode'.MLCStart.'i)
|
---|
2417 | MLCEnd = GetAVar( 'assist.mode.'Mode'.MLCEnd.'i)
|
---|
2418 | MLCNest = GetAVar( 'assist.mode.'Mode'.MLCNest.'i)
|
---|
2419 | MLCEndPrio = GetAVar( 'assist.mode.'Mode'.MLCEndPrio.'i)
|
---|
2420 |
|
---|
2421 | --#dprintf( "array", "MLC data: "MLCStart MLCEnd MLCNest)
|
---|
2422 | MLCStartSearch = EscapeSearchChars( MLCStart)
|
---|
2423 | MLCEndSearch = EscapeSearchChars( MLCEnd)
|
---|
2424 | --#dprintf( "array", ""MLCStart "search = "MLCStartSearch)
|
---|
2425 | --#dprintf( "array", ""MLCEnd "search = "MLCEndSearch)
|
---|
2426 | MLCStartLen = length( MLCStart)
|
---|
2427 | MLCEndLen = length( MLCEnd)
|
---|
2428 | .line = 1
|
---|
2429 | .col = 1
|
---|
2430 | array_index = 0 -- LISTCOMM: assumes a separate list for each MLC string-pair is built
|
---|
2431 | NestedStartsList = ''
|
---|
2432 | AdvLen = 0
|
---|
2433 |
|
---|
2434 | do forever
|
---|
2435 |
|
---|
2436 | -- Use setsearch and repeatfind to move the cursor after a previous search
|
---|
2437 | -- Bugs of 'xcom l', 'xcom c' and repeatfind:
|
---|
2438 | -- 'xcom l' and 'xcom c' don't move the cursor, repeatfind does.
|
---|
2439 | -- ... (see locate.e)
|
---|
2440 | -- repeatfind at the start pos. won't start searching at that pos.,
|
---|
2441 | -- but xcom l does.
|
---|
2442 | --setsearch 'xcom l '\1''MLCStartSearch''\1'x'MLCCase'+F'
|
---|
2443 | --repeatfind
|
---|
2444 | SearchCmdStart = 'xcom l '\1''MLCStartSearch''\1'x'MLCCase'+F'
|
---|
2445 | SearchCmdEnd = 'xcom l '\1''MLCEndSearch''\1'x'MLCCase'+F'
|
---|
2446 | SearchCmdBoth = 'xcom l '\1'('MLCStartSearch'|'MLCEndSearch')'\1'x'MLCCase'+F'
|
---|
2447 |
|
---|
2448 | -- Search the MLC start
|
---|
2449 | do l = 1 to AdvLen
|
---|
2450 | right
|
---|
2451 | enddo
|
---|
2452 | -- Search the MLC end
|
---|
2453 | SearchCmdStart
|
---|
2454 | if rc then
|
---|
2455 | leave
|
---|
2456 | endif
|
---|
2457 | AdvLen = MLCStartLen
|
---|
2458 |
|
---|
2459 | -- Check if position is within a SLC or a literal
|
---|
2460 | if InsideSLC( Mode) then
|
---|
2461 | iterate
|
---|
2462 | endif
|
---|
2463 | if InsideLiteral( Mode) then
|
---|
2464 | iterate
|
---|
2465 | endif
|
---|
2466 |
|
---|
2467 | MLCStartLine = .line
|
---|
2468 | MLCStartCol = .col
|
---|
2469 | --#dprintf( "comm", MLCStart "found at" MLCStartLine MLCStartCol)
|
---|
2470 | NestedStartsList = MLCStartLine MLCStartCol NestedStartsList
|
---|
2471 |
|
---|
2472 | -- Search the MLC end - for modes with nesting, search both
|
---|
2473 | do while (NestedStartsList <> '')
|
---|
2474 | --#dprintf( "comm", "MLCEnd, presearch loc: ".line",".col)
|
---|
2475 | do l = 1 to AdvLen
|
---|
2476 | right
|
---|
2477 | enddo
|
---|
2478 | -- Search the matching MLC end
|
---|
2479 | if MLCNest then
|
---|
2480 | SearchCmdBoth
|
---|
2481 | else
|
---|
2482 | SearchCmdEnd
|
---|
2483 | endif
|
---|
2484 | if rc then
|
---|
2485 | leave
|
---|
2486 | endif
|
---|
2487 |
|
---|
2488 | -- For a found MLC end
|
---|
2489 | if substr( textline( .line), .col, MLCEndLen) = MLCEnd then
|
---|
2490 | AdvLen = MLCEndLen
|
---|
2491 | -- Check if position is within a SLC or a literal
|
---|
2492 | if MLCEndPrio = 0 then -- 1 = default value
|
---|
2493 | -- 0 = Started MLCs have higher priority than SLCs and strings.
|
---|
2494 | -- That means that for recognizing a MLC end, it can follow a
|
---|
2495 | -- SLC string or a string opener. In between two corresponding
|
---|
2496 | -- MLC strings all other chars are ignored.
|
---|
2497 |
|
---|
2498 | --#dprintf( "comm", "MLCEnd, postsearch loc: ".line",".col)
|
---|
2499 | SLCPosition = InsideSLC( Mode, .line, .col)
|
---|
2500 | if SLCPosition then
|
---|
2501 | iterate
|
---|
2502 | endif
|
---|
2503 |
|
---|
2504 | if InsideLiteral( Mode) then
|
---|
2505 | iterate
|
---|
2506 | endif
|
---|
2507 | --#dprintf( "comm", "line# ".line" col: ".col" text: "textline( .line))
|
---|
2508 | endif
|
---|
2509 |
|
---|
2510 | -- Remove matching MLCStartLine MLCStartCol from NestedStartsList
|
---|
2511 | parse value NestedStartsList with MLCStartLine MLCStartCol NestedStartsList
|
---|
2512 | array_value = MLCStartLine MLCStartCol MLCStartLen .line .col MLCEndLen NestedStartsList
|
---|
2513 |
|
---|
2514 | -- Save only unnested MLCs: Nested MLCs can be ignored.
|
---|
2515 | -- They would slow down LocateMLC and complicate it as well:
|
---|
2516 | if NestedStartsList = '' then
|
---|
2517 | array_index = array_index + 1
|
---|
2518 | call SetAvar( fid'.assist.'i'.List.'array_index, array_value)
|
---|
2519 | else
|
---|
2520 | --dprintf( 'MLC --: 'array_value' (nested, not saved)')
|
---|
2521 | endif
|
---|
2522 |
|
---|
2523 | -- For a found MLC start (if nesting is allowed)
|
---|
2524 | else
|
---|
2525 | -- this code should only be reached if MLCNest = 1 and MLCStart was matched
|
---|
2526 | AdvLen = MLCStartLen
|
---|
2527 | NestedStartsList = .line .col NestedStartsList
|
---|
2528 |
|
---|
2529 | endif
|
---|
2530 | --#dprintf( "comm", 'after Nestlist: 'NestedStartsList)
|
---|
2531 | enddo
|
---|
2532 |
|
---|
2533 | if NestedStartsList <> '' then
|
---|
2534 | --#dprintf( "comm", 'Unmatched MLCs: 'NestedStartsList)
|
---|
2535 | /*
|
---|
2536 | sayerror 'Unmatched MLCs: 'NestedStartsList
|
---|
2537 | */
|
---|
2538 | leave
|
---|
2539 | endif
|
---|
2540 |
|
---|
2541 | -- Save the number of found MLC entries for this MLC string-pair
|
---|
2542 | call SetAvar( fid'.assist.'i'.List.0', array_index)
|
---|
2543 |
|
---|
2544 | enddo -- End of loop for each unnested comment
|
---|
2545 |
|
---|
2546 | enddo -- End of loop for each MLC string-pair
|
---|
2547 |
|
---|
2548 | call SetAVar( fid'.assist.Modify', fid.modify)
|
---|
2549 | call SetAvar( fid'.assist.ArrayValid', 1)
|
---|
2550 | call pRestore_Pos( savepos)
|
---|
2551 | enddo -- once
|
---|
2552 | return
|
---|
2553 |
|
---|
2554 | ; ---------------------------------------------------------------------------
|
---|
2555 | ; Returns the tokens which start and end multi-line comments
|
---|
2556 | ; for the given mode. Also returned is whether the MLC can be nested
|
---|
2557 | ; within another MLC. These values are returned through three "var"
|
---|
2558 | ; parameters. Each "word" of each these parameters represents the
|
---|
2559 | ; start token, the end token and a flag indicating if theat MLC can
|
---|
2560 | ; be nested within another.
|
---|
2561 | defproc GetMLCChars( Mode, var MLCStartChars, var MLCEndChars, var MLCNestList, var MLCEndPrioList)
|
---|
2562 | MLCStartChars = QueryModeKey( Mode, 'MultiLineCommentStart')
|
---|
2563 | if MLCStartChars <> '' then
|
---|
2564 | MLCEndChars = QueryModeKey( Mode, 'MultiLineCommentEnd')
|
---|
2565 | MLCNestList = QueryModeKey( Mode, 'MultiLineCommentNested', '0')
|
---|
2566 | MLCEndPrioList = QueryModeKey( Mode, 'MultiLineCommentEndPrio', '1')
|
---|
2567 | endif
|
---|
2568 | return
|
---|
2569 |
|
---|
2570 | ; ---------------------------------------------------------------------------
|
---|
2571 | ; This routine takes a "search-for-this" search string and it inserts escape
|
---|
2572 | ; characters in front of any extended grep metacharacters.
|
---|
2573 | ; For example, if the search string is "(abc)" (i.e. find "(abc)"), this
|
---|
2574 | ; routine returns "\(abc\)" because "(" and ")" are extended grep
|
---|
2575 | ; metacharacters and so they must be "escaped" with "\".
|
---|
2576 | defproc EscapeSearchChars( SearchStr)
|
---|
2577 | p = -1
|
---|
2578 | do forever
|
---|
2579 | if SearchStr == '' then
|
---|
2580 | leave
|
---|
2581 | endif
|
---|
2582 | p = verify( SearchStr, EGREP_METACHARACTERS, 'M', p + 2)
|
---|
2583 | if not p then
|
---|
2584 | leave
|
---|
2585 | else
|
---|
2586 | SearchStr = leftstr( SearchStr, p - 1)'\'substr( SearchStr, p)
|
---|
2587 | endif
|
---|
2588 | enddo
|
---|
2589 | return SearchStr
|
---|
2590 |
|
---|
2591 | ; ---------------------------------------------------------------------------
|
---|
2592 | ; Determines if the cursor is located within a single-line comment.
|
---|
2593 | ; Returns the column of the start of the comment. A value of 0 is returned,
|
---|
2594 | ; if no one-line comment is found.
|
---|
2595 | defproc InsideSLC( Mode)
|
---|
2596 | CurLine = arg( 2)
|
---|
2597 | if CurLine = '' then
|
---|
2598 | CurLine = .line
|
---|
2599 | endif
|
---|
2600 | CurCol = arg( 3)
|
---|
2601 | if CurCol = '' then
|
---|
2602 | CurCol = .col
|
---|
2603 | endif
|
---|
2604 |
|
---|
2605 | --#dprintf( "1line", "Entry: "CurLine CurCol "mode = "Mode)
|
---|
2606 | LineStr = textline( CurLine)
|
---|
2607 | retval = 0
|
---|
2608 |
|
---|
2609 | SLCCount = GetAVar( 'assist.mode.'Mode'.SLC.0')
|
---|
2610 | if SLCCount = '' then
|
---|
2611 | call GetSLCChars( Mode, SLCCharList, SLCPosList, SLCNeedList)
|
---|
2612 | SLCCount = words( SLCCharList)
|
---|
2613 | --#dprintf( "1line", "SLCCount: "SLCCount)
|
---|
2614 | call SetAVar( 'assist.mode.'Mode'.SLC.0', SLCCount)
|
---|
2615 | do i = 1 to SLCCount
|
---|
2616 | call SetAVar( 'assist.mode.'Mode'.SLC.'i, word( SLCCharList, i))
|
---|
2617 | call SetAVar( 'assist.mode.'Mode'.SLCPos.'i, word( SLCPosList, i))
|
---|
2618 | call SetAVar( 'assist.mode.'Mode'.SLCNeed.'i, word( SLCNeedList, i))
|
---|
2619 | enddo
|
---|
2620 | endif
|
---|
2621 |
|
---|
2622 | do SLCIndex = 1 to SLCCount
|
---|
2623 | SLC = GetAVar( 'assist.mode.'Mode'.SLC.'SLCIndex)
|
---|
2624 | SLCPos = GetAVar( 'assist.mode.'Mode'.SLCPos.'SLCIndex)
|
---|
2625 | SLCNeed = GetAVar( 'assist.mode.'Mode'.SLCNeed.'SLCIndex)
|
---|
2626 | --#dprintf( "1line", "SLC/Pos/Need: "SLC"/"SLCPos"/"SLCNeed)
|
---|
2627 |
|
---|
2628 | if SLCNeed = 1 then
|
---|
2629 | SLC = SLC' '
|
---|
2630 | endif
|
---|
2631 |
|
---|
2632 | /*
|
---|
2633 | -- Disabled, because column restrictions are only valid for Fortran < 90.
|
---|
2634 | -- Therefore the '!' comment char of Fortran90 can't be affected.
|
---|
2635 | -- Fortran77 doesn't need a special treatment here, because a '*' or 'C'
|
---|
2636 | -- comment has to start in column 1.
|
---|
2637 |
|
---|
2638 | -- Extension for Fortran90's SLC "!". SLCPos for this char is -6.
|
---|
2639 | -- SLCPos = -6 means: any column except column 6
|
---|
2640 | if SLCPos < 0 then
|
---|
2641 | if CurCol = -SLCPos + 1 then -- needs + 1 to handle '!' in column 6
|
---|
2642 | return 0
|
---|
2643 | else
|
---|
2644 | SLCPos = '0' -- SLC is in an acceptable column so treat it as any other '0'-type
|
---|
2645 | endif
|
---|
2646 | endif
|
---|
2647 | */
|
---|
2648 |
|
---|
2649 | -- SLCPos = 0 means: any column is allowed
|
---|
2650 | if SLCPos = '0' then
|
---|
2651 | savecol = CurCol
|
---|
2652 | len = length( SLC)
|
---|
2653 | p = 1 - len
|
---|
2654 | do forever
|
---|
2655 | p = pos( SLC, LineStr, p + len)
|
---|
2656 | if (p = 0) then -- if not found
|
---|
2657 | leave
|
---|
2658 | elseif (p >= savecol) then -- if found on or after cursor column
|
---|
2659 | leave
|
---|
2660 | elseif (retval > 0 & p >= retval) then -- if later than a previously found comment
|
---|
2661 | leave
|
---|
2662 | endif
|
---|
2663 | CurCol = p
|
---|
2664 | if not InsideLiteral( Mode) then
|
---|
2665 | leave
|
---|
2666 | endif
|
---|
2667 | enddo
|
---|
2668 | CurCol = savecol
|
---|
2669 | if (p & p <= CurCol) then -- if found before cursor location
|
---|
2670 | if (retval = 0 | (retval > 0 & p < retval)) then
|
---|
2671 | retval = p
|
---|
2672 | --#dprintf( "1line", "Found "SLC" comment")
|
---|
2673 | endif
|
---|
2674 | endif
|
---|
2675 |
|
---|
2676 | -- SLCPos = F means: first non-blank char in LineStr
|
---|
2677 | elseif SLCPos = 'F' then
|
---|
2678 | --#dprintf( "1line", "PosF "leftstr( word( LineStr, 1), length( SLC)))
|
---|
2679 | if leftstr( word( LineStr, 1), length( SLC)) = SLC then -- if line starts with a comment
|
---|
2680 | --#dprintf( "1line", "Found '"SLC"' comm")
|
---|
2681 | p = pos( SLC, LineStr)
|
---|
2682 | if (retval = 0) | (p < retval) then
|
---|
2683 | retval = p
|
---|
2684 | endif
|
---|
2685 | endif
|
---|
2686 |
|
---|
2687 | -- SLCPos = 1 means: only column 1 is allowed
|
---|
2688 | elseif SLCPos = '1' then
|
---|
2689 | --#dprintf( "1line", "Pos1 "leftstr( LineStr, length( SLC)))
|
---|
2690 | if leftstr( LineStr, length( SLC)) = SLC then -- if line starts with a comment in column 1
|
---|
2691 | --#dprintf( "1line", "Found '"SLC"' comm")
|
---|
2692 | retval = 1
|
---|
2693 | leave
|
---|
2694 | endif
|
---|
2695 | endif
|
---|
2696 |
|
---|
2697 | enddo
|
---|
2698 | --#dprintf( "1line", "Exit: "retval CurLine CurCol)
|
---|
2699 | return retval
|
---|
2700 |
|
---|
2701 | ; ---------------------------------------------------------------------------
|
---|
2702 | ; Returns the single-line comment data for the given mode.
|
---|
2703 | ; For each possible SLC the following is returned:
|
---|
2704 | ; o The token which initiates the SLC
|
---|
2705 | ; (SLCCharlist)
|
---|
2706 | ; o A flag indicating any positional requirements
|
---|
2707 | ; (SLCPosList)
|
---|
2708 | ; 0: SLC can start anywhere on a line
|
---|
2709 | ; 1: SLC MUST start in column 1
|
---|
2710 | ; F: SLC must be the first non-blank on the line
|
---|
2711 | ; <negative_number> : SLC must NOT start in this column
|
---|
2712 | ; (-6 means SLC must NOT start in column 6)
|
---|
2713 | ; o A flag indicating if the token must be followed by a blank
|
---|
2714 | ; (SLCNeedList)
|
---|
2715 | ; 0: No (i.e. ANY character may follow the start token
|
---|
2716 | ; 1: A blank must follow the token
|
---|
2717 | defproc GetSLCChars( Mode, var SLCCharList, var SLCPosList, var SLCNeedList)
|
---|
2718 | SLCCharList = QueryModeKey( Mode, 'LineComment', '')
|
---|
2719 | if SLCCharList <> '' then
|
---|
2720 | SLCNeedList = QueryModeKey( Mode, 'LineCommentNeedSpace', '0')
|
---|
2721 | SLCPosList = QueryModeKey( Mode, 'LineCommentPos', '0')
|
---|
2722 | endif
|
---|
2723 | return
|
---|
2724 |
|
---|
2725 | ; ---------------------------------------------------------------------------
|
---|
2726 | ; Makes the multi-line comment array rebuild on next pAssist call.
|
---|
2727 | defproc InvalidateMlcArray()
|
---|
2728 | getfileid fid
|
---|
2729 | call SetAvar( fid'.assist.ArrayValid', 0)
|
---|
2730 |
|
---|
2731 | return
|
---|
2732 |
|
---|
2733 | ; ---------------------------------------------------------------------------
|
---|
2734 | ; Repositions the cursor on the next non-blank, non-comment and non-literal
|
---|
2735 | ; character.
|
---|
2736 | ; Syntax: NextCodeChar( Mode [, Line [, Col [, Direction]]])
|
---|
2737 | ; The default values for Line and Col are the current cursor position.
|
---|
2738 | ; Direction = '+F' | '-R'. The default direction is '+F'.
|
---|
2739 | defproc NextCodeChar( Mode)
|
---|
2740 | Mode = upcase( Mode)
|
---|
2741 | CurLine = arg( 2)
|
---|
2742 | if CurLine = '' then
|
---|
2743 | CurLine = .line
|
---|
2744 | endif
|
---|
2745 | CurCol = arg( 3)
|
---|
2746 | if CurCol = '' then
|
---|
2747 | CurCol = .col
|
---|
2748 | endif
|
---|
2749 | Direction = upcase( arg( 4))
|
---|
2750 | if Direction = '' | not wordpos( Direction, '+F -R') then
|
---|
2751 | Direction = '+F'
|
---|
2752 | endif
|
---|
2753 | FoundChar = ''
|
---|
2754 | pSave_Pos( SavedPos)
|
---|
2755 | .line = CurLine
|
---|
2756 | .col = CurCol
|
---|
2757 | getsearch savesearch
|
---|
2758 | setsearch 'xcom l /[^ \t]+/x'Direction -- find the next non-blank
|
---|
2759 | do forever
|
---|
2760 | display -11 -- Enable only errors to the messageline
|
---|
2761 | repeatfind
|
---|
2762 | display 11
|
---|
2763 | if rc then
|
---|
2764 | pRestore_Pos( SavedPos)
|
---|
2765 | leave
|
---|
2766 | endif
|
---|
2767 |
|
---|
2768 | literal_rc = InsideLiteral2( Mode, LitData)
|
---|
2769 | if literal_rc then
|
---|
2770 | -- Move to start or end of literal
|
---|
2771 | parse value LitData with LitStartCol LitEndCol
|
---|
2772 | if LitStartCol & LitEndCol then
|
---|
2773 | if pos( 'R', Direction) then
|
---|
2774 | .col = LitStartCol
|
---|
2775 | else
|
---|
2776 | .col = LitEndCol
|
---|
2777 | endif
|
---|
2778 | endif
|
---|
2779 | -- Search again
|
---|
2780 | iterate
|
---|
2781 | endif
|
---|
2782 |
|
---|
2783 | comment_rc = InsideComment2( Mode, CommentData)
|
---|
2784 | -- CommentData is returned and used to position the cursor before
|
---|
2785 | -- the next search
|
---|
2786 | --dprintf( "pAssist", "next pos: ".line",".col "Char: '"substr( textline( .line), .col, 1)'"' "comment_rc: "comment_rc)
|
---|
2787 | if comment_rc = 1 then
|
---|
2788 | -- rc = 1: Inside SLC
|
---|
2789 | if Direction = '+F' then
|
---|
2790 | endline
|
---|
2791 | else
|
---|
2792 | .col = word( CommentData, 1)
|
---|
2793 | endif
|
---|
2794 | -- Search again
|
---|
2795 | iterate
|
---|
2796 | elseif comment_rc = 2 then
|
---|
2797 | -- rc = 2: Inside MLC
|
---|
2798 | parse value CommentData with MLCStartLine MLCStartCol . MLCEndLine MLCEndCol MLCEndLen
|
---|
2799 | --dprintf( "pAssist", "next comment data: "MLCEndLine MLCEndCol MLCEndLen)
|
---|
2800 | if Direction = '+F' then
|
---|
2801 | .line = MLCEndLine
|
---|
2802 | .col = MLCEndCol + MLCEndLen - 1
|
---|
2803 | else
|
---|
2804 | .line = MLCStartLine
|
---|
2805 | .col = MLCStartCol
|
---|
2806 | endif
|
---|
2807 | -- Search again
|
---|
2808 | iterate
|
---|
2809 | endif
|
---|
2810 |
|
---|
2811 | -- rc = 0: Found
|
---|
2812 | FoundChar = substr( textline( .line), .col, 1)
|
---|
2813 | leave
|
---|
2814 | enddo
|
---|
2815 | setsearch savesearch
|
---|
2816 | return FoundChar
|
---|
2817 |
|
---|
2818 | ; ---------------------------------------------------------------------------
|
---|
2819 | ; Returns the search string for a mode-specific identifier for egrep search.
|
---|
2820 | ; Syntax: GetIdentifierMask( Mode [, Option])
|
---|
2821 | ; Option = 'F' | 'N' | 'B' (first, next, both). The default option is Both.
|
---|
2822 | defproc GetIdentifierMask( Mode)
|
---|
2823 | Mode = upcase( Mode)
|
---|
2824 | Option = upcase( strip( leftstr( arg( 2), 1)))
|
---|
2825 | UsedMode = Mode
|
---|
2826 |
|
---|
2827 | if Mode = 'C' then
|
---|
2828 | FirstMask = '[a-zA-Z_\$]'
|
---|
2829 | NextMask = '[a-zA-Z0-9_\$]*'
|
---|
2830 | elseif Mode = 'REXX' then
|
---|
2831 | FirstMask = '[a-zA-Z!\?_]'
|
---|
2832 | NextMask = '[a-zA-Z0-9!\?_]*'
|
---|
2833 | elseif Mode = 'E' then
|
---|
2834 | FirstMask = '[A-Z_]'
|
---|
2835 | NextMask = '[A-Z0-9_]*'
|
---|
2836 | elseif Mode = 'TEX' then
|
---|
2837 | FirstMask = '\\'
|
---|
2838 | NextMask = '[a-zA-Z]+'
|
---|
2839 | elseif Mode = 'IPF' then
|
---|
2840 | FirstMask = '\:'
|
---|
2841 | NextMask = '[a-zA-Z0-9_]+'
|
---|
2842 | elseif Mode = 'HTEXT' then
|
---|
2843 | FirstMask = '^\.'
|
---|
2844 | NextMask = '[a-zA-Z0-9_]+'
|
---|
2845 | elseif wordpos( Mode, 'HTML, WARPIN, XML') then
|
---|
2846 | FirstMask = '\<'
|
---|
2847 | NextMask = '/?[a-zA-Z0-9_]+\>?'
|
---|
2848 | elseif Mode = 'PASCAL' then
|
---|
2849 | FirstMask = '[a-zA-Z_\$]'
|
---|
2850 | NextMask = '[a-zA-Z0-9_\$\.]*'
|
---|
2851 | elseif Mode = 'CMD' then
|
---|
2852 | FirstMask = '[A-Z_]'
|
---|
2853 | NextMask = '[A-Z0-9_]*'
|
---|
2854 | elseif Mode = 'PERL' then
|
---|
2855 | FirstMask = '[a-zA-Z_\$]'
|
---|
2856 | NextMask = "[a-zA-Z0-9_\$\']*" -- contains '
|
---|
2857 | elseif wordpos( Mode, 'ASSEMBLER JAVASCRIPT PYTHON PHP') then
|
---|
2858 | UsedMode = 'C'
|
---|
2859 | FirstMask = '[a-zA-Z_\$]'
|
---|
2860 | NextMask = '[a-zA-Z0-9_\$]*'
|
---|
2861 | else -- use C
|
---|
2862 | UsedMode = 'C'
|
---|
2863 | FirstMask = '[a-zA-Z_\$]'
|
---|
2864 | NextMask = '[a-zA-Z0-9_\$]*'
|
---|
2865 | endif
|
---|
2866 |
|
---|
2867 | if Option = '' | Option = 'B' then
|
---|
2868 | Mask = FirstMask''NextMask
|
---|
2869 | if UsedMode = 'C' then
|
---|
2870 | Mask = ':c'
|
---|
2871 | elseif UsedMode = 'REXX' then
|
---|
2872 | Mask = ':r'
|
---|
2873 | endif
|
---|
2874 | elseif Option = 'F' then
|
---|
2875 | Mask = FirstMask
|
---|
2876 | else
|
---|
2877 | -- Option = 'N'
|
---|
2878 | Mask = NextMask
|
---|
2879 | endif
|
---|
2880 | return Mask
|
---|
2881 |
|
---|
2882 | ; ---------------------------------------------------------------------------
|
---|
2883 | ; Finds the mode-specific identifier at the cursor.
|
---|
2884 | ; Syntax: FoundIdStr = CurIdentifier( Mode [, fIncludeLitCom])
|
---|
2885 | ; Returns pIdStart pIdEnd FoundId or empty.
|
---|
2886 | ; If 1 is specified for fIncludeLitCom, then literals and comments are
|
---|
2887 | ; handled like code. The default behavior is to ignore them.
|
---|
2888 | defproc CurIdentifier( Mode)
|
---|
2889 | FoundIdStr = ''
|
---|
2890 | rc = 0
|
---|
2891 | fIncludeLitCom = (arg( 2) = 1)
|
---|
2892 |
|
---|
2893 | do once = 1 to 1
|
---|
2894 | Mode = upcase( Mode)
|
---|
2895 |
|
---|
2896 | if not fIncludeLitCom then
|
---|
2897 | literal_rc = InsideLiteral2( Mode, LitData)
|
---|
2898 | if literal_rc then
|
---|
2899 | parse value LitData with LitStartCol LitEndCol
|
---|
2900 | if LitStartCol & LitEndCol then
|
---|
2901 | -- Inside a literal
|
---|
2902 | rc = -2
|
---|
2903 | leave
|
---|
2904 | endif
|
---|
2905 | endif
|
---|
2906 |
|
---|
2907 | comment_rc = InsideComment2( Mode, CommentData)
|
---|
2908 | if comment_rc = 1 then
|
---|
2909 | -- Inside a SLC
|
---|
2910 | rc = -3
|
---|
2911 | leave
|
---|
2912 | elseif comment_rc = 2 then
|
---|
2913 | -- Inside a MLC
|
---|
2914 | rc = -4
|
---|
2915 | leave
|
---|
2916 | endif
|
---|
2917 | endif
|
---|
2918 |
|
---|
2919 | fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive')
|
---|
2920 | FirstMask = GetIdentifierMask( Mode, 'F')
|
---|
2921 | NextMask = GetIdentifierMask( Mode, 'N')
|
---|
2922 | IdMask = FirstMask''NextMask
|
---|
2923 | RevIdMask = NextMask''FirstMask
|
---|
2924 | if fCaseSensitive then
|
---|
2925 | CaseIdMask = IdMask
|
---|
2926 | RevCaseIdMask = RevIdMask
|
---|
2927 | else
|
---|
2928 | CaseIdMask = upcase( IdMask)
|
---|
2929 | RevCaseIdMask = upcase( RevIdMask)
|
---|
2930 | endif
|
---|
2931 |
|
---|
2932 | getline LineStr
|
---|
2933 | if fCaseSensitive then
|
---|
2934 | CaseLineStr = LineStr
|
---|
2935 | else
|
---|
2936 | CaseLineStr = upcase( LineStr)
|
---|
2937 | endif
|
---|
2938 | RevCaseLineStr = reverse( CaseLineStr)
|
---|
2939 | LineLen = length( LineStr)
|
---|
2940 |
|
---|
2941 | -- Find pIdEnd
|
---|
2942 | pStart = .col
|
---|
2943 | next = pos( CaseIdMask, CaseLineStr, pStart, 'xm')
|
---|
2944 | parse value next with . pIdEnd .
|
---|
2945 |
|
---|
2946 | if not IsNum( pIdEnd) then
|
---|
2947 | -- Not on an id
|
---|
2948 | rc = -1
|
---|
2949 | leave
|
---|
2950 | endif
|
---|
2951 |
|
---|
2952 | -- Find pIdStart
|
---|
2953 | pRevStart = LineLen - pIdEnd + 1
|
---|
2954 | next = pos( RevCaseIdMask, RevCaseLineStr, pRevStart, 'xm')
|
---|
2955 | parse value next with pRevIdStart pRevIdEnd .
|
---|
2956 | pIdStart = LineLen - pRevIdEnd + 1
|
---|
2957 |
|
---|
2958 | if pStart < pIdStart | pStart > pIdEnd then
|
---|
2959 | -- Not on an id
|
---|
2960 | rc = -1
|
---|
2961 | leave
|
---|
2962 | endif
|
---|
2963 |
|
---|
2964 | FoundId = substr( LineStr, pIdStart, pIdEnd - pIdStart + 1)
|
---|
2965 | FoundIdStr = pIdStart pIdEnd FoundId
|
---|
2966 | enddo
|
---|
2967 | return FoundIdStr
|
---|
2968 |
|
---|
2969 | ; ---------------------------------------------------------------------------
|
---|
2970 | ; Repositions the cursor on the next non-comment and non-literal identifier.
|
---|
2971 | ; Syntax: FoundIdStr = NextIdentifier( Mode [, Line [, Col [, Direction]]])
|
---|
2972 | ; Returns pIdStart pIdEnd FoundId or empty.
|
---|
2973 | ; The default values for Line and Col are the current cursor position.
|
---|
2974 | ; Direction = '+F' | '-R'. The default direction is '+F'.
|
---|
2975 | defproc NextIdentifier( Mode)
|
---|
2976 | Mode = upcase( Mode)
|
---|
2977 | CurLine = arg( 2)
|
---|
2978 | if CurLine = '' then
|
---|
2979 | CurLine = .line
|
---|
2980 | endif
|
---|
2981 | CurCol = arg( 3)
|
---|
2982 | if CurCol = '' then
|
---|
2983 | CurCol = .col
|
---|
2984 | endif
|
---|
2985 | Direction = upcase( arg( 4))
|
---|
2986 | if Direction = '' | not wordpos( Direction, '+F -R') then
|
---|
2987 | Direction = '+F'
|
---|
2988 | endif
|
---|
2989 |
|
---|
2990 | pSave_Pos( SavedPos)
|
---|
2991 | .line = CurLine
|
---|
2992 | .col = CurCol
|
---|
2993 |
|
---|
2994 | -- Find Id at cursor and go to end or start
|
---|
2995 | next = CurIdentifier( Mode)
|
---|
2996 | if next <> '' then
|
---|
2997 | parse value next with pIdStart pIdEnd FoundId
|
---|
2998 | if pIdStart > 0 & pIdEnd >= pIdStart then
|
---|
2999 | if Direction = '+F' then
|
---|
3000 | .col = pIdEnd
|
---|
3001 | else
|
---|
3002 | .col = pIdStart
|
---|
3003 | endif
|
---|
3004 | endif
|
---|
3005 | else
|
---|
3006 | endif
|
---|
3007 |
|
---|
3008 | FirstMask = GetIdentifierMask( Mode, 'F')
|
---|
3009 | NextMask = GetIdentifierMask( Mode, 'N')
|
---|
3010 | IdMask = FirstMask''NextMask
|
---|
3011 | RevIdMask = NextMask''FirstMask
|
---|
3012 | FoundIdStr = ''
|
---|
3013 | getsearch SavedSearch
|
---|
3014 | -- Foreward (left to right): The cursor is on pStart
|
---|
3015 | -- Backward (right to left): The cursor is on pEnd
|
---|
3016 | setsearch 'xcom l '\1''IdMask''\1'ex'Direction
|
---|
3017 |
|
---|
3018 | do forever
|
---|
3019 | display -11 -- Enable only errors to the messageline
|
---|
3020 | repeatfind
|
---|
3021 | display 11
|
---|
3022 | if rc then
|
---|
3023 | pRestore_Pos( SavedPos)
|
---|
3024 | leave
|
---|
3025 | endif
|
---|
3026 |
|
---|
3027 | literal_rc = InsideLiteral2( Mode, LitData)
|
---|
3028 | if literal_rc then
|
---|
3029 | -- Move to start or end of literal
|
---|
3030 | parse value LitData with LitStartCol LitEndCol
|
---|
3031 | if LitStartCol & LitEndCol then
|
---|
3032 | if pos( 'R', Direction) then
|
---|
3033 | .col = LitStartCol
|
---|
3034 | else
|
---|
3035 | .col = LitEndCol
|
---|
3036 | endif
|
---|
3037 | endif
|
---|
3038 | -- Search again
|
---|
3039 | iterate
|
---|
3040 | endif
|
---|
3041 |
|
---|
3042 | comment_rc = InsideComment2( Mode, CommentData)
|
---|
3043 | if comment_rc = 1 then
|
---|
3044 | -- Inside a SLC
|
---|
3045 | if Direction = '+F' then
|
---|
3046 | endline
|
---|
3047 | else
|
---|
3048 | .col = word( CommentData, 1)
|
---|
3049 | endif
|
---|
3050 | -- Search again
|
---|
3051 | iterate
|
---|
3052 | elseif comment_rc = 2 then
|
---|
3053 | -- Inside a MLC
|
---|
3054 | parse value CommentData with MLCStartLine MLCStartCol . MLCEndLine MLCEndCol MLCEndLen
|
---|
3055 | if Direction = '+F' then
|
---|
3056 | -- Does CommentData always return the correct MLC pair?
|
---|
3057 | -- Go after this comment pos if after current
|
---|
3058 | tmpline = MLCEndLine
|
---|
3059 | tmpcol = MLCEndCol + MLCEndLen - 1
|
---|
3060 | if tmpline > .line | (tmpline = .line & tmpcol > .col) then
|
---|
3061 | .line = tmpline
|
---|
3062 | .col = tmpcol
|
---|
3063 | endif
|
---|
3064 | else
|
---|
3065 | -- Go before this comment pos if before current
|
---|
3066 | tmpline = MLCStartLine
|
---|
3067 | tmpcol = MLCStartCol
|
---|
3068 | if tmpline < .line | (tmpline = .line & tmpcol < .col) then
|
---|
3069 | .line = tmpline
|
---|
3070 | .col = tmpcol
|
---|
3071 | endif
|
---|
3072 | endif
|
---|
3073 | -- Search again
|
---|
3074 | iterate
|
---|
3075 | endif
|
---|
3076 |
|
---|
3077 | -- Found
|
---|
3078 | getline LineStr
|
---|
3079 | RevLineStr = reverse( LineStr)
|
---|
3080 | LineLen = length( LineStr)
|
---|
3081 | if Direction = '+F' then
|
---|
3082 | -- Foreward (left to right): The cursor is on pStart
|
---|
3083 | pStart = .col
|
---|
3084 | next = pos( IdMask, LineStr, pStart, 'xm')
|
---|
3085 | parse value next with pIdStart pIdEnd .
|
---|
3086 | else
|
---|
3087 | -- Backward (right to left): The cursor is on pEnd
|
---|
3088 | pEnd = .col
|
---|
3089 | pRevStart = LineLen - pEnd + 1
|
---|
3090 | next = pos( RevIdMask, RevLineStr, pRevStart, 'xm')
|
---|
3091 | parse value next with pRevIdStart pRevIdEnd .
|
---|
3092 | pIdStart = LineLen - pRevIdEnd + 1
|
---|
3093 | pIdEnd = LineLen - pRevIdStart + 1
|
---|
3094 | .col = Max( 1, pIdStart)
|
---|
3095 | endif
|
---|
3096 | FoundId = substr( LineStr, pIdStart, pIdEnd - pIdStart + 1)
|
---|
3097 | FoundIdStr = pIdStart pIdEnd FoundId
|
---|
3098 | leave
|
---|
3099 | enddo
|
---|
3100 |
|
---|
3101 | setsearch SavedSearch
|
---|
3102 | return FoundIdStr
|
---|
3103 |
|
---|
3104 | ; ---------------------------------------------------------------------------
|
---|
3105 | ; Dynamically set the array variable 'debuglist', which is used by
|
---|
3106 | ; the dprintf proc.
|
---|
3107 | /*
|
---|
3108 | defc t8
|
---|
3109 | -- AddAVar( 'debuglist', str)
|
---|
3110 | SetAVar( 'debuglist', arg( 1))
|
---|
3111 |
|
---|
3112 | defc t10
|
---|
3113 | list = GetAVar( 'debuglist')
|
---|
3114 | 'SayHint debuglist: 'list
|
---|
3115 |
|
---|
3116 | defc InsideComment, IC
|
---|
3117 | CurMode = GetMode()
|
---|
3118 | parse arg CurLine CurCol .
|
---|
3119 | if CurLine = '' then
|
---|
3120 | CurLine = .line
|
---|
3121 | endif
|
---|
3122 | if CurCol = '' then
|
---|
3123 | CurCol = .col
|
---|
3124 | endif
|
---|
3125 | pSave_Pos( SavedPos)
|
---|
3126 | if InsideComment( CurMode, CurLine, CurCol) then
|
---|
3127 | 'SayHint Inside a comment'
|
---|
3128 | elseif InsideLiteral( CurMode, CurLine, CurCol) then
|
---|
3129 | 'SayHint Inside a literal'
|
---|
3130 | else
|
---|
3131 | 'SayHint Not inside a comment or literal'
|
---|
3132 | endif
|
---|
3133 | pRestore_Pos( SavedPos)
|
---|
3134 |
|
---|
3135 | defc InsideLiteral, IL
|
---|
3136 | CurMode = GetMode()
|
---|
3137 | parse arg CurLine CurCol .
|
---|
3138 | if CurLine = '' then
|
---|
3139 | CurLine = .line
|
---|
3140 | endif
|
---|
3141 | if CurCol = '' then
|
---|
3142 | CurCol = .col
|
---|
3143 | endif
|
---|
3144 | pSave_Pos( SavedPos)
|
---|
3145 | if InsideLiteral( CurMode, CurLine, CurCol) then
|
---|
3146 | 'SayHint Inside a literal'
|
---|
3147 | else
|
---|
3148 | 'SayHint Not inside a literal'
|
---|
3149 | endif
|
---|
3150 | pRestore_Pos( SavedPos)
|
---|
3151 |
|
---|
3152 | defc InsideSingleLineComment, ISLC
|
---|
3153 | CurMode = GetMode()
|
---|
3154 | parse arg CurLine CurCol .
|
---|
3155 | if CurLine = '' then
|
---|
3156 | CurLine = .line
|
---|
3157 | endif
|
---|
3158 | if CurCol = '' then
|
---|
3159 | CurCol = .col
|
---|
3160 | endif
|
---|
3161 | pSave_Pos( SavedPos)
|
---|
3162 | if InsideSLC( CurMode, CurLine, CurCol) then
|
---|
3163 | 'SayHint Inside a single-line comment'
|
---|
3164 | else
|
---|
3165 | 'SayHint Not inside a single-line comment'
|
---|
3166 | endif
|
---|
3167 | pRestore_Pos( SavedPos)
|
---|
3168 |
|
---|
3169 | defc InsideMultiLineComment, IMLC
|
---|
3170 | CurMode = GetMode()
|
---|
3171 | parse arg CurLine CurCol .
|
---|
3172 | if CurLine = '' then
|
---|
3173 | CurLine = .line
|
---|
3174 | endif
|
---|
3175 | if CurCol = '' then
|
---|
3176 | CurCol = .col
|
---|
3177 | endif
|
---|
3178 | pSave_Pos( SavedPos)
|
---|
3179 | if InsideMLC( CurMode, CurLine, CurCol) then
|
---|
3180 | 'SayHint Inside a multi-line comment'
|
---|
3181 | else
|
---|
3182 | 'SayHint Not inside a multi-line comment'
|
---|
3183 | endif
|
---|
3184 | pRestore_Pos( SavedPos)
|
---|
3185 |
|
---|
3186 | defc PrevCodeChar, PCC
|
---|
3187 | CurMode = GetMode()
|
---|
3188 | parse arg CurLine CurCol .
|
---|
3189 | if CurLine = '' then
|
---|
3190 | CurLine = .line
|
---|
3191 | endif
|
---|
3192 | if CurCol = '' then
|
---|
3193 | CurCol = .col
|
---|
3194 | endif
|
---|
3195 | Direction = '-R'
|
---|
3196 | FoundChar = NextCodeChar( CurMode, CurLine, CurCol, Direction)
|
---|
3197 | dprintf( 'PrevCodeChar: FoundChar = 'FoundChar)
|
---|
3198 |
|
---|
3199 | defc NextCodeChar, NCC
|
---|
3200 | CurMode = GetMode()
|
---|
3201 | parse arg CurLine CurCol .
|
---|
3202 | if CurLine = '' then
|
---|
3203 | CurLine = .line
|
---|
3204 | endif
|
---|
3205 | if CurCol = '' then
|
---|
3206 | CurCol = .col
|
---|
3207 | endif
|
---|
3208 | Direction = '+F'
|
---|
3209 | FoundChar = NextCodeChar( CurMode, CurLine, CurCol, Direction)
|
---|
3210 | dprintf( 'NextCodeChar: FoundChar = 'FoundChar)
|
---|
3211 |
|
---|
3212 | defc CurIdentifier, CID
|
---|
3213 | CurMode = GetMode()
|
---|
3214 | dprintf( 'CurIdentifier: FoundIdStr = 'CurIdentifier( CurMode))
|
---|
3215 |
|
---|
3216 | defc PrevIdentifier, PID
|
---|
3217 | CurMode = GetMode()
|
---|
3218 | parse arg CurLine CurCol .
|
---|
3219 | if CurLine = '' then
|
---|
3220 | CurLine = .line
|
---|
3221 | endif
|
---|
3222 | if CurCol = '' then
|
---|
3223 | CurCol = .col
|
---|
3224 | endif
|
---|
3225 | Direction = '-R'
|
---|
3226 | FoundIdStr = NextIdentifier( CurMode, CurLine, CurCol, Direction)
|
---|
3227 | dprintf( 'PrevIdentifier: FoundIdStr = 'FoundIdStr)
|
---|
3228 |
|
---|
3229 | defc NextIdentifier, NID
|
---|
3230 | CurMode = GetMode()
|
---|
3231 | parse arg CurLine CurCol .
|
---|
3232 | if CurLine = '' then
|
---|
3233 | CurLine = .line
|
---|
3234 | endif
|
---|
3235 | if CurCol = '' then
|
---|
3236 | CurCol = .col
|
---|
3237 | endif
|
---|
3238 | Direction = '+F'
|
---|
3239 | FoundIdStr = NextIdentifier( CurMode, CurLine, CurCol, Direction)
|
---|
3240 | dprintf( 'NextIdentifier: FoundIdStr = 'FoundIdStr)
|
---|
3241 | */
|
---|
3242 |
|
---|