Sunday, April 21, 2013

FAR Manager. Macros and whatnot.

Edit: This article's updated variant has been posted to an appropriate  forum. 
Gather round, boys and girls, for I am about to tell you a story.

Macro in your FAR Manager? It's more likely than you think.

    The "macro" term is used loosely in Far to describe a broad range of user-made modifications of the application's behavior. For the sake of simplicity, let me divide them into several use cases:



1. Assigning hotkeys / remapping key bindings.
This is the simplest. You want one custom key (or combination with Ctrl, Shift, Alt modifiers) do what another key (combination) already does. It is one for one replacement.

2. Your typical macro. Press one key to emulate a sequence of many keys. 
Its not much different from just a hot key. You press a key - it is treated as if you pressed some fixed predefined string of keys.

3. Script.
Now this is interesting. Script involves logic and decision making, not just some fixed reaction. A script has means to analyze current situation and affect Far Manager in non-trivial ways. Requires programming skills to create, but luckily the are many scripts already written and you may find one just fitting your needs.

4.  Plugin.
Well, this is a moot point. With the course Far development is following now the gap between a complex script and a full fledged plugin is closing rapidly. As of right now, a script has most of functional capabilities a plugin has, it has access to both macro API and plugin API, in the latest builds a macro script can be started by an event, not just by a key pressed and so forth...

History and identification of obsolete.

    FAR Manager has traveled a long way from its early versions and so did its macro capabilities. In Far1 and Far2 the configuration was stored in Windows registry, including macros. In Far3 configuration was moved to SQLite database files located in user's profile folder. But later it was decided that it would be better to allow users simpler access to macros and they were moved from a database to individual files (still inside user's profile folder). Also, parallel to moving macro definitions to external files, the macro language was changed to LUA.
    In addition to that, there is a very popular plugin called "MacroLib". It provides extended macro features on top of built-in system. It used to overlay old macro language, but then switched to LUA as well. It always stored macros in external files.

    So, what to look out for to spot outdated manuals / macro recipes?
1) *.reg files. Partial and full configurations were distributed as reg import files in times of Far1 and Far2. That included macros. No *.reg files are used in Far3.

2) *.farconfig files. Those are XML text files containing configurations for Far3. They are still used for other parts of configuration (coloring schemes and such) but not for macros anymore.

3) Old macro language. It contained keywords like "$IF" "$ELSE" - denoted by dollar sign.

4) Old MacroLib files *.fml - new MacroLib macro files use "fmlua" extension.

    It is important to note that internal help in Far (called by "F1") is massively lagging behind development - hence this article.

   What now?

    At present, by means of storage macros fall in three groups.
1) Files of the built-in macro system. *.lua
Located in %FARPROFILE%/Macros/internal and %FARPROFILE%/Macros/scripts

2) MacroLib files *.fmlua. 
By default are located within plugin's folder, but it can be configured to read macros from any user defined path (or several).

3) Other macro processing plugins. "Lua4Editor", for example. I don't know much about these, you are on your own here, folks.

    Important warning! There are plugins written in LUA. These are something different from macros. They are legit plugins with all the things a "usual" plugin has (like being listed in plugins' menu "F11"). Except they are written in LUA and distributed as source files. They should not confuse you as they lie in their folders in %FARHOME%/Plugins

Conversion.

    It is best to rewrite your macros in LUA from scratch. If they are few and simple, it won't take much effort. If they are complex, conversion is likely to fail to do it automatically. But if you are still interested in doing things hard way, there are few tools to help you. They were meant as quick fixes for transition period and aren't supported anymore, probably.

I. Far1, Far2 -> Far 3 2x3 perl converter
This tool is used to convert old configuration from registry to database. This includes macros.
The result will be a bunch of XML files containing far configurations and macros in the old language.


II. Translation from old language to the new one is done by Macro2Lua Converter plugin. The readme is in Russian, but here is an excerpt regarding main usage via command line
 >  M2L: convert <input file> <output file> [<syntax>] 
where <syntax> is optional input format specifier and is one of following:
xml_file, xml_macros, xml_keymacros, xml_macro, fml_file, fml_macro, chunk, expression. General file format is the part before underscore, the specific section of a file is the part after underscore. "chunk" and "expression" are some kind of raw macro pieces of texts.

  The result should be a XML file (<farconfig> </farconfig>) with macros translated to LUA inside of it or a MacroLib fmlua file if original was *.fml and corresponding syntax was specified.

III. Far3 2927-3000  -> Far3 3001+
   Now you need an older version of Far3 (pre3001). You import your macros to Far per usual command, then use a script provided in the following forum thread:
  Macros have been moved from macros.db to files

Managing confusion.

    While all macros are written in LUA, file contents are not interchangeable as of right now. It means that you can't rename X.fmlua to X.lua, move it to %FARPROFILE%/Macros/scripts and expect it to work. Likewise you can't just move files from /internal to /scripts.

    Luckily, with few rules I am about to explain, you won't get lost in all of the LUA files lying around.

1) Don't touch your internals!
Files in %FARPROFILE%/Macros/internal are to be manipulated (created/edited/deleted) by FAR Manager itself. And while it is possible to edit them manually, better to leave them alone. Unless you really know what are you doing. Or just feeling adventurous.

