## Passing line number to external viewer

Moderators: fgagnon, nikos, Site Mods

jporubek
Member
Posts: 10
Joined: 2010 Jan 05, 19:07

### Passing line number to external viewer

I am using Editor2 as a quick viewer of code routines in a program source file. The "/L:nn" options allows me to jump directly to the relevant line (which I've pre-determined and saved in a Freemind branch that calls Editor2), which is very handy. I currently have Vim set up as the external viewer, so I can use its power and features if I decide to edit the file by pressing <F12> in Editor2. The only thing that's missing is being able to pass the line number to Vim. Is there a way to do this that I'm missing? If not, consider this a feature request!

nikos
Posts: 14335
Joined: 2002 Feb 07, 15:57
Location: UK
Contact:

### Re: Passing line number to external viewer

you can pass command line arguments to the external viewer (I think) but you couldn't add something variable as the line number

Platinum Member
Posts: 4569
Joined: 2008 Sep 30, 06:52
Location: Dublin

### Re: Passing line number to external viewer

nikos wrote:...but you couldn't add something variable as the line number
Always some excuse with you, isn't it?

The trick here is to use scripting - instead of configuring Ed2 to call Vim directly, you want Ed2 to call your script as an external intermediary instead, and let that spawn Vim directly. The reason for this is that the script will retrieve the current line number (since Ed2 doesn't want to give it to us, we will prise it away from its cold dead fingers the hard way) and then pass that using Vim's own "+" command-line parameter.

The script essentially looks like this:

Code: Select all

#include <SendMessage.au3>

Global Const $EM_LINEFROMCHAR = 0xC9 Global$hWin = WinActivate("[CLASS:ATL:000000000042D430]")
Global $hCtrl = ControlGetHandle($hWin, "", "[CLASS:RichEdit20W; INSTANCE:1]")

Global $LineNumber = _SendMessage($hCtrl, $EM_LINEFROMCHAR, -1) Run(Chr(34) & "C:\Program Files (x86)\Vim\vim74\gvim.exe" & Chr(34) & _ " " & Chr(34) &$CmdLine[1] & Chr(34) & " +" & \$LineNumber)
The line number is derived from a normal EM_LINEFROMCHAR API message to the edit control itself.

Obviously, the Run() command calls Vim (I can't really give you a pre-compiled script for this, as only you know where your Vim binary exists), passing the script's own first command-line element (received automatically from Ed2 itself) which is the text-file's name, then appending the "+nnn" line number target as the second argument. Simple.

The basic idea is that you compile the above script (it's in AutoIt, but the same could be easily written in any language) into EXE form, then supply that EXE name as the "External Editor" setting within Ed2.

Et voilà, you press <F12> as usual and you get Vim opened to the same line number as Ed2.

There is one caveat with this - the concept of long-line text wrapping can skew the results, as depending on the relative window/font-sizes of Ed2 vs. Vim, the line numbers themselves may not correlate as you expect. This only happens when a document is made up of whole paragraphs as single-lines - if you're perusing source-code or anything like that which has a more structured line-by-line approach, everything will work fine.

If you're bored, you can also configure the script to automatically kill the Ed2 process as part of the hand-off, so it doesn't remain open, etc, etc, etc.

If you aren't into compiling scripts yourself, I'll be happy to supply one for you - all I need to know is the full location of your Vim binary and whatever other command-line arguments you may use. To tell you the truth I installed Vim just to test this script out (and it works fine), but I can't make head nor tails of Vim's attitude - it doesn't seem to like to save its own settings or anything friendly like that - but hey, to each his own.

jporubek
Member
Posts: 10
Joined: 2010 Jan 05, 19:07

### Re: Passing line number to external viewer

I skinned the cat another way (poor cat!). I created three batch files to give me the desired results. The first one, which I named ed2.bat, is called like this: ed2.bat filename line#. (Actually I have to create a separate batch file for each code routine with the filename and line number hard-coded in it for Freemind, because it doesn't allow parameters to be passed in a node, but that's a different topic.) Here are the contents of ed2.bat:

Code: Select all

@echo off
set line=%2
"<full path to>\editor2_64.exe" /V /L:%line% %1
set line=
Here I created an environment variable called "line" and set it equal to the passed-in line number parameter. Then I call Editor2 with the line number and filename in viewer mode. In Editor2, I set the external viewer to point to another batch file which I call to_gvim-inter.bat. Here are its contents:

Code: Select all

@echo off
start /min <full path to>\to_gvim.bat %1 %line% ^& exit
The "-inter" in the name is to denote that this is an intermediary step, necessary so that the created cmd window is minimized (doesn't show up). It calls to_gvim.bat, which is where Vim (gvim) is finally called. Here is to_gvim.bat:

Code: Select all

@echo off
"<full path to>\gvim.exe" %1 +%line%
The "^& exit" in to_gvim.bat is so that the created minimized cmd window doesn't hang around after we're done. The "set line=" at the end of ed2.bat removes the no-longer-needed line number variable after Editor2 is closed.

This may seem quite convoluted, but it works and I'm pleased with the result. Now I just have one other complaint: when Editor2 gets opened using the /L: flag, the desired line is somewhere near the end of the window. It would be nice if it were opened as the top line or in the middle (Vim opens it in the middle). However, I have found that I can move the line to the top by pressing Alt+PageUp (not sure if this is documented), so it's not too big an inconvenience.

Platinum Member
Posts: 4569
Joined: 2008 Sep 30, 06:52
Location: Dublin

### Re: Passing line number to external viewer

jporubek wrote:This may seem quite convoluted, but it works...
Now there's an understatement! I actually assumed you wanted the current line number (not necessarily the original one) sent to vim, which is why I took the approach I did.

For example, if you happened to browse to another line of the same document within ed2 (the original being scrolled away) before invoking Vim, you'd have Vim open immediately to what you were actually looking at, not the original line. It could be argued as desirable either way, depending on the user, I guess.

For anyone viewing who may express a fondness for the idea of this thread, but finds jporubek's solution takes perhaps too much skin off their cat, I created a simpler more flexible script which may be used with any editor which allows a command-line line-number reference (be that Vim or whatever).

Just download Ed2Conceder and extract the EXE to a location of your choice. Then, in the Ed2 options, set the external editor as follows:

"<pathto>\Ed2Conceder.EXE" "<pathto>\MyEditor.EXE" "<line-designator>" "Close"

The <line-designator> argument is a string literal for whatever your editor uses to open to a specific line. In Vim this is the "+" symbol, while in Notepad++ it is "-n". Remember, this is not the line-number itself - that's generated automatically, this is just the prefix to it.

The last argument (the word "Close") is optional. If you add it, the Ed2 window will be closed and then the external editor is called. If you leave that argument off, the Ed2 window remains in the background while the new editor is opened over it.

In other words, for Vim, you might use:

"Ed2Conceder.exe" "gvim.exe" "+" "Close"

Or, for Notepad++, you could use:

This way when you hit <F12> in Ed2, it just invokes the editor of your choice to whatever line# the cursor-caret is currently on. In the above examples, Vim would be opened and x2 closed, but Notepad++ and Ed2 would both be open.

Remember that you do require the double-quotes (") around both the EXE's if you happen to have any spaces in their full pathnames.

Anyway, that's it, all wrapped up in a single flexible package without console windows, muss, or fuss. And (more importantly) it's feline-friendly!

jporubek
Member
Posts: 10
Joined: 2010 Jan 05, 19:07

### Re: Passing line number to external viewer

Kilmatead wrote:I actually assumed you wanted the current line number (not necessarily the original one) sent to vim, which is why I took the approach I did.

For example, if you happened to browse to another line of the same document within ed2 (the original being scrolled away) before invoking Vim, you'd have Vim open immediately to what you were actually looking at, not the original line. It could be argued as desirable either way, depending on the user, I guess.
My use case was to view or edit a specific code routine, hence the preservation of the line number.

However, your solution is more general and easier to use and I'm not so pig-headed as to ignore a better approach, especially when it requires next to no effort on my part! I see that Ed2Conceder is basically an extension and repackaging (into an executable) of your original script. I have to say that you've really got me interested in AutoIt and I've added it to my already long list of things to investigate someday.

So I downloaded Ed2Conceder.rar and extracted it to my chosen location. I changed the external viewer option in Ed2 and voila!... It didn't work. Gvim opens, but at the top of the file, not the line number I was on in Ed2. I tried adding "Close", but Gvim again opened at the top and Ed2 did not close. I tried the "+" with and without quotes - no difference. Everything in Ed2Conceder.au3 makes sense to me except the test for the "Close" argument (BTW, I take it that it's case-sensitive?) and its application in the constructed command line. I'd like to get this working, so whatever I can do to help you debug it, let me know.

FrizzleFry
Platinum Member
Posts: 1141
Joined: 2005 Oct 16, 19:09

### Re: Passing line number to external viewer

you should show the command you used for the external editor so Kilmatead can test it...

Platinum Member
Posts: 4569
Joined: 2008 Sep 30, 06:52
Location: Dublin

### Re: Passing line number to external viewer

Yeah, I need to see the actual arguments you used, and in what order. The method I used is highly dependant upon specific arguments in specific positions, and any deviation from that will throw a wrench in the works - for example, right now it doesn't accept any other user arguments you may want to pass to the external editor, and their addition will screw up the lot.

In every test I ran, it worked perfectly for me if the examples I gave above were applied literally (except for whatever pathnames are needed)..

As the "close" parameter did not work for you, that tells me it's not being found in the correct position in the command-list - it's not case sensitive, but it is position sensitive (and by position I don't mean "just at the end", because the "end" is not actually the end here).

Remember (counter-intuitively) that the external-editor command in Ed2 automatically adds the filename argument by itself, so you don't ever need to use %1 or anything like that for Vim, and adding such a thing will just scare the children.

jporubek
Member
Posts: 10
Joined: 2010 Jan 05, 19:07

### Re: Passing line number to external viewer

I was going to make a snide remark about this not being my first rodeo and that I can follow simple instructions, but I refrained (or did I?). Anyways, here's my exact line, pulled directly from the External viewer: window in Editor2 options (the paths weren't even changed to protect the innocent):

Code: Select all

"C:\Program Files\zabkat\Ed2Conceder\Ed2Conceder.exe" "C:\Program Files\Vim\vim74\gvim.exe" "+"
For what it's worth and in case it makes a difference, here's the version of Editor2 I'm using (I may have missed an update): 2.9.1.13 Unicode x64

Platinum Member
Posts: 4569
Joined: 2008 Sep 30, 06:52
Location: Dublin

### Re: Passing line number to external viewer

jporubek wrote:I was going to make a snide remark about this not being my first rodeo and that I can follow simple instructions, but I refrained (or did I?).
That's okay, by curious coincidence this just happens to be the annual "Snide Remark Extravaganza Week" here at Zabkat forums, so the more the merrier! What, after all, would the internet be without snide remarks? We even have our own German member who seems to exist for no other reason than to make snide comments and goad me into a chorus of raucous replies for his own amusement. 'Tis in the water, I fear.

That said, the final explanation for the "problem" was rather unexpected:
jporubek wrote:For what it's worth and in case it makes a difference, here's the version of Editor2 I'm using (I may have missed an update): 2.9.1.13 Unicode x64
Surprisingly, this does make a difference! After digging up and installing this same older version as yours to test it, I discovered that its window class is ATL:000000000042C430, whereas the "current" 2.9.2.2 version has a class of ATL:000000000042D430. Methinks someone updated their WTL nonsense and didn't realise that the end of the world was nigh as a result.

Naturally, I wrote the script to check for the "D"-variant, since I didn't even know a "C"-version existed - and thus it could not retrieve the correct window for you, and thus the API call failed, so no line-number is passed, and nor is there a window handle to "close"!

Obviously, I should have stuck an error-trap on that one, but I certainly never expected the window classname to change from one version to the next! What kind of lunatic asylum are you running here, Nikos? Can a man no longer trust the firmness of the Earth beneath his feet? Should we always be vigilant for the evil that lurks in the minds of the butterflies amongst us? Or is this just more of that famous Greek book-keeping skill that made you lads the reliable-moneylenders of Europe we all know you to be?

Since the license for Ed2 is literally "Free as Beer", and since (to my knowledge) no one has as yet figured out how to store real beer on DropBox, I will just supply you with this current version of Ed2 (x64) for the fun of it. The manifest should be replaced as well, as it contains a superfluous Vista+ compatibility notification which is not in the "old version", but no doubt is required (in the grand tradition of MicroSoft) to keep the Rumpelstiltskin's of the world from waking up and finally proving to everyone that "Newerer Does Not Mean Betterer!".

So, after updating your version of Ed2, the Concederer doodad should do its thing as expected... and I apologise for my cavalier attitude towards error-trapping in this instance causing any confusion - I happily place all the blame on Nikos' boring idea of rather technical classname choices... for future reference, Oh Grand Poobah, please use:

WNDCLASSEXW wc = {0};
wc.lpszClassName = L"MayGodHaveMercyOnPoorNikosThePenitent";

...like the rest of us, and I promise no one will ever mention that executive-level ashleymadison.com subscription of yours ever again!

jporubek
Member
Posts: 10
Joined: 2010 Jan 05, 19:07

### Re: Passing line number to external viewer

I guess it was a good thing I thought to include the version of my Ed2, otherwise my post would have been a waste of time and effort and my snide un-remark would have been for naught! With the new Ed2 (thanks for that), your Ed2Conceder works as advertised and is greatly appreciated. Perhaps I need to re-evaluate my decision to hold off on upgrading my xplorer2 to v3. I don't particularly like ribbon toolbars and this time I was going to have to pay full price. But Nikos deserves to get paid for his fine efforts and I don't want to be the "special case" using outdated software!
Kilmatead wrote: Or is this just more of that famous Greek book-keeping skill that made you lads the reliable-moneylenders of Europe we all know you to be?
That made me laugh out loud and hopefully was taken in the spirit of good fun by Nikos. You seem to know him better than I do.