Macro interacting with other macro

You have encountered a problem using Far macros? Here you can get help.
Post Reply
przemoc
Posts: 30
Joined: Sat 27 Feb, 2010 20:55
Has thanked: 9 times
Been thanked: 3 times

Macro interacting with other macro

Post by przemoc »

Recently I was informed about HlfTools. I don't like to modify external scripts, mostly to support seamless updates in case they would be modified in the future, so wanted to create simple macro utilizing it.

I want / (slash) to perform F4,F7 combo in Help.
The concept: F4 handled in Help by HlfTools opens Editor, F7 handled by Far opens Search dialog.
My initial attempt did not work.

Code: Select all

Macro {
  description="Search in given help page (requires HlfTools)";
  area="Help"; key="/";
  flags="";
  code="Keys(\"F4 F7\")";
}
It behaves like only F7 is executed and normal help search dialog shows up instead of in the editor (editor that HlfTools is meant to show).
I found thread, which pointed me in the right direction - use eval with mode=2, which runs the macro assigned to the keyboard shortcut.

But my second attempt also failed.

Code: Select all

Macro {
  description="Search in given help page (requires HlfTools)";
  area="Help"; key="/";
  flags="";
  code="if eval(\"./F4\", 2) == 0 then Keys(\"F7\") end";
}
It gets to the editor, so there is a progress, but search dialog did not show up.

I was starting to think that perhaps eval returns non-0 error code, which would be strange, so I wrapped eval into far.Message(tostring(...), ...).
I did not get the message upon entering to editor via my slash macro, I got it only after exiting from editor (one Esc) and exiting from help (second Esc).
It looks like editor continues running in macro's context and eval does not return until help is closed.
I admit I started playing a bit with macros in Far only last year, so my assessment of the situation may be incomplete and inaccurate.

What would be the proper and idiomatic way to build Macro in Far upon other existing HlfTools F4 macro?
I feel like extending HlfTools.lua or copy-pasting its F4 macro to separate file and modifying wouldn't be clean solutions.
User avatar
John Doe
Бюрократ
Posts: 14547
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 508 times
Contact:

Macro interacting with other macro

Post by John Doe »

  1. You should not mess with "internal" macros. Read about user macros in macroapi_manual.en.chm
  2. Try to use mf.postmacro(Keys,"F7")
https://t.me/FarManager — Telegram чат
przemoc
Posts: 30
Joined: Sat 27 Feb, 2010 20:55
Has thanked: 9 times
Been thanked: 3 times

Macro interacting with other macro

Post by przemoc »

1.
John Doe wrote: Sun 01 Mar, 2026 16:43 You should not mess with "internal" macros. Read about user macros in macroapi_manual.en.chm
By messing with "internal" macros you mean manually editing keyboard macros recorded in Lua files in %FARPROFILE%\Macros\internal?
I'm aware that
https://github.com/FarGroup/FarManager/blob/builds/3.0.6644/enc/enc_lua/macroapi_manual.en.tsi#L57-L61 wrote:Macrofiles are loaded from sequence of directories (recursively with their subdirectories), determined by one of the following ways (in order of priorities):
  1. A sequence of directories, specified explicitly (in a command or a function argument)
  2. The value of MacroPath variable in the file luamacro.ini
  3. The directory %FARPROFILE%\Macros\scripts
so I always put my macros in %FARPROFILE%\Macros\scripts only.
The macros attempts discussed in this thread were also put there.

Or do you refer to using code vs action in Macro definition?
I started with code, because I thought it will be a simple quick macro so I copy-pasted existing one and tweaked keys, but it turned to be not the case, so yeah, I should switch to action.
According to plugins/luamacro/utils.lua for non-moonscript inline code code is passed to loadstring, which makes it compiled into function every time, so it is more expensive, but does it affect how it executes in this particular case?

2.
John Doe wrote: Sun 01 Mar, 2026 16:43 Try to use mf.postmacro(Keys,"F7")
Do you mean using mf.postmacro like below?

Code: Select all

Macro {
  description="Search in given help page (requires HlfTools)";
  area="Help"; key="/";
  action=function() mf.postmacro(Keys,"F7"); eval("./F4", 2) end;
}
Unfortunately it does not work. From the results I get it works effectively the same like my last attempt. F7 is passed only after hitting Esc twice, basically after Help is left, so it shows Make folder dialog.
If you meant something different, please be more specific, as I am still a newbie in the world of Lua scripts in Far.