2) MacroLib files are always named *.fmlua, so you can never confuse them with native script files, even if you configured the MacroLib so they are located in the same directory.

3) User-made native script files are located in %FARPROFILE%/Macros/scripts and are named *.lua.  They are read at Far launch, but you can make Far to re-read the folder via command line (more on that later).

    So, only (2) and (3) are in user's management and they are different in names, location and internal structure.

    But there are similarities too.

    1) Both  MacroLib and native macros have a concept of "Area of execution" - basically, a broad condition limiting macro effect. Typical are "Editor" - when editor is open, "Shell" - when file panels are in focus, etc...

    2) In addition to general area, some more conditions might be specified for activation of a macro. Like passive panel being visible, command line not being empty and similar. These conditions/flags are legacy carried over from times when macro language was primitive and things like that were hard to check in script itself. Alternatives are being developed (like custom function conditionals in native scripts) but there is no sign that old flags will be abandoned yet.

    3) And finally, there are two flags that control execution of the macro itself. One is to disable/enable intermediate visual output during macro execution (reduces flicker of menus and dialogs being open/closed, for example), another is to control if plugins can intercept keyboard events generated by macro. No other macro can intercept current macro while it is executing - so you don't have to worry about nasty macro interferences.


Out of the box.

    In the beginning of time the macro language was ugly and everyone was sad. And few of the developers raised their voices: "Look! There in the great outside lies shiny LUA. Let us take it for ourselves, let us bind it to our manager and then we won't be suffering dollar-signed keywords no more." And so they did. And night turned day, and day turned night, and the Moon died and was born again as they tinkered and meddled and compiled and debugged. Seasons passed by, but finally, the day has come and their labor was over.
    And they stood proud among men and shouted: "Behold this LuaMacro plugin! We can rework our ugly macros into LUA, we have the technology now. But wait! There's more: we can write plugins in LUA as well, if we desire so." And everyone rejoiced.
    And gathered developers of Far and saw what their brethren did, and saw that it was good. So good in fact, they put the new plugin in the core package and abandoned their old ways of macros.

    So, native macro capabilities are provided by LuaMacro plugin, which is distributed with Far itself as part of its core package. The plugin has no configuration dialog, but has a list of commands to manipulate it:
  • lm: unload     - Far forgets all macros. They are still on disk and can be loaded back with next command.
  • lm: load       - makes Far discard all macros and then re-read them from directories anew. 
  • lm: post <sequence>|@<filename>   - executes a macro code immediately. Either a "raw" piece of code typed in command line, or same raw code saved in a file. File name is prefixed with "@" symbol.
  • lm: check <sequence>|@<filename>  - same as above. Except the macro is not executed but checked for syntax errors.
  • lm: save       - I don't have a clue.
    When "load" and "unload" operations are concerned, only native macros are affected. I.e. those *.lua that are located in /internal/ and /scripts/. MacroLib macros are not touched. List of all currently loaded native macros is available in Far built-in help "F1". That part of help is not translated to English yet, and its not very convenient in operation anyway. Check this macro out though.

