Automate suggestions in your command line!

Intro

Hi all, today I would like to say something about automation of work. I use cmder¬†as my standard command line. I would like to focus today on clink integration. It is the very powerful tool, which allows you among other things to add your code completions. And this post will be devoted to that. Because in my current work I use vagrant. I lacked very many suggestions of provisions and snapshots syntax support. There is some support for vagrant suggestions, but this stuff wasn’t implemented. So I started investigating and added it ūüėČ


Lua – extend your clink in cmder

During my beginning of investigation how it is working. I found this directory:

{your_path}\Cmder\vendor\clink-completions

And I found repository¬†related to clink-completions where I’ve contributed.¬†So as you can see the language used for code-completion is Lua. Lua is functional and scripting language. Probably the reason why this language is chosen is that¬† clink already uses Lua to parse the commands:

view raw clink-lua-parser.lua hosted with ❤ by GitHub

To implement straightforward map write something like that:

local chris_parser = parser({
"m1" .. parser({
"m1a",
"m2a"}),
"m2" .. parser({
"m2a",
"m2b" ..parser({"--x"})}),
}, "-h" .. parser({}))
--register parser under first keyword
clink.arg.register_parser("chris1", chris_parser)
view raw chris-parser.lua hosted with ❤ by GitHub

To run your new system suggestion just open a new command line and start typing chris1 and press tab

Printed suggestions.

If you want to check graph of your parser just invoke command below:

chris_parser:dump()

Then on the new command line, it will show you a graph of your abstract syntax tree like this:

0.0 - m1
1.0 - m1a
1.0 - m2a
0.0 - m2
1.0 - m2a
1.0 - m2b
2.0 - --x
0.F - table: 000000AFCDC87FB0
view raw chris-parser-ast hosted with ❤ by GitHub

Everything is easy when you need to provide just simple map. But what if you need to do something more complicated?

local parser = clink.arg.new_parser
--declare function
local function xyz()
return {"a","b","c"}
end
local chris_parser = parser({xyz})
clink.arg.register_parser("chris", chris_parser)
view raw function-lua.lua hosted with ❤ by GitHub

The answer is: declare function which returns collection of strings. The order of code matters. So to use function which you would like to use you need to define it first.

So to provide some custom functionallity you need to use function and then you can use all of good of Lua language. Additionaly, you have also modules in module directory:

{your_path}\Cmder\vendor\clink-completions\modules

which you can load to your scripts.

-- load module into matchers alias
local matchers = require('matchers')
-- use clink to get system environment
clink.get_env("VAGRANT_VAGRANTFILE")
view raw load-more.lua hosted with ❤ by GitHub

When lua scripts are loaded in cmder?

Lua scripts of code-completion in cmder are loaded at each time when open new console.

If you consider file `.init.lua` in code-completion folder you will notice that every file with lua extension is taken into consider when your clink/cmder is running.

Vagrant addendum

If you go to my github you can see that I’ve contributed to clink-completions and I added two things:

  1. Snapshots
  2. Suggest name of provisions

I did it in 3 Pull Requests:

First pull request where I did the most of stuff. The main mechanism is like this:

  • Find Vagrantfile – mostly analogous as finding¬†.git folder¬†in git suggestions
  • Find matching regex
  • Return matches as collection for parser

Enhance regex for provision names

Bug fix of unclosed file

References