|
| 1 | +""" |
| 2 | + Script: GotoLineCol.py |
| 3 | + Utility: 1. Moves the cursor position to the specified line and column for a file in Notepad++. |
| 4 | + Especially useful for inspecting data files in fixed-width record formats. |
| 5 | + 2. Also, displays the character code (SBCS & LTR) in decimal and hex at the specified position. |
| 6 | + Requires: Python Script plugin in Notepad++ |
| 7 | +
|
| 8 | + Customizable parameters for the goToLineCol function call in main(): |
| 9 | + bRepeatPrompt: Whether to repeat prompting when the specified number value is out of range |
| 10 | + iEdgeBuffer: Ensures that the caret will be that many characters inside the left and right edges of the editor viewing area, when possible |
| 11 | + iCaretHiliteDuration: Caret will be in Block mode for specified seconds |
| 12 | + bCallTipAutoHide: Whether to hide the call tip automatically in sync when caret highlighting is turned off |
| 13 | + bBraceHilite: Whether to use brace highlighting style for the character at the specified position. Automatically turns off when current line changes. |
| 14 | +
|
| 15 | +Known Issues: 1. Character code display in the call tip is functional with SBCS (Single-Byte Character Sets) and LTR (left-to-right) direction. |
| 16 | + With MBCS (Bulti-Bytes Character Sets) or RTL (right-to-left) direction, results will not be reliable. |
| 17 | + 2. If iCaretHiliteDuration is set to a high value (>3 seconds), and the user tries to rerun the script |
| 18 | + while the previous execution is still running, the Python Script plugin will display an error message: |
| 19 | + "Another script is still running..." So set this parameter to 3 seconds or lower. |
| 20 | +
|
| 21 | + Author: Shridhar Kumar |
| 22 | + Date: 2019-08-15 |
| 23 | +""" |
| 24 | + |
| 25 | +def main(): |
| 26 | + goToLineCol(bRepeatPrompt = True, |
| 27 | + iEdgeBuffer = 5, |
| 28 | + iCaretHiliteDuration = 5, |
| 29 | + bCallTipAutoHide = False, |
| 30 | + bBraceHilite = True) |
| 31 | + |
| 32 | + |
| 33 | +def getDisplayLineCol(): |
| 34 | + iCurrLine = editor.lineFromPosition(editor.getCurrentPos()) |
| 35 | + iCurrCol = editor.getCurrentPos() - editor.positionFromLine(iCurrLine) |
| 36 | + return str(iCurrLine + 1), str(iCurrCol + 1) |
| 37 | + |
| 38 | +def promptValue(sInfoText, sTitleText, sDefaultVal, iMinVal, iMaxVal, sRangeError, bRepeatPrompt): |
| 39 | + while True: |
| 40 | + sNewVal = notepad.prompt(sInfoText, sTitleText, sDefaultVal) |
| 41 | + if sNewVal == None: |
| 42 | + return None |
| 43 | + |
| 44 | + try: |
| 45 | + iNewVal = int(sNewVal) |
| 46 | + if iMinVal <= iNewVal <= iMaxVal: |
| 47 | + return iNewVal |
| 48 | + else: |
| 49 | + raise |
| 50 | + except: |
| 51 | + notepad.messageBox(sRangeError + '.\n\nYou specified: ' + sNewVal + |
| 52 | + '\n\nPlease specify a number between ' + str(iMinVal) + ' and ' + str(iMaxVal) + '.', |
| 53 | + 'Specified value is out of range') |
| 54 | + if not bRepeatPrompt: |
| 55 | + return None |
| 56 | + |
| 57 | + |
| 58 | +def goToLineCol(bRepeatPrompt, iEdgeBuffer, iCaretHiliteDuration, bCallTipAutoHide, bBraceHilite): |
| 59 | + import time |
| 60 | + |
| 61 | + sCurrLine, sCurrCol = getDisplayLineCol() |
| 62 | + iMaxLines = editor.getLineCount() |
| 63 | + |
| 64 | + iNewLine = promptValue(sInfoText = 'Line number (between 1 and ' + str(iMaxLines) + '):', |
| 65 | + sTitleText = 'Specify line number', |
| 66 | + sDefaultVal = sCurrLine, |
| 67 | + iMinVal = 1, |
| 68 | + iMaxVal = iMaxLines, |
| 69 | + sRangeError = 'File line count is only ' + str(iMaxLines), |
| 70 | + bRepeatPrompt = bRepeatPrompt) |
| 71 | + if iNewLine == None: |
| 72 | + return |
| 73 | + |
| 74 | + # Get the character count plus 1 for the specified line |
| 75 | + # Plus 1 is to account for the caret position at the end of the line, past all characters but before EOL/EOF |
| 76 | + # Since lineLength already includes EOL, we just need to subtract 1 only when EOL is 2 chars. i.e., CRLF |
| 77 | + # For the last line in file, there is no 2-character CRLF EOL; only a single character EOF. |
| 78 | + iMaxCols = max(1, editor.lineLength(iNewLine - 1)) |
| 79 | + if (editor.getEOLMode() == ENDOFLINE.CRLF) and (iNewLine < iMaxLines): |
| 80 | + iMaxCols -= 1 |
| 81 | + |
| 82 | + iNewCol = promptValue(sInfoText = 'Column position (between 1 and ' + str(iMaxCols) + ') for line ' + str(iNewLine) + ':', |
| 83 | + sTitleText = 'Specify column position', |
| 84 | + sDefaultVal = sCurrCol, |
| 85 | + iMinVal = 1, |
| 86 | + iMaxVal = iMaxCols, |
| 87 | + sRangeError = 'There are only ' + str(iMaxCols) + ' characters in line ' + str(iNewLine), |
| 88 | + bRepeatPrompt = bRepeatPrompt) |
| 89 | + |
| 90 | + # Navigate to the specified position in the document |
| 91 | + iLineStartPos = editor.positionFromLine(iNewLine - 1) |
| 92 | + iNewPos = iLineStartPos + iNewCol - 1 |
| 93 | + editor.ensureVisible(iNewLine - 1) |
| 94 | + editor.gotoPos( min(iLineStartPos + iMaxCols, iNewPos + iEdgeBuffer) ) # Ensure that caret is 'iEdgeBuffer' characters inside right edge when possible |
| 95 | + editor.gotoPos( max(iLineStartPos, iNewPos - iEdgeBuffer) ) # Ensure that caret is 'iEdgeBuffer' characters inside left edge when possible |
| 96 | + editor.gotoPos(iNewPos) # Finally, move caret to the specified position |
| 97 | + |
| 98 | + # Obtain current caret style to restore it later on |
| 99 | + currCS = editor.getCaretStyle() |
| 100 | + |
| 101 | + # Set the caret to block style to highlight the new position |
| 102 | + editor.setCaretStyle(CARETSTYLE.BLOCK) |
| 103 | + |
| 104 | + # Display a call tip with the new line and column numbers with verification |
| 105 | + # Also display the character code in decimal and hex |
| 106 | + sCurrLine, sCurrCol = getDisplayLineCol() |
| 107 | + editor.callTipShow(iNewPos, ' Line: ' + sCurrLine + |
| 108 | + '\n Column: ' + sCurrCol + |
| 109 | + '\nChar Code: ' + str(editor.getCharAt(iNewPos)) + ' [' + hex(editor.getCharAt(iNewPos)) + ']') |
| 110 | + |
| 111 | + if iCaretHiliteDuration > 0: |
| 112 | + time.sleep(iCaretHiliteDuration) |
| 113 | + |
| 114 | + # Reset the caret style |
| 115 | + editor.setCaretStyle(currCS) |
| 116 | + |
| 117 | + if bCallTipAutoHide: |
| 118 | + editor.callTipCancel() |
| 119 | + |
| 120 | + if bBraceHilite: |
| 121 | + editor.braceHighlight(iNewPos, iNewPos) |
| 122 | + |
| 123 | + |
| 124 | +main() |
0 commit comments