What I think happens (and I may be very much wrong) is that below code from F4 action from HlfTools.lua:

Code: Select all

      local res = editor.Editor(filename,nil,nil,nil,nil,nil,nil,findLine(filename,topic),1)
      if res==F.EEC_OPEN_ERROR then
        far.Message(("Unable to open in editor:\n%s"):format(filename), "Error", nil, "w")
      end
      if not far.ShowHelp(filename, topic, helpflags) then -- make use of std error message
        far.ShowHelp(filename, nil, helpflags) -- show @Contents
      end
is executed synchronously by Far, at least from Lua perspective, so whether I use Keys directly or via mf.postmacro it is still executed after quoted code, which is executed due to eval("./F4", 2).

Perhaps the main question is:
If it is possible to schedule execution of code that will be executed when editor is shown by currently running code?
Shmuel
Posts: 7217
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 48 times
Been thanked: 627 times

Macro interacting with other macro

Post by Shmuel »

przemoc wrote: Sun 01 Mar, 2026 22:19 Perhaps the main question is:
If it is possible to schedule execution of code that will be executed when editor is shown by currently running code?
I'm not the user of HlfTools, but I guess the problem is that a modal editor returns control to the macro only when it's finished (i.e. closed).
To work around that you can try something like in the example below:

Code: Select all

Macro {
  area="Help"; key="/";
  action=function()
    far.Timer(100, function(h) h:Close() mf.postmacro(Keys, "F7") end)
    editor.Editor("aa")
  end;
}
Shmuel
Posts: 7217
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 48 times
Been thanked: 627 times

Macro interacting with other macro

Post by Shmuel »

The line with far.Timer call can be replaced by a shorter variant:
actl.Synchro(mf.postmacro, Keys, "F7")
Last edited by Shmuel on Mon 02 Mar, 2026 00:02, edited 1 time in total.
User avatar
HaRT
Moderator
Posts: 11417
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 265 times
Been thanked: 412 times

Macro interacting with other macro

Post by HaRT »

Shmuel wrote: Mon 02 Mar, 2026 00:00 far.Timer call can be replaced by a shorter variant
This variant works for me: far.Timer(0, function(h) h:Close(); mf.postmacro(Keys, 'F7') end); eval('F4', 2)
This does not: actl.Synchro(mf.postmacro, Keys, 'F7'); eval('F4', 2) (F7 is handled only after the modal editor and Help are closed).
Фар есть инструмент, а не нянька. © 2009 DrKnS
Shmuel
Posts: 7217
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 48 times
Been thanked: 627 times

Macro interacting with other macro

Post by Shmuel »

actl.Synchro(mf.postmacro, Keys, 'F7'); eval('F4', 2) works for me as well.
User avatar
HaRT
Moderator
Posts: 11417
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 265 times
Been thanked: 412 times

Macro interacting with other macro

Post by HaRT »

Shmuel wrote: Mon 02 Mar, 2026 00:16 works for me as well
Within the OP's macro?
Фар есть инструмент, а не нянька. © 2009 DrKnS
Shmuel
Posts: 7217
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 48 times
Been thanked: 627 times

Macro interacting with other macro

Post by Shmuel »

HaRT wrote: Mon 02 Mar, 2026 00:21 Within the OP's macro?
No, I didn't try it.
przemoc
Posts: 30
Joined: Sat 27 Feb, 2010 20:55
Has thanked: 9 times
Been thanked: 3 times

Macro interacting with other macro

Post by przemoc »

Thank you, Shmuel, for pointing toward far.Timer (help) and actl.Synchro (help).
Thank you, HaRT, for testing both. Indeed, only Timer works in my use case.

Updated macro:

Code: Select all

Macro {
  description="Search in given help page (requires HlfTools)";
  area="Help"; key="/";
  action=function()
    far.Timer(0, function(h)
      h:Close()
      mf.postmacro(Keys, 'F7')
    end)
    eval('./F4', 2)
  end
}
Using timer is maybe not the prettiest solution, but if there are no better alternatives, I can live with that.
Post Reply

Return to “Support and Troubleshooting”