Can clickable links contain line numbers?
-
I have log files that have clickable links in them like:
____________________________________________ (2)file:///C:/Scot/config/BaseTBAutomationPosMgr.xml#3686
I can click this link and it opens the file in Notepad++ like I intended. However, it doesn’t go to line 3686. Is there any way I can make this link or another format link open the file in Notepad++ and go to that line?
-
I don’t think it is possible using native npp functions.
What I can think of is using a scripting language like python script or lua script
and using the hotspotclick notification send by scintilla.
We would receive the location/position of this click event and could get the text
from that line. If your format is always the same I assume we could prepare such a script.
Let us know if you wanna go this way.Cheers
Claudia -
Python would be great! I already have it installed. I have never used these kinds of scripts with NPP so that would be a great learning experience for me.
-
because the latest python script version tends to fail if installed by plugin manager
just double check if it has correctly installed on your side. Plugins->PythonScript->Show Console should report something likePython 2.7.6-notepad++ r2 (default, Apr 21 2014, 19:26:54) [MSC v.1600 32 bit (Intel)] Initialisation took 145ms Ready.
If this doesn’t appear or you get an error download the MSI package and reinstall it.
Once done, create a new script by Plugin->PythonScript-New Script
name the file startup.py and paste the following content into it.import os file_identifier = 'file:///' position_seperator = '#' file_to_load = None line_in_file = 0 def callbackBUFFERACTIVATED(args): global file_to_load if file_to_load is not None: current_file = notepad.getBufferFilename(args['bufferID']) if file_to_load.lower() == os.path.normpath(current_file).lower(): editor.gotoLine(int(line_in_file)) editor.verticalCentreCaret() file_to_load = None def callbackHOTSPOTCLICK(args): line_of_link = editor.lineFromPosition(args['position']) link_text = editor.getLine(line_of_link) if file_identifier in link_text and position_seperator in link_text: global file_to_load global line_in_file file_to_load, line_in_file = link_text.split(position_seperator) file_to_load = file_to_load.replace(file_identifier, '') file_to_load = os.path.normpath(file_to_load) notepad.open(file_to_load) editor.callback(callbackHOTSPOTCLICK, [SCINTILLANOTIFICATION.HOTSPOTCLICK]) notepad.callback(callbackBUFFERACTIVATED, [NOTIFICATION.BUFFERACTIVATED])
Take care about indention, python is strict about it (don’t know if you familar with python language).
One additional step -> Plugins->PythonScript->Configuration
change Initialisation from LAZY to ATSTARTUP.Done - every time you start npp this script gets executed automatically.
What does the script?
It registers a callback for hotspotclick and bufferactivated notification. Once you click
on a link the callback gets executed and tries to get the text from the link.
If it starts with file:/// and has # in the line it is supposed to be a file link and gets
the details, file_to_load and line_in_file. Then it asks notepad to open that file.
If this is successful, npp sends a notification (bufferactivated) once the buffer has been loaded. Now the second part starts - it gets checked if this is the file we want
and if so we goto the line in question.
Currently I have no windows environment to test but under Linux(wine)
I do have a strange behavior. When the goto line is called some text before that
line gets selected. I hope this isn’t an issue under windows.Cheers
Claudia -
ok, found the culprit, we need to use HOTSPOTRELEASECLICK instead HOTSPOTCLICK. The following should work.
import os file_identifier = 'file:///' position_seperator = '#' file_to_load = None line_in_file = 0 def callbackBUFFERACTIVATED(args): global file_to_load if file_to_load is not None: current_file = notepad.getBufferFilename(args['bufferID']) if file_to_load.lower() == os.path.normpath(current_file).lower(): editor.gotoLine(int(line_in_file)) editor.verticalCentreCaret() file_to_load = None def callbackHOTSPOTRELEASECLICK(args): line_of_link = editor.lineFromPosition(args['position']) link_text = editor.getLine(line_of_link) if file_identifier in link_text and position_seperator in link_text: global file_to_load global line_in_file file_to_load, line_in_file = link_text.split(position_seperator) file_to_load = file_to_load.replace(file_identifier, '') file_to_load = os.path.normpath(file_to_load) notepad.open(file_to_load) editor.callback(callbackHOTSPOTRELEASECLICK, [SCINTILLANOTIFICATION.HOTSPOTRELEASECLICK]) notepad.callback(callbackBUFFERACTIVATED, [NOTIFICATION.BUFFERACTIVATED])
Cheers
Claudia -
and if your program starts counting lines from 1 instead of 0 you need to
change the lineeditor.gotoLine(int(line_in_file))
to
editor.gotoLine(int(line_in_file)-1)
So, hopefully this was the last update today ;-)
Cheers
Claudia -
ok, one last change before going to bed.
Maybe there is text before and after the link, in such a case
it would break the logic. Here a solution which gets the link text only.
Replace callbackHOTSPOT… with this onedef callbackHOTSPOTRELEASECLICK(args): __pos = args['position'] __style_id = editor.getStyleAt(__pos) __word_start = None __word_end = None _p = __pos while True: __word_start = _p if editor.getStyleAt(_p) != __style_id: break _p -= 1 _p = __pos while True: if editor.getStyleAt(_p) != __style_id: __word_end = _p break _p += 1 link_text = editor.getTextRange(__word_start, __word_end+1) if file_identifier in link_text and position_seperator in link_text: global file_to_load global line_in_file file_to_load, line_in_file = link_text[link_text.find(file_identifier):].split(position_seperator) file_to_load = file_to_load.replace(file_identifier, '') file_to_load = os.path.normpath(file_to_load) notepad.open(file_to_load)
Good Night.
Cheers
Claudia -
Thank you! The last works perfect.