From 517f512c76b7147f96f8e49cb6dd311156dca0dc Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Fri, 26 Feb 2016 22:01:03 -0300 Subject: [PATCH] Add "Go to..." to contextual menu, for SUB/FUNCTION/Labels. If a user right-clicks a SUB/FUNCTION name or a label name anywhere in the code, the contextual menu now offers to jump to the line where such procedure/label is defined, providing a quick way to navigate through code. Even if there are multiple identical labels in different procedures, scope is taken into consideration, leading you to the definition that's located inside the current procedure. --- source/ide/ide_global.bas | 1 + source/ide/ide_methods.bas | 192 ++++++++++++++++++++++++++++++++++++- source/qb64.bas | 3 +- 3 files changed, 192 insertions(+), 4 deletions(-) diff --git a/source/ide/ide_global.bas b/source/ide/ide_global.bas index 15781ea94..65221d7bb 100644 --- a/source/ide/ide_global.bas +++ b/source/ide/ide_global.bas @@ -152,6 +152,7 @@ DIM SHARED idechangeto AS STRING DIM SHARED idechangemade AS INTEGER DIM SHARED ideinsert AS INTEGER DIM SHARED idepathsep AS STRING * 1 +DIM SHARED SubFuncLIST(0) AS STRING '-------------------------------------------------------------------------------- TYPE idedbptype diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index 1cca4d382..3b9042c05 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -3803,6 +3803,26 @@ DO GOTO contextualhelp END IF + IF left$(menu$(m, s), 10) = "#Go to SUB" OR left$(menu$(m, s), 15) = "#Go to FUNCTION" THEN 'Contextual menu Goto + PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt + idecy = CVL(MID$(SubFuncLIST(1), 1, 4)) + idesy = idecy + idecx = 1 + idesx = 1 + ideselect = 0 + GOTO ideloop + END IF + + IF left$(menu$(m, s), 12) = "#Go to label" THEN 'Contextual menu Goto label + PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt + idecy = CVL(MID$(SubFuncLIST(ubound(SubFuncLIST)), 1, 4)) + idesy = idecy + idecx = 1 + idesx = 1 + ideselect = 0 + GOTO ideloop + END IF + IF menu$(m, s) = "#Contents page" THEN PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt lnk$ = "QB64 Help Menu" @@ -10670,6 +10690,9 @@ menusize(m) = i - 1 END SUB SUB IdeMakeContextualMenu + REDIM SubFuncLIST(0) AS STRING + DIM Selection$ + m = idecontextualmenuID: i = 0 menu$(m, i) = "Contextual": i = i + 1 @@ -10691,12 +10714,65 @@ SUB IdeMakeContextualMenu a2$ = LEFT$(a2$, 19) + string$(3, 250) END IF menu$(m, i) = "Find '" + a2$ + "'": i = i + 1 + Selection$ = a2$ END IF END IF - 'identify if word or character at current cursor position is in the help system -- copied from ide2 + 'build SUB/FUNCTION list: + TotalSF = 0 + FOR y = 1 TO iden + a$ = idegetline(y) + a$ = LTRIM$(RTRIM$(a$)) + sf = 0 + nca$ = UCASE$(a$) + IF LEFT$(nca$, 4) = "SUB " THEN sf = 1: sf$ = "SUB " + IF LEFT$(nca$, 9) = "FUNCTION " THEN sf = 2: sf$ = "FUNC " + IF sf THEN + IF RIGHT$(nca$, 7) = " STATIC" THEN + a$ = RTRIM$(LEFT$(a$, LEN(a$) - 7)) + END IF + + IF sf = 1 THEN + a$ = RIGHT$(a$, LEN(a$) - 4) + ELSE + a$ = RIGHT$(a$, LEN(a$) - 9) + END IF + + a$ = LTRIM$(RTRIM$(a$)) + x = INSTR(a$, "(") + IF x THEN + n$ = RTRIM$(LEFT$(a$, x - 1)) + ELSE + n$ = a$ + END IF + + 'attempt to cleanse n$, just in case there are any comments or other unwanted stuff + for CleanseN = 1 to len(n$) + select case mid$(n$, CleanseN, 1) + case " ", "'", ":" + n$ = left$(n$, CleanseN - 1) + exit for + end select + next + + n2$ = n$ + if len(n2$) > 1 then + do until alphanumeric(asc(right$(n2$, 1))) + n2$ = left$(n$, len(n2$) - 1) 'removes sigil, if any + loop + end if + + 'Populate SubFuncLIST() + TotalSF = TotalSF + 1 + REDIM _PRESERVE SubFuncLIST(1 to TotalSF) AS STRING + SubFuncLIST(TotalSF) = MKL$(y) + CHR$(sf) + n2$ + END IF + NEXT + + 'identify if word or character at current cursor position is in the help system OR a sub/func + '(copied/adapted from ide2) a$ = idegetline(idecy) + a2$ = "" x = idecx - HelpOnSelection = 0 IF x <= LEN(a$) THEN IF alphanumeric(ASC(a$, x)) THEN x1 = x @@ -10712,6 +10788,68 @@ SUB IdeMakeContextualMenu a2$ = CHR$(ASC(a$, x)) END IF a2$ = UCASE$(a2$) + END IF + + 'check if cursor is on sub/func/label name + if len(Selection$) > 0 then + do until alphanumeric(asc(right$(Selection$, 1))) + Selection$ = left$(Selection$, len(Selection$) - 1) 'removes sigil, if any + loop + Selection$ = ltrim$(rtrim$(Selection$)) + end if + + if right$(a2$, 1) = "$" then a3$ = left$(a2$, len(a2$) - 1) else a3$ = a2$ 'creates a new version without $ + + if len(a3$) > 0 or len(Selection$) > 0 THEN + + for CheckSF = 1 to TotalSF + if a3$ = ucase$(mid$(SubFuncLIST(CheckSF), 6)) or ucase$(Selection$) = ucase$(mid$(SubFuncLIST(CheckSF),6)) then + CurrSF$ = FindCurrentSF$(idecy) + if len(CurrSF$) = 0 then goto SkipCheckCurrSF + + do until alphanumeric(asc(right$(CurrSF$, 1))) + CurrSF$ = left$(CurrSF$, len(CurrSF$) - 1) 'removes sigil, if any + loop + CurrSF$ = ucase$(CurrSF$) + + SkipCheckCurrSF: + if asc(SubFuncLIST(CheckSF), 5) = 1 THEN + CursorSF$ = "SUB " + else + CursorSF$ = "FUNCTION " + end if + CursorSF$ = CursorSF$ + mid$(SubFuncLIST(CheckSF),6) + + if ucase$(CursorSF$) = CurrSF$ THEN + exit for + else + menu$(m, i) = "#Go to " + CursorSF$: i = i + 1 + SubFuncLIST(1) = SubFuncLIST(CheckSF) + exit for + end if + end if + next CheckSF + + v = 0 + CurrSF$ = FindCurrentSF$(idecy) + if not Error_Happened then v = HashFind(a2$, HASHFLAG_LABEL, ignore, r) + CheckThisLabel: + if v then + LabelLineNumber = Labels(r).SourceLineNumber + ThisLabelScope$ = FindCurrentSF$(LabelLineNumber) + if ThisLabelScope$ <> CurrSF$ AND v = 2 then + v = HashFindCont(ignore, r) + goto CheckThisLabel + end if + if LabelLineNumber > 0 and LabelLineNumber <> idecy then + menu$(m, i) = "#Go to label " + rtrim$(Labels(r).cn): i = i + 1 + REDIM _PRESERVE SubFuncLIST(1 to ubound(SubFuncLIST) + 1) AS STRING + SubFuncLIST(ubound(SubFuncLIST)) = MKL$(Labels(r).SourceLineNumber) + end if + end if + end if + + if len(a2$) > 0 then 'check if F1 is in help links fh = FREEFILE OPEN "internal\help\links.bin" FOR INPUT AS #fh @@ -10736,7 +10874,7 @@ SUB IdeMakeContextualMenu menu$(m, i) = "#Help on '" + l2$ + "'": i = i + 1 end if END IF - END IF + end if IF i > 1 THEN menu$(m, i) = "-": i = i + 1 @@ -11670,4 +11808,52 @@ SELECT CASE DataType END SELECT END SUB +FUNCTION FindCurrentSF$(whichline) + 'Get the name of the SUB/FUNCTION whichline is in. + + sfname$ = "" + IF whichline > 0 THEN + FOR currSF_CHECK = whichline TO 1 STEP -1 + thisline$ = idegetline(currSF_CHECK) + thisline$ = ltrim$(RTRIM$(thisline$)) + isSF = 0 + ncthisline$ = UCASE$(thisline$) + IF LEFT$(ncthisline$, 4) = "SUB " THEN isSF = 1 + IF LEFT$(ncthisline$, 9) = "FUNCTION " THEN isSF = 2 + IF isSF > 0 THEN + IF RIGHT$(ncthisline$, 7) = " STATIC" THEN + thisline$ = RTRIM$(LEFT$(thisline$, LEN(thisline$) - 7)) + END IF + + thisline$ = RTRIM$(LTRIM$(thisline$)) + checkargs = INSTR(thisline$, "(") + IF checkargs > 0 THEN + sfname$ = RTRIM$(LEFT$(thisline$, checkargs - 1)) + ELSE + sfname$ = thisline$ + END IF + + 'It could be that SUB or FUNCTION is inside a DECLARE LIBRARY. + 'In such case, it must be ignored: + InsideDECLARE = 0 + FOR declib_CHECK = currSF_CHECK TO 1 STEP -1 + thisline$ = idegetline(declib_CHECK) + thisline$ = rtrim$(lTRIM$(thisline$)) + ncthisline$ = UCASE$(thisline$) + IF LEFT$(ncthisline$, 8) = "DECLARE " AND INSTR(ncthisline$, " LIBRARY") > 0 THEN InsideDECLARE = -1: EXIT FOR + IF LEFT$(ncthisline$, 11) = "END DECLARE" THEN EXIT FOR + NEXT + + IF InsideDECLARE = -1 THEN + sfname$ = "" + END IF + EXIT FOR + END IF + NEXT + END IF + + FindCurrentSF$ = sfname$ +END FUNCTION + + '$INCLUDE:'wiki\wiki_methods.bas' diff --git a/source/qb64.bas b/source/qb64.bas index a8b56a0e9..38ffed66b 100644 --- a/source/qb64.bas +++ b/source/qb64.bas @@ -407,6 +407,7 @@ TYPE Label_Type Data_Referenced AS _UNSIGNED _BYTE 'set to 1 if data is referenced (data_offset will be used to create the data offset variable) Error_Line AS LONG 'the line number to reference on errors Scope_Restriction AS LONG 'cannot exist inside this scope (post checked) + SourceLineNumber AS LONG END TYPE DIM SHARED nLabels, Labels_Ubound Labels_Ubound = 100 @@ -3191,7 +3192,7 @@ DO addlabaq: Labels(r).State = 1 Labels(r).Data_Offset = linedataoffset - + Labels(r).SourceLineNumber = linenumber IF LEN(layout$) THEN layout$ = layout$ + sp + tlayout$ + ":" ELSE layout$ = tlayout$ + ":"