# A :lua command for Kakoune

**URL:** <https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003>\
**Category:** Plugins\
**Created:** [May 8, 2020, 5:47am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003 "2020-05-08T05:47:06Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 8, 2020, 5:47am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/1 "2020-05-08T05:47:06Z")

</div>

Kakoune doesn’t have an embeded scripting language. Instead, it defines a clever extension model in which you rely on external tools to do all sorts of work. In particular, to execute some programming logic, it has the built-in `%sh{}` expansion.

As a user of the [fish](https://fishshell.com/) shell, I’m not used to the idiosyncrasies of standard Unix shell programming. So I’ve been missing a programming language I’m more familiar with when writing my `kakrc`.

This is why I’ve written a very simple plugin to Kakoune called [luar](https://github.com/gustavo-hms/luar). It defines just a single `:lua` command to execute lua code from within Kakoune. It’s not meant to be a bloated binding to Kakoune’s internals. It’s just a simple complement to the `%sh{}` expansion to be used whenever you need to write some logic.

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 8, 2020, 5:53am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/2 "2020-05-08T05:53:03Z")

</div>

This is really cool! We had a thread previously discussing the need of real scripting language: [Kakoune needs a real scripting language](https://discuss.kakoune.com/t/kakoune-needs-a-real-scripting-language/575) and in it there was several lua examples you may find interesting.

I’ve defined this abomination [https://github.com/andreyorst/dotfiles/blob/master/.config/kak/defperl.kak](https://github.com/andreyorst/dotfiles/blob/master/.config/kak/defperl.kak) but never actually used it, because I mostly fine with shell script. Some of my plugins do use Perl, but I just call functions from files directly via shell. But your solution seems like a quite nice library

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 8, 2020, 12:42pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/3 "2020-05-08T12:42:00Z")

</div>

Thanks!

One thing I’ve found curious about that thread is that people started to mix two different decisions:

1. Have a scripting language built in.
2. Expose traditional bindings (like Emacs and Vim do) to Kakoune’s internals using that scripting language.

This plugin shows they can be thought independent of each other.

I don’t think Kakoune would benefit from an implementation of the second decision. For me, this is clear.

But I would like to see a good discussion about the pros and cons of the first decision. Perhaps, during that discussion, the community find that this is not a good path to take, but I still didn’t see good arguments in favour or against it. Just arguments mixing the two different decisions.

---

<div class="post-metadata">

**Author:** ![robertmeta](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/robertmeta/32/833_2.png) [@robertmeta](https://discuss.kakoune.com/u/robertmeta)\
**Post date:** [May 8, 2020, 4:22pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/4 "2020-05-08T16:22:05Z")

</div>

> [@andreyorst](#):
>
> because I mostly fine with shell script

I am becoming less fine with them by the day, as for reasons I have yet to track down they will just suddenly stop working. There was a great spelling one I got from here, that suddenly stopped working and I haven’t yet dug in to debug.

---

<div class="post-metadata">

**Author:** ![robertmeta](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/robertmeta/32/833_2.png) [@robertmeta](https://discuss.kakoune.com/u/robertmeta)\
**Post date:** [May 8, 2020, 4:25pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/5 "2020-05-08T16:25:52Z")

</div>

Multiple great points.

> [@gustavo-hms](#):
>
> Just arguments mixing the two different decisions.

Agreed, and as you pointed out, they are best carried on as two completely seperate discussions. The reasoning (as I have understood it) for not embedding a script language is well – the platform has script languages.

> [@gustavo-hms](#):
>
> Expose traditional bindings (like Emacs and Vim do)

One interesting thing is how differently those two editors approach this, vim having a kakoune alike (the command is the command) and emacs having “the command calls the API” – which in and of itself is really a 3rd discussion!

Very cool binding, as someone who was a huge fan of tier 1 support for Lua in Neovim, this is something I will have to dig into.

---

<div class="post-metadata">

**Author:** ![alexherbo2](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/alexherbo2/32/1140_2.png) [@alexherbo2](https://discuss.kakoune.com/u/alexherbo2)\
**Post date:** [May 8, 2020, 4:40pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/6 "2020-05-08T16:40:16Z")

</div>

I like `sh` as a glue script to external tools. It encourages to write Kakoune and text editor independant tools.

I don’t like `sh` because of the string hell escaping and slowness. Talking back to Kakoune with perfect escaping is difficult, and running multiple shell commands to have their outputs is slow.

I’m not a fan of Lua, but it elegantly solves the two problems above.

What I’m afraid of, is having a real programming language encourages users to extend the editor with it instead of using it as a glue to external tools.

`sh` is ugly for sure, but it is a good constraint – and rail – for the creativity and composability (because it would be too ugly and slow to implement that and that in pure `sh` :D, we rely on external and language independant applications). On another topic, the same idea can be transposed for synchronous vs. asynchronous highlighters.

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 9, 2020, 8:36am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/7 "2020-05-09T08:36:36Z")

</div>

debugging shell scripts is really painful indeed. The most complex plugins I wrote were plug.kak and fzf.kak, and I’m really scared to change those much

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 9, 2020, 8:39am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/8 "2020-05-09T08:39:11Z")

</div>

> [@alexherbo2](#):
>
> `sh` is ugly for sure, but it is a good constraint – and rail – for the creativity and composability (because it would be too ugly and slow to implement that and that in pure `sh` 😃

_ahem_, [shit](https://git.sr.ht/~sircmpwn/shit), _ahem_

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 9, 2020, 3:25pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/9 "2020-05-09T15:25:45Z")

</div>

> sh is ugly for sure, but it is a good constraint – and rail – for the creativity and composability (because it would be too ugly and slow to implement that and that in pure sh :D, we rely on external and language independant applications).

This is an odd reasoning, but a legitimate one. So, apparently, these are the arguments in favor of using a POSIX shell for scripting:

- It’s portable to any POSIX OS.
- Being a glue language, it encourages you to rely on external tools to do all sorts of work, thus enforcing composability.
- Being such a horrible language, no one wants to use it except for the bare minimum. Again, enforcing composability. In fact, the claim that Kakoune does not have a scripting language of choice is not very accurate, since it does have one (the POSIX shell), although not built-in; it’s just that it is such a pain to use in complex programs development that developers prefer to use something else.

So, let’s start to thing about alternative ways to enforce the same discipline without to much burden for plugin developers.

At the moment, I can see two possible alternatives I want to discuss with you.

## Restrict the environment

Suppose Kakoune embeds a scripting language. It, as the host environment, can restrict what a script is able to see. I’m going to use Lua as an example, but I thing the same arguments hold for other scripting languages.

One very nice property of Lua is that it’s designed from the beginning not to be an interpreted language, but a _scripting language_. It means its design reflects the fact that it is conceived to be embedded in a host environment, being the Lua interpreter just an example of such a host. This is one of the reasons for its minimalism (the entire Lua C library has just a hundred kilobytes). As such, a Lua script can access the outside world only through the host, and the host has total control of what is exposed to the script.

For example, by default, its C API doesn’t expose any Lua module to the script. The host has to explicitly tell what it want the plugin to see.

So, one way to have Lua as a scripting language while still enforcing a Unix discipline is to load only the minimum set of modules necessary for the plugin to communicate with the POSIX environment (like the `io` and `os` modules). Or even providing a custom (more POSIX-like) module for accessing the OS, since the desire to be extremely portable and minimalist makes Lua do not provide many tools for interacting with the operating system.

Another interesting aspect is that the `require` statement used to import modules is not really a statement, but a function. Being a function: it can be configured to just load modules from a specific PATH Kakoune has control of; it can be replaced by a custom one; or we can even remove the `require` function altogether, making the plugin unable to use any module not explicitly provided by the host.

This way, we gain:

- a better scripting language;
- a [way faster one](https://julialang.org/benchmarks/);
- a portable one, because it’s embedded in Kakoune itself;
- a programming environment that enforces a composability discipline as much as we want.

Again, I’m using Lua as an example because I know it better (and I know it enough to say that it also has many aspects I don’t like at all). I’m sure you can list other languages with similar characteristics, and I really don’t care if another one would be chosen (in the case Kakoune decides to embed a scripting language). I don’t have a beloved programming language and actually like to learn new ones (provided they are not as arcane as bash scripting =D).

## Provide a client-server model

A very interesting scripting model is the one adopted by [bspwm](https://github.com/baskerville/bspwm). It has two programs: the actual window manager (`bspwm`) and a configuration program (`bspc`). The later communicates with the former using a socket, and it is used to send to `bspwm` whatever messages necessary to control it.

It has some subcommands, among which `bspc query`, to inspect `bspwm`’s state, `bspc config`, to set configuration options, and `bspc subscribe`, to listen to events.

A configuration file is just an executable file `bspwm` executes at initialisation. Here is mine:

```fish
#! /usr/bin/fish

sxhkd &
picom --experimental-backends &

bspc monitor eDP1 -d 1 2 3 4
bspc monitor HDMI1 -d 5 6 7 8

bspc config initial_polarity first_child
bspc config border_width 1
bspc config presel_feedback_color "#0b2f4f"
bspc config focused_border_color "#eff0f1"
bspc config normal_border_color "#2f353a"
bspc config window_gap 6
bspc config gapless_monocle true
bspc config click_to_focus true
bspc config pointer_follows_monitor true
bspc config remove_disabled_monitors true
bspc config remove_unplugged_monitor true

bspc rule -a plasmashell state=floating border=off layer=normal
bspc rule -a krunner border=off state=floating layer=above

```

My `bspwmrc` is very basic and declarative, but it can have arbitrary logic in it if needed.

One nice property is that `bspwm` is idempotent regarding the configuration. So, to reload the config file, one just needs to execute it again.

This models allows `bspwm` to adhere more closely to the Unix philosophy. For instance, it doesn’t process keyboard shortcuts, relying on external programs (such as `sxhkd`) to do so. So, a sample `sxhkdrc` looks like this:

```auto
# Alternate between the tiled and monocle layout
super + m
	bspc desktop -l next

# Swap the current node and the biggest node
super + g
	bspc node -s biggest.local

# Cancel the preselection for the focused desktop
super + ctrl + shift + space
	bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel

```

Note how every command is just a simple shell command line invocation. Also, note how clever this model is: since the configuration file is just an executable, `bspwm` doesn’t need to parse it; it doesn’t even need to read it, just execute it. From `bspwm` perspective, its content is irrelevant. As such, I can write my config file in whatever language I want, even compiled ones. It’s written in `fish`, but could also be in Lua:

```lua
#! /usr/bin/env lua

-- A bspwmrc written in lua

os.execute("sxhkd &")

-- ...

os.execute("bspc config initial_polarity first_child")
os.execute("bspc config border_width 1")

-- ...

```

Or, perhaps, Ruby:

```ruby
#! /usr/bin/env ruby

# A bspwmrc written in ruby

`sxhkd &`

# ...

`bspc config initial_polarity first_child`
`bspc config border_width 1`

# ...

```

This is truly a language agnostic plugin model. Kakoune, instead, is tied to POSIX shell scripting more than we usually admit.

It also has the benefit to abstract away both the handling of communication with the server and the protocol to do so. If it uses `json`, `ZeroMQ`, raw strings, etc., for the user it doesn’t matter, and frees the `bspwm` developers to change to another implementation if needed without compromising the API.

I don’t know if this is a model that can be used by Kakoune, but if it could, it would be a big improvement.

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 9, 2020, 3:30pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/11 "2020-05-09T15:30:55Z")

</div>

> [@alexherbo2](#):
>
> On another topic, the same idea can be transposed for synchronous vs. asynchronous highlighters.

I’m not sure I’ve understood it…

---

<div class="post-metadata">

**Author:** ![alexherbo2](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/alexherbo2/32/1140_2.png) [@alexherbo2](https://discuss.kakoune.com/u/alexherbo2)\
**Post date:** [May 9, 2020, 5:39pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/12 "2020-05-09T17:39:58Z")

</div>

> <https://github.com/mawww/kakoune/issues/2454#issuecomment-428372089>
>
> So I've tested three main editors, which I think are comparable: Kakoune, Emacs …and NeoVim. All with default settings. I've opened simple web page, which size is 10M. What I've noticed is that both Vim and Emacs use pretty much the same amount of RAM no matter what position I am currently viewing, while Kakoune needs whooping ~340M MB after jump to the end of the file.
> 
> So what I did:
> Opened this file: \[https \_habr.com\_post\_423889\_htm.tar.gz\](https://github.com/mawww/kakoune/files/2430952/https.\_habr.com\_post\_423889\_htm.tar.gz);
> \- \`kak\` (user configuration folder doesn't exist): 55.7M
> \- \<kbd\>g\</kbd\>\<kbd\>j\</kbd\>
> \- checked memory usage: 338M
> 
> The same for NeoVim:
> \- \`nvim -u NORC\`: 18.2
> \- jump with: \<kbd\>G\</kbd\>
> \- after jump: 18.2
> 
> Emacs:
> \- open file: 35.8
> \- \<kbd\>Alt\</kbd\>\<kbd\>\>\</kbd\>
> \- after jump: 41.5 but highlighting is \_broken\_
> 
> nvim starts immediately, and jump is super quick. Emacs need some time, comparable to Kakoune, and jump takes some time too.
> 
> I know that vim and neovim doesn't highlight whole file, like it is done in Kakoune (maybe I'm wrong, but it is the only meaningful reason why memory usage is so big), but only a part of it. I don't know how it is implemented in Emacs, but memory usage still stands around the same value as at the moment of opening file. Opening file with \`kak -n\`, is immediate, and jump is quick too, memory usage is the same, regardless positioning - 18M, but there's no highlighting.
> 
> Sometimes I work with huge log files, and I apply syntax highlighting to them. Previously I did this in NeoVim, with my own syntax file. I'd like to stop using neovim for that, because I do like kakoune's editing model more, but working with several files of even bigger size is painful due to RAM limit I have.
> 
> Are there any plans of optimizing Kakoune's highlighting system, or a way to limit highlightion to visible part of file or to some meaningful regions so parser could do highlighting correctly, but not keep it for whole file?

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 9, 2020, 5:58pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/13 "2020-05-09T17:58:03Z")

</div>

> [@gustavo-hms](#):
>
> It’s portable to any POSIX OS.

Not quite. Many scripts that work in posix sh on Linux will not work in poxis sh on BSD due to _bugs_ in sh itself. I had some experience with my plugins not working on BSD because of how its shell put processes to background

---

<div class="post-metadata">

**Author:** ![TeddyDD](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/teddydd/32/21_2.png) [@TeddyDD](https://discuss.kakoune.com/u/TeddyDD)\
**Post date:** [May 10, 2020, 7:10pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/14 "2020-05-10T19:10:40Z")

</div>

Well done plugin! I have to come up with some nice uses for it.

* * *

> [@gustavo-hms](#):
>
> It has two programs: the actual window manager ( `bspwm` ) and a configuration program ( `bspc` ).

We kinda have it with Kakoune - `echo "cmd" | kak -p SESSION`. You can execute this command from any programming language skipping shell (and avoiding painful shell escaping issues). Transferring data out of Kakoune is cumbersome unfortunately. Env variables are clunky and most reliable way (I think) is `echo -to-file` since it avoids shell altogether.

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 11, 2020, 12:05pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/15 "2020-05-11T12:05:02Z")

</div>

> [@andreyorst](#):
>
> Not quite. Many scripts that work in posix sh on Linux will not work in poxis sh on BSD due to _bugs_ in sh itself.

Then there’s yet another unanticipated problem in the current situation…

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 11, 2020, 12:06pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/16 "2020-05-11T12:06:29Z")

</div>

> [@TeddyDD](#):
>
> We kinda have it with Kakoune - `echo "cmd" | kak -p SESSION` .

Hi, @TeddyDD! Thanks for the suggestion. Unfortunately, it works just until you realise you need the `SESSION` information in the first place. How do you get it? Additionally, I can’t write my `kakrc` in whatever language I want (like with my `bspwmrc`), because Kakoune parses it and so it needs to understand it. But let’s try to elaborate it a bit further to see what we get.

Perhaps what we need is an opaque `kakrc` together with opaque command definitions.

Suppose for a moment that, like `bspwm`, we have an hypothetical `kakc` client, used to communicate with the server (it can be a `kak -p` with some additional features). Also like `bspwm`, suppose Kakoune doesn’t read `kakrc`, just executes it. In this scenario, `kakrc` is opaque to Kakoune and so can be written in any language, say, Julia:

```julia
#!/usr/bin/env julia

# This is `kakrc` written in Julia

`kakc set-option global grepcmd ag`
`kakc set-option global aligntab true`

`kakc define-command a-new-command -params 2 mycommand`

```

If, then, the command `a-new-command` is invoked like this: `:a-new-command \d+ 17`, Kakoune does something along these lines:

```sh
export KAKOUNE_SESSION="the session number"
export KAKOUNE_CLIENT="the client from which the command was invoked"
mycommand '\d+' '17'

```

It allows us to write the custom command as an executable file called `mycommand` written, say, in Lua:

```lua
#!/usr/bin/env lua

-- This is file `mycommand`

local param1, param2 = arg[1], arg[2]
local register = io.popen("kakc query register 1"):read()
local text = register:gsub(param1, param2)
os.execute("kakc add-highlighter window/mycommand dynregex " .. text .. " 0:default,+u")

```

There are many informations in the above examples. Let’s start with the first one:

- `kakc` subcommands are named after the commands they invoke;
- a custom command is nothing more than an external executable (in this example, called `mycommand`).

When the new command is invoked (see the second example):

- Kakoune executes the associated executable, setting some environment variables needed to identify the client and session from which the command was invoked;
- whatever parameters are passed to `:a-new-command` are then passed to the executable as command line arguments (like `luar` currently does).

In the `mycommand` file:

- parameters can be accessed as command line arguments;
- Kakoune’s state is accessible via a new `kakc query` subcommand;
- the plugin doesn’t need to manage session information; since everything is already set in environment variables, `kakc` itself can automatically read them, freeing plugin authors from handling them.

By doing so, both `kakrc` and command definitions would be opaque to Kakoune and, as such, all code related to parsing `.kak` files could be deleted from Kakoune, thus reducing the code base.

Is it enough? Or am I missing some complications? More importantly, is it feasible?

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 11, 2020, 12:30pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/17 "2020-05-11T12:30:37Z")

</div>

> [@gustavo-hms](#):
>
> Unfortunately, it works just until you realise you need the `SESSION` information in the first place. How do you get it?

There’s a `$kak_session` environment variable that is being exported via Kakoune inside `%sh{}` blocks

> [@gustavo-hms](#):
>
> Then there’s yet another unanticipated problem in the current situation…

The problem is, that there is no truly crossplatform solution. Our best bet is virtual machines, that encapsulate common part between all systems while providing the same interfaces for all different operating systems thus sacrificing performance. But even java has cross platform problems.

VM based languages generally better at cross platform apps though, and that’s why I mostly use Perl for my plugins, since it is available for majority of systems where Kakoune runs, and seems to be pretty the same across those. I don’t know how good Lua in this regard, but I know that it uses libraries written in C, which probably can be a portability problem. I also think that this is why python is popular for plugin development across various editors.

Given that we have a way to escape Kakoune to shell we can use any language for scripting, as long as we escape strings well. Luckely for us Kakoune supports arbitrary delimiters for strings so we can easily use non-ascii characters like: `echo %sh🦀 echo "{}[]()''\"\""🦀` and don’t worry much about escaping things.

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 11, 2020, 1:29pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/18 "2020-05-11T13:29:32Z")

</div>

> [@andreyorst](#):
>
> I don’t know how good Lua in this regard, but I know that it uses libraries written in C, which probably can be a portability problem.

Lua is written in _Clean C_ (a subset of ANSI C) exactly to enable porting it to as many platforms as possible. This is why its [`os` library](https://www.lua.org/manual/5.3/manual.html#6.9) is so restricted. This deliberate decision probably makes it a better solution than alternatives regarding portability.

> [@andreyorst](#):
>
> There’s a `$kak_session` environment variable that is being exported via Kakoune inside `%sh{}` blocks

I mean we still need to rely on `%sh{}` to get expansions, so we can’t approach the problem the `bspwm` way even with `kak -p`

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 11, 2020, 1:56pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/19 "2020-05-11T13:56:56Z")

</div>

> [@gustavo-hms](#):
>
> I mean we still need to rely on `%sh{}` to get expansions, so we can’t approach the problem the `bspwm` way even with `kak -p`

You can save session by doing `echo -to-file /tmp/kak-session %val{session}`. I get your point though.

---

<div class="post-metadata">

**Author:** ![gustavo-hms](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/gustavo-hms/32/598_2.png) [@gustavo-hms](https://discuss.kakoune.com/u/gustavo-hms)\
**Post date:** [May 11, 2020, 7:25pm UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/20 "2020-05-11T19:25:36Z")

</div>

The truth is that I have little experience writing plugins for Kakoune. You are at a much better position to say what works and what doesn’t 😄 I was just trying to take into consideration @alexherbo2’s concerns. For my personal needs, the `:lua` command is the missing piece, everything else works well enough.

That said, I must say I like the idea of having opaque commands .

> [@andreyorst](#):
>
> that’s why I mostly use Perl for my plugins, since it is available for majority of systems where Kakoune runs

That’s the main problem with Lua. One can’t expected it to be shipped by default on any OS. On the other hand, since it’s so small (the interpreter for Linux 64 is ~ 250 KB), if this turns out to be a problem, I can always ship it bundled with any plugin I make, or even download it on demand.

> [@andreyorst](#):
>
> Luckely for us Kakoune supports arbitrary delimiters for strings

This is something very useful indeed.

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [May 12, 2020, 7:08am UTC](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003/21 "2020-05-12T07:08:39Z")

</div>

> [@gustavo-hms](#):
>
> The truth is that I have little experience writing plugins for Kakoune. You are at a much better position to say what works and what doesn’t

You’ll be good at it in no time 😃

[Next page](https://discuss.kakoune.com/t/a-lua-command-for-kakoune/1003.md?page=2)