Note. "lm:"  commands are similar to ones provided by FarCommands plugin via "macro:" and "far:macro " prefixes. There was a difference in that FarCommands used "<" symbol to specify filename, but now it supports both "<" and "@" for this.

    It is time now to explain why some macros are put in /internal/ and others in /scripts/. Its fairly simple - "internal" is a codename for "recorded" and all the recoded macros go there. More on recorded macros is in the "Hotkeys / Macro use case" chapter.
    User-made macros are to be placed in /scripts/. Sadly, there's no comprehensible manual on how to write them. One is reduced to scavenging for bits and pieces of knowledge by perusing Far's changelog and dissecting macros written by others (SimSU macro pack for example, topic in Russian forum: http://forum.farmanager.com/viewtopic.php?f=15&t=7075). Here is a script for the Editor that pastes a macro template on "Ctrl+F11" by Shmuel: InsertMacro.lua.7z

MacroLib.

    This is what all the cool kids use. MacroLib is a plugin that provides somewhat extended functionality to macros. It is built on top of native macro system, so 99% of the code working for "regular" macro will work for MacroLib as well.
    Project's main page: http://code.google.com/p/far-plugins/wiki/MacroLib, download page: http://code.google.com/p/far-plugins/downloads/list?q=MacroLib, documentation (Russian): http://code.google.com/p/far-plugins/wiki/FML.
    MacroLib files are named *.fmlua and are located in one or several directories designated by user in configuration dialog. The dialog allows you to update macros from disk and shows you a very neat list of all macros currently loaded with ability to sort, filter, run a macro from the list.

    MacroLib used to have many advantages over built-in system, but nowadays Far has caught up for the most part and is ahead in some experimental things (like events). However, there are two things *.fmlua scripts have over *.lua ones.
1) You can use modifiers to your assigned hotkeys, such as "Hold" (macro is invoked after the key was held for a certain period of time), "Double"(on double click or double key tap), "Release" (macro is called on key being released, rather than being pressed).
2) You frame your macro code in double curly brackets for extra swag {{     }}.

Hotkey / Macro use case.

    Can't get used to saving edited file by "F2"? Too lazy to run through menus every time you want to view your current Folder Shortcuts? Then this chapter is for YOU. This chapter covers a very simple usage of Far macros - redefining hotkeys for existing actions and creating hotkeys for actions that don't have them by default.
    The easiest way to do said things is by using "Recorded Macro" feature. The Far Manager has an ability to record your actions (keyboard events) and assign them to a specific key, pressing which will replay your actions. This function is in there from Far1 and is explained in "F1" Help, but I will rehash it for you anyway.
    You start recording by pressing "Ctrl+." (Control key plus dot key) or "CtrlShift+.", a little red "R" letter appears in the top-left corner and your following key presses will be recorded. You continue to use Far as usual, doing things you want to be put in the macro, or just pressing one key you want to be remapped. Then you finish recording by pressing "Ctrl+." or "CtrlShift+." again. Then you will be asked for a key to which this macro will be assigned, you can select one from a drop-down list with a mouse or just press the desired combination, then "Enter". At this moment an optional dialog might appear to configure additional parameters of you macro.

So,
1. "Ctrl+." or "CtrlShift+."
2. Do stuff on record.
3. "Ctrl+."  or "CtrlShift+."
4. Select a desired key to assign to.
5. (optional) Configuration dialog.

    If you finish recording with "CtrlShift+." on step 3 you will be shown a dialog on step 5. Otherwise you won't be. To know more about this dialog, press "F1" while in there, its covered in the Help.
     Starting the recording with "CtrlShift+." puts a "NoSendKeysToPlugins" flag on your macro, which means that during macro playback plugins won't be able to react to keyboard events generated by this macro - it forces plugins to ignore this macro in that regard. I'm not sure if this flag is operational though, as I was not able to confirm it with tests.

    If you made a mistake in your macro during recording you may interrupt the recording by usual "Ctrl+." and then hit "Esc" when asked about desired key.
    If you select a key that is already taken by a macro, you will be asked if you want to overwrite previous macro. This means you cannot have two recorded macros on the same key in the same area of execution. You can, however, have one for each area (one in Editor, one in Viewer, etc.)
    If you need to delete a macro you previously recorded, you create an empty macro for the key you want to free: "Ctrl+.", "Ctrl+.", the key. Then select "yes" to confirm deletion.

    If you want to know what macros are already recorded, you can navigate to %FARPROFILE%/Macros/internal. It is possible delete macros in there, just don't forget to use lm: load command to update, or restart Far.

    Example: lets bind a hotkey to "File associations" menu.
0. (preparation) Make sure you are in the Shell area of Far, its where two panels with files and folders are.
1. Press "Ctrl+." and make sure the red "R" letter appeared.
2. Press "F9" to move input focus to Far's menu (usually is the top line of the window), then "c" for commands, then "a". Now, if done right the "File associations" menu is on screen.
3. Press "Ctrl+."again, a little "Define macro" box should pop up. Press "Ctrl+Shift+a" and confirm that corresponding key code appeared in the box ("CtrlShiftA").
4. Press "Enter" and enjoy a new quality of life improvement you just created for yourself. Now every time you press "Ctrl+Shift+a" combo in Far shell, the menu will instantly appear.

Script use case.

    "Script" is a program that runs within/by other program (as opposed to one run by CPU/OS). Scripts in Far evolved from macros to a point when macros themselves are considered primitive cases of scripting. Being programs, scripts require "Programming / Coding" skill to be created, therefore, if you intend to use Far to its fullest potential you might want to invest few skill points in it on your next level up. Alternatively, you can utilize macros written by someone else - just copy the files in appropriate folders.
    As mentioned before, Far uses LUA language for scripting. From within the script you have access to
 1) Far (plugin) API - function of Far that are available to plugins.
 2) Far macro API - some specific functions that were available in old language. These overlap "Plugin API" to some extend and considered legacy API. Better use "Plugin API" where possible.
 3) Custom functions exported by plugins - some plugins export their functions to be called from macro. Those depend on plugin being installed and loaded, of course.
 4) LUA libraries - native to LUA (see language manual) plus few libraries additionally shipped with LuaFar ("bit64", "win" - gate to Win API, Selene Unicode)
 5) Far UI - you can control Far simply by issuing keyboard/mouse commands to it. Why bother finding a function that will open Editor for file under cursor when you can just send "F4" to Far?

    Your main source of information about Far APIs is in %FARHOME%\Encyclopedia files. Lets look at them.
  • "FarEncyclopedia.ru.chm" - includes (1) and (2), in Russian. Macro API is outdated (pre-LUA). There's an online version too: http://api.farmanager.com/ru/
  • "luafar_manual.chm" - originally a LuaFar plugin manual (writing plugins in LUA), but we can use it in scripts too. Covers (1) in LUA in English. Very spartan - most of the functions have no textual descriptions, only input parameters and result values (implies ability to read "FarEncyclopedia.ru.chm"). For the most part it is not a problem though, functions' names are self-descriptive.
  • "macroapi_manual.chm" - mapping of (2) to LUA. Again, almost no descriptions.
    Damn, its kinda depressing, ain't it? Luckily for you, I have a magical artifact that will allow you to understand Russian: abracadabra. Paste a link to Russian website or text fragment and hit "Enter".
And Acerbic saves the day once again! You are welcome.

    To sum it up: you will use "luafar_manual.chm" in conjunction with translated online encyclopedia for Far plugin API reference and "macroapi_manual.chm" in conjunction with this link for Macro API reference.
    I found this script very helpful: lua_explorer. It allows you to browse Lua tables/values/functions soup available to LUA script. Thread on the forum.

Native or MacroLib?

MacroLib.

Sample script.

Here's a little demonstration of what you can do in MacroLib: "RCtrl Folder shortcuts.fmlua"
[code] ........ [/code]

2 comments:

  1. Replies
    1. Damn. Glad you asked. Here's their site: http://farmanager.com/index.php?l=en

      Far Manager is a free open source orthodox file manager for Windows. (Wiki: http://en.wikipedia.org/wiki/Orthodox_file_manager). It is an efficient way to move/copy/archive/view files in native file systems and entities that can be presented as such (win registry, for example).

      Delete