Full Code of andreyorst/plug.kak for AI

master aa31e3bd89aa cached
4 files
48.2 KB
12.9k tokens
1 requests
Download .txt
Repository: andreyorst/plug.kak
Branch: master
Commit: aa31e3bd89aa
Files: 4
Total size: 48.2 KB

Directory structure:
gitextract_em9e3vjj/

├── LICENSE
├── README.md
└── rc/
    ├── plug.kak
    └── plug.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Andrey Orst

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Project status

Because I have stopped using Kakoune, this project will not receive active maintenance. The issues section has been closed, as I do not plan to address any issues myself. However, I welcome pull requests from anyone who encounters problems with this plugin and knows how to resolve them.

# plug.kak
[![GitHub issues][1]][2] ![license][3]

![plug.kak][4]

**plug.kak** is a plugin manager for Kakoune, which was inspired by [vim-plug][5] and [use-package][6].
It can install and update plugins, run post-update actions, and help to encapsulate the configuration within itself.


## Installation

**plug.kak** can be installed anywhere in your system, but to update itself, it is required to install **plug.kak** in the plugin installation directory.
By default, **plug.kak** installs plugins to the `%val{config}/plugins`, which is usually at `$HOME/.config/kak/plugins`:

``` sh
mkdir -p $HOME/.config/kak/plugins
git clone https://github.com/andreyorst/plug.kak.git $HOME/.config/kak/plugins/plug.kak
```

Now, when **plug.kak** is installed, we need to tell Kakoune about it.
Add this to the `kakrc` file:

``` kak
source "%val{config}/plugins/plug.kak/rc/plug.kak"
plug "andreyorst/plug.kak" noload
```

Alternatively, this process can be automated by adding the following snippet to the `kakrc`:

``` sh
evaluate-commands %sh{
    plugins="$kak_config/plugins"
    mkdir -p "$plugins"
    [ ! -e "$plugins/plug.kak" ] && \
        git clone -q https://github.com/andreyorst/plug.kak.git "$plugins/plug.kak"
    printf "%s\n" "source '$plugins/plug.kak/rc/plug.kak'"
}
plug "andreyorst/plug.kak" noload
```

This will create all needed directories on Kakoune launch, and download **plug.kak** if it is not installed already.

**Note**: `plug "andreyorst/plug.kak" noload` is needed to register **plug.kak** as a manually loaded plugin, so `plug-clean` will not delete **plug.kak**.


## Usage

All plugins are installed and loaded with the `plug` command.
This command accepts one or more arguments, which are keywords and attributes, that change how **plug.kak** behaves.

The first strict rule of the `plug` command is that the first argument is always the plugin name formatted as in GitHub URL: `"author/repository"`.

``` kak
plug "author/repository"
```

By default **plug.kak** will look for the plugin at GitHub.com and download it.
When the plugin is hosted on a different service, a URL can be used as the first argument.
So, in most cases, it is enough to add this to the `kakrc` to use a plugin:

```kak
plug "delapouite/kakoune-text-objects"
```

Or with URL:

```kak
plug "https://gitlab.com/Screwtapello/kakoune-inc-dec"
```

After adding this, `kakrc` needs to be re-sourced to let **plug.kak** know that the configuration was changed.
Alternatively, Kakoune can be restarted.
After that, newly added plugins can be installed with the `plug-install` command.
More information about other commands available in the [Commands](#Commands) section.


### Keywords and attributes

The `plug` command accepts optional attributes that change how **plug.kak** works, or add additional steps for `plug` to perform.

These keywords are supported:

- [branch, tag, commit](#branch-tag-or-commit)
- [load-path](#loading-plugin-from-a-different-path)
- [noload](#skipping-loading-of-a-plugin)
- [do](#automatically-do-certain-tasks-on-install-or-update)
- [theme](#installing-color-schemes)
- [config](#handling-user-configurations)
- [defer](#deferring-plugin-configuration)
- [demand](#demanding-plugin-module-configuration)
- [ensure](#ensuring-that-plugins-are-installed)


#### Branch, Tag, or Commit

`plug` can checkout a plugin to the desired branch, commit, or tag before loading it.
It can be done by adding the following keywords with parameters: `branch "branch_name"`, `tag "tag_name"` or `commit "commit_hash"`.


#### Loading plugin from a different path

Plugins can be loaded from an arbitrary path by specifying the `load-path` keyword and providing the path as an argument:

``` kak
plug "plugin_name" load-path "~/Development/plugin_dir"
```

However, all `plug` related commands, like `plug-update` or `plug-clean`, will not work for plugins that aren't installed to `plug_install_dir`.


#### Skipping loading of a plugin

If a plugin needs to be loaded manually, the `noload` keyword can be used.
This can also be used to avoid loading the plugin a second time, like in the example with **plug.kak** from the [installation](#installation) section:

```kak
source "%val{config}/plugins/plug.kak/rc/plug.kak"
plug "andreyorst/plug.kak" noload
```

Note that plugins with the `noload` keyword are still configured and managed.
See [handling-user-configuration](#handling-user-configurations) for more details.


#### Automatically do certain tasks on install or update

When the plugin requires some additional steps to perform after installation or update, the `do` keyword can be used.
This keyword expects the body, which will be executed in the shell. 
Thus, it can only contain shell commands, not Kakoune commands.

```kak
plug "ul/kak-lsp" do %{
    cargo build --release --locked
    cargo install --force --path .
}
```

In the example above **plug.kak** will run these `cargo` commands after `kak-lsp` was installed or updated.

**Note** that even though this is technically a shell expansion, the `%sh{}` expansion can't be used with `do`, as it will be evaluated immediately each time `kakrc` is loaded.
Use `%{}` instead.


#### Installing color schemes

To register the plugin as a color scheme, use `theme` keyword.
Such plugins will be copied to the `%val{config}/colors` directory.

```kak
plug "andreyorst/base16-gruvbox.kak" theme config %{
    colorscheme base16-gruvbox-dark-soft
}
```


#### Ensuring that plugins are installed

`plug` command can be explicitly told to install the plugin automatically with the `ensure` keyword.
The `plug_always_ensure` option can be set to `true` to perform this for each and every plugin specified in the `kakrc`.

Note that `ensure` plugins are installed (if missing) in a background job; they are then only loaded when the install finishes.
Thus, subsequent `kakrc` commands should not depend on functionality provided by such plugins.
Only use `ensure` with non-essential plugins, which are not required for `kakrc` to complete loading.


#### Handling user configurations

The configuration of the plugin is performed only when the plugin is installed.
There's a second strict rule of `plug` command: every parameter that doesn't have a keyword before it, is treated as plugin configuration.
For example:

```kak
plug "andreyorst/fzf.kak" config %{
    map -docstring 'fzf mode' global normal '<c-p>' ': fzf-mode<ret>'
}
```

Here, `plug` will map <kbd>Ctrl</kbd>+<kbd>p</kbd> key only if the plugin is installed.
Everything within the `config %{}` block is an ordinary kakscript.

The `config` keyword is optional, and can be skipped.
Multiple `config` blocks are also supported.


#### Commenting out `plug` options

It may be tricky to "toggle" `plug` options, for debugging or testing purposes, because it is impossible to continue a command past a `#...` comment (also, `config` blocks usually span multiple lines).
To solve this, `plug` supports a `comment` keyword that ignores its next argument.
For example, to toggle a `load-path` option, wrap it in `comment %{}`; then remove the "wrapper" to turn it back on (without having to re-type the full path):
```kak
plug "andreyorst/fzf.kak" comment %{load-path /usr/local/src/fzf} config %{
    # ...
}
```


### Deferring plugin configuration

With the introduction of the module system, some configurations have to be preformed after loading the module.
The `defer` keyword is a shorthand to register a `ModuleLoaded` hook for given `module`.
You need to **`require` the module explicitly** elsewhere.

Below is the configuration of [fzf.kak](https://github.com/andreyorst/fzf.kak) plugin, which provides the `fzf` module:

```kak
plug "andreyorst/fzf.kak" config %{
    map -docstring 'fzf mode' global normal '<c-p>' ': fzf-mode<ret>'
} defer fzf %{
    set-option global fzf_preview_width '65%'
    set-option global fzf_project_use_tilda true
}
```

**Note**: the `ModuleLoaded` hook is defined as early as possible - before sourcing any of plugin files.

### Demanding plugin module configuration

Works the same as `defer` except requires the module immediately:

```kak
plug "andreyorst/fzf.kak" config %{
    # config1 (evaluated before demanding the module)
} demand fzf %{
    # demand block (will generate `require-modlue fzf` call, and a respective hook)
    set-option global fzf_project_use_tilda true
} config %{
    # config2 (evaluated after demanding the module)
}
```

The above snippet is a shorthand for this code:

``` kak
plug "andreyorst/fzf.kak" defer fzf %{
    # the body of demand block
    set-option global fzf_project_use_tilda true # demand block
} config %{
    # config1 (evaluated before demanding the module)
    require-module fzf # the demand hook
    # config2 (evaluated after demanding the module)
}
```

**Note**: the `ModuleLoaded` hook is defined as early as possible - before sourcing any of plugin files.
The place where `require-module` call will be placed depends on the order of config blocks in the `plug` command.
As soon as the module is required, the `ModuleLoaded` hook will execute.


## **plug.kak** Configuration

Several configuration options are available:

- Changing the [plugin installation directory](#plugin-installation-directory),
- Limiting the [maximum amount of active downloads](#maximum-downloads),
- Specifying the [default git domain](#default-git-domain),
- And [ensuring that plugins are installed](#ensuring-that-plugins-are-installed).

Proper way to configure **plug.kak** is to load it with the `plug` command, and providing both `noload` and `config` blocks:
This should be done before loading other plugins.

```kak
plug "andreyorst/plug.kak" noload config %{
    # configure plug.kak here
}
```


### Plugin installation directory

By default **plug.kak** automatically detects its installation path and installs plugins to the same directory.
To change this, use the `plug_install_dir` option:

```kak
plug "andreyorst/plug.kak" noload config %{
    set-option global plug_install_dir %sh{ echo $HOME/.cache/kakoune_plugins }
}
```


### Maximum downloads

**plug.kak** downloads plugins from github.com asynchronously via `git`.
By default it allows only `10` simultaneously active `git` processes.
To change this, use the `plug_max_simultaneous_downloads` option.


### Default git domain

If majority of plugins is installed from the service other than GitHub, default git domain can be changed to avoid specifying the `domain` keyword for each plugin, or using URLs.


### Notify on configuration error

By default, **plug.kak** will display an `info` box when any plugin's `config` block has errors while being evaluated.
To change this, use the `plug_report_conf_errors` option:

```kak
set-option global plug_report_conf_errors false
```


## Commands

**plug.kak** adds five new commands to Kakoune.


### `plug-install`

This command installs all plugins that were specified in any of the configuration files sourced after Kakoune launch.
It accepts optional argument, which can be the plugin name or the URL, so it could be used to install a plugin from command prompt without restarting Kakoune.
This plugin will be enabled automatically, but you still need to add `plug` command to your configuration files in order to use that plugin after the restart.


### `plug-list`

Display the buffer with all installed plugins, and check for updates.
The <kbd>Enter</kbd> key is remapped to execute `plug-update` or `plug-install` command for selected plugin, depending on its state.
This command accepts an optional argument `noupdate`, and if it is specified, check for updates will not be performed.


### `plug-update`

This command updates all installed plugins.
It accepts one optional argument, which is a plugin name, so it could be used to update single plugin.
When called from prompt, it shows all installed plugins in the completion menu.


### `plug-clean`

Remove plugins, that are installed, but disabled or missing in configuration files.
This command also accepts optional argument, which is a plugin name, and can be used to remove any installed plugin.


### `plug`

Load plugin from plugin installation directory by its name.


### `plug-chain`

This command can collapse separate `plug` invocations and thus saves startup time by reducing multiple shell calls; it may come in handy if you're invoking `kak` frequently (e.g. as the `$EDITOR`). Replace the first `plug` command in your `kakrc` with `plug-chain`, then append subsequent `plug` calls and their parameters, as in the following:
```
plug-chain https://github.com/Delapouite/kakoune-select-view config %{
  map global view s '<esc>: select-view<ret>' -docstring 'select view'
} plug https://github.com/occivink/kakoune-vertical-selection %{
} plug https://github.com/jbomanson/search-doc.kak demand search-doc %{
  alias global doc-search search-doc
}
```

Backslashes can also be used to separate individual `plug` "clauses" (which avoids the "visual hack" of empty config blocks, as above, serving as newlines).
An initial `plug` redundant argument is also supported for symmetry.
Either way, `plug-chain` simply figures out the parameters intended for each individual `plug` clause (using "`plug`" as a delimiter), and executes all implied `plug`s in a single shell call.
All regular `plug` features are supported.
Mix and match `plug` / `plug-chain` invocations in any order, any number of times.

Note, that if plug.kak own variables are altered in the `plug-chain` body, the chained `plug` commands won't get updated values.
This happens because Kakoune reads its variables only once per shell invocation, and calling `set-option` won't update the value of a variable for current shell.


### Alternative plugin managers

Here are some other plugin managers to consider as alternatives to plug.kak:

- [kak-bundle][7]
- [cork.kak][8]

[1]: https://img.shields.io/github/issues/andreyorst/plug.kak.svg
[2]: https://github.com/andreyorst/plug.kak/issues
[3]: https://img.shields.io/github/license/andreyorst/plug.kak.svg
[4]: https://user-images.githubusercontent.com/19470159/51197223-f2c26a80-1901-11e9-9494-b79ce823a364.png
[5]: https://github.com/junegunn/vim-plug
[6]: https://github.com/jwiegley/use-package
[7]: https://github.com/jdugan6240/kak-bundle
[8]: https://github.com/topisani/cork.kak

<!--  LocalWords:  kak Kakoune Kakoune's GitLab Gitea noload config
      LocalWords:  kakscript kbd Ctrl github fzf
 -->


================================================
FILE: rc/plug.kak
================================================
# Author: Andrey Listopadov
# plug.kak is a plugin manager for Kakoune. It can install plugins, keep them updated, configure and build dependencies
# https://github.com/andreyorst/plug.kak

# Public options
declare-option -docstring \
"Path where plugins should be installed.

    Defaults to the plug.kak installation directory" \
str plug_install_dir %sh{ echo "${kak_source%%/rc*}/../" }

declare-option -docstring \
"Default domain to access git repositories. Can be changed to any preferred domain, like gitlab, bitbucket, gitea, etc.

    Default value: 'https://github.com'" \
str plug_git_domain 'https://github.com'

declare-option -docstring \
"Profile plugin loading." \
bool plug_profile false

declare-option -docstring \
"Maximum amount of simultaneously active downloads when installing or updating all plugins
    Default value: 10
" \
int plug_max_active_downloads 10

declare-option -docstring \
"Always ensure that all plugins are installed. If this option specified, all uninstalled plugins are being installed when Kakoune starts." \
bool plug_always_ensure false

declare-option -docstring "name of the client in which utilities display information" \
str toolsclient

declare-option -docstring \
"Block UI until operation completes." \
bool plug_block_ui false

# Private options
declare-option -hidden -docstring \
"Path to plug.sh script." \
str plug_sh_source %sh{ echo "${kak_source%%.kak}.sh" }

declare-option -hidden -docstring \
"Array of all plugins, mentioned in any configuration file.
Empty by default, and erased on reload of main Kakoune configuration, to track if some plugins were disabled
Should not be modified by user." \
str plug_plugins ""

declare-option -hidden -docstring \
"List of loaded plugins. Has no default value.
Should not be cleared during update of configuration files. Should not be modified by user." \
str plug_loaded_plugins ""

declare-option -docstring \
"Whether or not to report errors in config blocks. Defaults to true." \
bool plug_report_conf_errors true

declare-option -hidden -docstring \
"This will be set if there are any errors with a plugin's config block. Has no default value.
Should not be cleared during update of configuration files. Should not be modified by user." \
str plug_conf_errors ""

# since we want to add highlighters to kak filetype we need to require kak module
# using `try' here since kakrc module may not be available in rare cases
try %@
    require-module kak

    try %$
        add-highlighter shared/kakrc/code/plug_keywords   regex '\b(plug|plug-chain|do|config|domain|defer|demand|load-path|branch|tag|commit|comment)(?=[ \t])' 0:keyword
        add-highlighter shared/kakrc/code/plug_attributes regex '(?<=[ \t])(noload|ensure|theme)\b' 0:attribute
        add-highlighter shared/kakrc/plug_post_hooks1     region -recurse '\{' '\bdo\K\h+%\{' '\}' ref sh
        add-highlighter shared/kakrc/plug_post_hooks2     region -recurse '\[' '\bdo\K\h+%\[' '\]' ref sh
        add-highlighter shared/kakrc/plug_post_hooks3     region -recurse '\(' '\bdo\K\h+%\(' '\)' ref sh
        add-highlighter shared/kakrc/plug_post_hooks4     region -recurse '<'  '\bdo\K\h+%<'  '>'  ref sh
    $ catch %$
        echo -debug "Error: plug.kak: can't declare highlighters for 'kak' filetype: %val{error}"
    $
@ catch %{
    echo -debug "Error: plug.kak: can't require 'kak' module to declare highlighters for plug.kak. Check if kakrc.kak is available in your autoload."
}

# *plug* highlighters
try %{
    add-highlighter shared/plug_buffer group
    add-highlighter shared/plug_buffer/done          regex [^:]+:\h+(Up\h+to\h+date|Done|Installed)$                    1:string
    add-highlighter shared/plug_buffer/update        regex [^:]+:\h+(Update\h+available|Deleted)$                       1:keyword
    add-highlighter shared/plug_buffer/not_installed regex [^:]+:\h+(Not\h+(installed|loaded)|(\w+\h+)?Error([^\n]+)?)$ 1:red+b
    add-highlighter shared/plug_buffer/updating      regex [^:]+:\h+(Installing|Updating|Local\h+changes)$              1:type
    add-highlighter shared/plug_buffer/working       regex [^:]+:\h+(Running\h+post-update\h+hooks|Waiting[^\n]+)$      1:attribute
} catch %{
    echo -debug "Error: plug.kak: Can't declare highlighters for *plug* buffer: %val{error}"
}

hook -group plug-syntax global WinSetOption filetype=plug %{
    add-highlighter buffer/plug_buffer ref plug_buffer
    hook -always -once window WinSetOption filetype=.* %{
        remove-highlighter buffer/plug_buffer
    }
}

define-command -override -docstring \
"plug <plugin> [<switches>]: manage <plugin> from ""%opt{plug_install_dir}""
Switches:
    branch (tag, commit) <str>      checkout to <str> before loading plugin
    noload                          do not source plugin files
    subset <subset>                 source only <subset> of plugin files
    load-path <path>                path for loading plugin from foreign location
    defer <module> <configurations> load plugin <configurations> only when <module> is loaded
    config <configurations>         plugin <configurations>" \
plug -params 1.. -shell-script-candidates %{ ls -1 ${kak_opt_plug_install_dir} } %{ try %{
    evaluate-commands %sh{
        # $kak_client
        # $kak_config
        # $kak_opt_plug_always_ensure
        # $kak_opt_plug_git_domain
        # $kak_opt_plug_install_dir
        # $kak_opt_plug_loaded_plugins
        # $kak_opt_plug_max_active_downloads
        # $kak_opt_plug_plugin
        # $kak_opt_plug_plugins
        # $kak_opt_plug_profile
        # $kak_opt_plug_block_ui
        # $kak_opt_plug_report_conf_errors
        # $kak_opt_plug_conf_errors
        # $kak_session

        . "${kak_opt_plug_sh_source}"
        plug "$@"
    }
}}

define-command -override plug-chain -params 0.. -docstring %{
  Chain plug commands (see docs, saves startup time by reducing sh calls)
} %{ try %{
    evaluate-commands %sh{
        # $kak_client
        # $kak_config
        # $kak_opt_plug_always_ensure
        # $kak_opt_plug_git_domain
        # $kak_opt_plug_install_dir
        # $kak_opt_plug_loaded_plugins
        # $kak_opt_plug_max_active_downloads
        # $kak_opt_plug_plugin
        # $kak_opt_plug_plugins
        # $kak_opt_plug_profile
        # $kak_opt_plug_block_ui
        # $kak_opt_plug_report_conf_errors
        # $kak_opt_plug_conf_errors
        # $kak_session

        set -u
        . "${kak_opt_plug_sh_source}"
        plug1() {
          for _plug_param; do
            # reset "$@" on 1st iteration; args still in 'for'
            [ "$_plug_processed_args" != 0 ] || set --
            _plug_processed_args=$((_plug_processed_args + 1))
            [ plug != "$_plug_param" ] || break
            set -- "$@" "$_plug_param"
          done
          [ $# = 0 ] || plug "$@"  # subshell would be safer, but slower
        }
        while [ "$#" != 0 ]; do
          _plug_processed_args=0
          plug1 "$@"
          shift "$_plug_processed_args"
        done
    }
}}

define-command -override -docstring \
"plug-install [<plugin>] [<noload>]: install <plugin>.
If <plugin> omitted installs all plugins mentioned in configuration
files.  If <noload> is supplied skip loading the plugin." \
plug-install -params ..2 %{ nop %sh{
    # $kak_client
    # $kak_config
    # $kak_opt_plug_always_ensure
    # $kak_opt_plug_git_domain
    # $kak_opt_plug_install_dir
    # $kak_opt_plug_loaded_plugins
    # $kak_opt_plug_max_active_downloads
    # $kak_opt_plug_plugin
    # $kak_opt_plug_plugins
    # $kak_opt_plug_profile
    # $kak_opt_plug_block_ui
    # $kak_opt_plug_report_conf_errors
    # $kak_opt_plug_conf_errors
    # $kak_session

    . "${kak_opt_plug_sh_source}"
    plug_install "$@"
}}

define-command -override -docstring \
"plug-update [<plugin>]: Update plugin.
If <plugin> omitted all installed plugins are updated" \
plug-update -params ..1 -shell-script-candidates %{ printf "%s\n" ${kak_opt_plug_plugins} | tr ' ' '\n' } %{
    evaluate-commands %sh{
        # $kak_client
        # $kak_config
        # $kak_opt_plug_always_ensure
        # $kak_opt_plug_git_domain
        # $kak_opt_plug_install_dir
        # $kak_opt_plug_loaded_plugins
        # $kak_opt_plug_max_active_downloads
        # $kak_opt_plug_plugin
        # $kak_opt_plug_plugins
        # $kak_opt_plug_profile
        # $kak_opt_plug_block_ui
        # $kak_opt_plug_report_conf_errors
        # $kak_opt_plug_conf_errors
        # $kak_session

        . "${kak_opt_plug_sh_source}"
        plug_update "$@"
}}

define-command -override -docstring \
"plug-clean [<plugin>]: delete <plugin>.
If <plugin> omitted deletes all plugins that are installed but not presented in configuration files" \
plug-clean -params ..1 -shell-script-candidates %{ ls -1 ${kak_opt_plug_install_dir} } %{ nop %sh{
    # $kak_client
    # $kak_config
    # $kak_opt_plug_always_ensure
    # $kak_opt_plug_git_domain
    # $kak_opt_plug_install_dir
    # $kak_opt_plug_loaded_plugins
    # $kak_opt_plug_max_active_downloads
    # $kak_opt_plug_plugin
    # $kak_opt_plug_plugins
    # $kak_opt_plug_profile
    # $kak_opt_plug_block_ui
    # $kak_opt_plug_report_conf_errors
    # $kak_opt_plug_conf_errors
    # $kak_session

    . "${kak_opt_plug_sh_source}"
    plug_clean "$@"
}}

define-command -override -hidden \
-docstring "plug-eval-hooks: wrapper for post update/install hooks" \
plug-eval-hooks -params 1 %{ nop %sh{
    # $kak_client
    # $kak_config
    # $kak_opt_plug_always_ensure
    # $kak_opt_plug_git_domain
    # $kak_opt_plug_install_dir
    # $kak_opt_plug_loaded_plugins
    # $kak_opt_plug_max_active_downloads
    # $kak_opt_plug_plugin
    # $kak_opt_plug_plugins
    # $kak_opt_plug_profile
    # $kak_opt_plug_block_ui
    # $kak_opt_plug_report_conf_errors
    # $kak_opt_plug_conf_errors
    # $kak_session

    . "${kak_opt_plug_sh_source}"
    plug_eval_hooks "$@"
}}

define-command -override \
-docstring "plug-list [<noupdate>]: list all installed plugins in *plug* buffer. Checks updates by default unless <noupdate> is specified." \
plug-list -params ..1 %{ evaluate-commands -try-client %opt{toolsclient} %sh{
    # $kak_client
    # $kak_config
    # $kak_opt_plug_always_ensure
    # $kak_opt_plug_git_domain
    # $kak_opt_plug_install_dir
    # $kak_opt_plug_loaded_plugins
    # $kak_opt_plug_max_active_downloads
    # $kak_opt_plug_plugin
    # $kak_opt_plug_plugins
    # $kak_opt_plug_profile
    # $kak_opt_plug_block_ui
    # $kak_opt_plug_report_conf_errors
    # $kak_opt_plug_conf_errors
    # $kak_session

    . "${kak_opt_plug_sh_source}"
    plug_list "$@"
}}

define-command -hidden -override \
-docstring "operate on *plug* buffer contents based on current cursor position" \
plug-fifo-operate -params 1 %{ evaluate-commands -save-regs t %{
    execute-keys -save-regs '' "<a-h><a-l>"
    set-register t %val{selection}
    evaluate-commands %sh{
    # $kak_reg_t
    # $kak_client
    # $kak_config
    # $kak_opt_plug_always_ensure
    # $kak_opt_plug_git_domain
    # $kak_opt_plug_install_dir
    # $kak_opt_plug_loaded_plugins
    # $kak_opt_plug_max_active_downloads
    # $kak_opt_plug_plugin
    # $kak_opt_plug_plugins
    # $kak_opt_plug_profile
    # $kak_opt_plug_block_ui
    # $kak_opt_plug_report_conf_errors
    # $kak_opt_plug_conf_errors
    # $kak_session

    . "${kak_opt_plug_sh_source}"
    plug_fifo_operate "$@"
}}}

define-command -hidden -override \
plug-display-log -params 1 %{ evaluate-commands %sh{
    plugin_log="${TMPDIR:-/tmp}/${1##*/}-log"
    [ -s "${plugin_log}" ] && printf "%s\n" "edit! -existing -debug -readonly -scroll %{${plugin_log}}"
}}

define-command -override \
-docstring "displays help message" \
plug-show-help %{
    info -title "plug.kak Help" "h,j,k,l: Move
<ret>:   Update or Install plugin
I:       Install plugin
U:       Update plugin
D:       clean (Delete) plugin
L:       show Log, if any
R:       Run post-update hooks manually
H        show Help message"
}


================================================
FILE: rc/plug.sh
================================================
#!/usr/bin/env sh

# Author: Andrey Listopadov
# https://github.com/andreyorst/plug.kak
#
# plug.kak is a plugin manager for Kakoune. It can install plugins,
# keep them updated, configure and build dependencies.
#
# plug.sh contains a set of functions plug.kak calls via shell
# expansions.

plug_code_append () {
    eval "$1=\"\$$1
\$2\""
}

plug () {
    [ "${kak_opt_plug_profile:-}" = "true" ] && plug_save_timestamp profile_start
    plugin_arg=$1
    plugin="${1%%.git}"; plugin=${plugin%%/}
    shift
    plugin_name="${plugin##*/}"
    path_to_plugin="${kak_opt_plug_install_dir:?}/$plugin_name"
    build_dir="${kak_opt_plug_install_dir:?}/.build/$plugin_name"
    conf_file="$build_dir/config"
    hook_file="$build_dir/hooks"
    domain_file="$build_dir/domain"

    configurations= hooks= domain= checkout= checkout_type= noload= ensure=

    case "${kak_opt_plug_loaded_plugins:-}" in
      (*"$plugin"*)
        printf "%s\n" "echo -markup %{{Information}$plugin_name already loaded}"
        exit
        ;;
      (*)
        printf "%s\n" "set-option -add global plug_plugins %{$plugin }"
        ;;
    esac

    while [ $# -gt 0 ]; do
        case $1 in
            (branch|tag|commit) checkout_type=$1; shift; checkout=${1?} ;;
            (noload) noload=1 ;;
            (load-path) shift; eval "path_to_plugin=${1?}" ;;
            (comment) shift ;;
            (defer|demand)
                demand=$1
                shift; module=${1?}
                if [ $# -ge 2 ]; then
                    case "$2" in
                        (branch|tag|commit|noload|load-path|ensure|theme|domain|depth-sort|subset|no-depth-sort|config|defer|demand|comment)
                        ;;
                        (*)
                            shift
                            deferred=$1
                            case "$deferred" in (*[![:space:]]*)
                                case "$deferred" in (*'@'*)
                                    deferred=$(printf "%s\n" "$deferred" | sed "s/@/@@/g") ;;
                                esac
                                printf "%s\n" "hook global ModuleLoaded '$module' %@ $deferred @"
                            esac
                            [ "$demand" = demand ] && plug_code_append configurations "require-module $module" ;;
                    esac
                fi
                ;;
            ('do') shift; plug_code_append hooks "set -e
${1?}" ;;
            (ensure) ensure=1 ;;
            (theme)
                noload=1
                plug_code_append hooks "[ -d \"${kak_config:?}/colors\" ] || mkdir -p \"${kak_config}/colors\"; ln -sf \"\$PWD\" \"$kak_config/colors\""
            ;;
            (domain) shift; domain=${1?} ;;
            (depth-sort|subset)
                printf "%s\n" "echo -debug %{Error: plug.kak: '$plugin_name': keyword '$1' is no longer supported. Use the module system instead}"
                exit 1 ;;
            (no-depth-sort) printf "%s\n" "echo -debug %{Warning: plug.kak: '$plugin_name': use of deprecated '$1' keyword which has no effect}" ;;
            (config) shift; plug_code_append configurations "${1?}" ;;
            (*) plug_code_append configurations "$1" ;;
        esac
        shift
    done

    [ -d "$build_dir" ] || mkdir -p "$build_dir"
    rm -rf "$build_dir"/* "$build_dir"/.[!.]* "$build_dir"/..?*
    [ -n "$hooks" ] && printf "%s" "$hooks" > "$hook_file"
    [ -n "$domain" ] && printf "%s" "$domain" > "$domain_file"

    if [ -n "$configurations" ]; then
        if [ "${kak_opt_plug_report_conf_errors:-}" = "true" ]; then
            cat > "$conf_file" <<ERRHANDLE
try %{ $configurations } catch %{
    echo -debug "Error while evaluating '$plugin_name' configuration: %val{error}"

    set-option -add current plug_conf_errors "Error while evaluating '$plugin_name' configuration:"
    set-option -add current plug_conf_errors %sh{ printf "\n    " }
    set-option -add current plug_conf_errors %val{error}
    set-option -add current plug_conf_errors %sh{ printf "\n\n" }

    hook -once -group plug-conf-err global WinDisplay .* %{
        info -style modal -title "plug.kak error" "%opt{plug_conf_errors}"
        on-key %{
            info -style modal
            execute-keys -with-maps -with-hooks %val{key}
        }
    }
}
ERRHANDLE
        else
          printf "%s" "$configurations" > "$conf_file"
        fi
    fi

    if [ -d "$path_to_plugin" ]; then
        if [ -n "$checkout" ]; then
            (
                cd "$path_to_plugin" || exit
                # shellcheck disable=SC2030,SC2031
                [ -z "${GIT_TERMINAL_PROMPT:-}" ] && export GIT_TERMINAL_PROMPT=0
                if [ "$checkout_type" = "branch" ]; then
                    [ "$(git branch --show-current)" != "$checkout" ] && git fetch >/dev/null 2>&1
                fi
                git checkout "$checkout" >/dev/null 2>&1
            )
        fi
        plug_load "$plugin" "$path_to_plugin" "$noload"
        if  [ "$kak_opt_plug_profile" = "true" ]; then
            plug_save_timestamp profile_end
            profile_time=$(echo "scale=3; x=($profile_end-$profile_start)/1000; if(x<1) print 0; x" | bc -l)
            printf "%s\n" "echo -debug %{'$plugin_name' loaded in $profile_time sec}"
        fi
    else
        if [ -n "$ensure" ] || [ "${kak_opt_plug_always_ensure:-}" = "true" ]; then
            (
                plug_install "$plugin_arg" "$noload"
                wait
                if  [ "$kak_opt_plug_profile" = "true" ]; then
                    plug_save_timestamp profile_end
                    profile_time=$(echo "scale=3; x=($profile_end-$profile_start)/1000; if(x<1) print 0; x" | bc -l)
                    printf "%s\n" "echo -debug %{'$plugin_name' loaded in $profile_time sec}" | kak -p "${kak_session:?}"
                fi
            ) > /dev/null 2>&1 < /dev/null &
        fi
    fi
}

plug_install () {
    (
        plugin="${1%%.git}"; plugin=${plugin%%/}
        noload=$2
        plugin_name="${plugin##*/}"
        build_dir="${kak_opt_plug_install_dir:?}/.build/$plugin_name"
        domain_file="$build_dir/domain"

        # shellcheck disable=SC2030,SC2031
        [ -z "${GIT_TERMINAL_PROMPT:-}" ] && export GIT_TERMINAL_PROMPT=0

        if [ ! -d "${kak_opt_plug_install_dir}" ]; then
            if ! mkdir -p "${kak_opt_plug_install_dir}" >/dev/null 2>&1; then
                printf "%s\n" "evaluate-commands -client ${kak_client:-client0} echo -debug 'Error: plug.kak: unable to create directory for plugins'" | kak -p "${kak_session:?}"
                exit
            fi
        fi

        printf "%s\n" "evaluate-commands -client ${kak_client:-client0} %{ try %{ buffer *plug* } catch %{ plug-list noupdate } }" | kak -p "${kak_session}"
        sleep 0.3

        lockfile="${kak_opt_plug_install_dir}/.${plugin_name:-global}.plug.kak.lock"
        if [ -d "${lockfile}" ]; then
            plug_fifo_update "${plugin_name}" "Waiting for .plug.kak.lock"
        fi

        # this creates the lock file for a plugin, if specified to
        # prevent several processes of installation of the same
        # plugin, but will allow install different plugins without
        # waiting for each other.  Should be fine, since different
        # plugins doesn't interfere with each other.
        while ! mkdir "${lockfile}" 2>/dev/null; do sleep 1; done
        # shellcheck disable=SC2064
        trap "rmdir '${lockfile}'" EXIT

        # if plugin specified as an argument add it to the *plug*
        # buffer, if it isn't there already otherwise update all
        # plugins
        if [ -n "${plugin}" ]; then
            plugin_list=${plugin}
            printf "%s\n" "
                evaluate-commands -buffer *plug* %{ try %{
                    execute-keys /${plugin}<ret>
                } catch %{
                    execute-keys gjO${plugin}:<space>Not<space>installed<esc>
                }}" | kak -p "${kak_session}"
            sleep 0.2
        else
            plugin_list=${kak_opt_plug_plugins}
        fi

        for plugin in ${plugin_list}; do
            plugin_name="${plugin##*/}"
            [ -e "$domain_file" ] && git_domain="https://$(cat "$domain_file")" || git_domain=${kak_opt_plug_git_domain:?}
            if [ ! -d "${kak_opt_plug_install_dir}/${plugin_name}" ]; then
                (
                    plugin_log="${TMPDIR:-/tmp}/${plugin_name}-log"
                    printf "%s\n" "hook global -always KakEnd .* %{ nop %sh{rm -rf \"$plugin_log\"}} " | kak -p "${kak_session}"
                    plug_fifo_update "${plugin_name}" "Installing"
                    cd "${kak_opt_plug_install_dir}" || exit
                    case ${plugin} in
                        (https://*|http://*|*@*|file://*|ext::*)
                            git clone --recurse-submodules "${plugin}" "$plugin_name" >> "$plugin_log" 2>&1 ;;
                        (*)
                            git clone --recurse-submodules "$git_domain/$plugin" "$plugin_name" >> "$plugin_log" 2>&1 ;;
                    esac
                    status=$?
                    if [ ${status} -ne 0 ]; then
                        plug_fifo_update "$plugin_name" "Download Error ($status)"
                    else
                        plug_eval_hooks "$plugin_name"
                        wait
                        plug_load "$plugin" "${kak_opt_plug_install_dir:?}/$plugin_name" "$noload" | kak -p "${kak_session:?}"
                    fi
                ) > /dev/null 2>&1 < /dev/null &
            fi
            # this is a hacky way to measure amount of active
            # processes. We need this because dash shell has this long
            # term bug:
            # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=482999
            jobs=$(mktemp "${TMPDIR:-/tmp}"/plug.kak.jobs.XXXXXX)
            jobs > "${jobs}"; active=$(wc -l < "${jobs}")
            while [ "${active}" -ge "${kak_opt_plug_max_active_downloads:?}" ]; do
                sleep 1
                jobs > "${jobs}"; active=$(wc -l < "${jobs}")
            done
            rm -rf "${jobs}"
        done
        wait
    ) > /dev/null 2>&1 < /dev/null &
}

plug_load() {
    plugin="${1%%.git}"
    path_to_plugin=$2
    noload=$3
    plugin_name="${plugin##*/}"
    build_dir="${kak_opt_plug_install_dir:?}/.build/$plugin_name"
    conf_file="$build_dir/config"

    if [ -z "${noload}" ]; then
        find -L "${path_to_plugin}" -path '*/.git' -prune -o -type f -name '*.kak' -exec printf 'source "%s"\n' {} +
    fi
    [ -e "$conf_file" ] && printf "%s\n" "source $conf_file"
    printf "%s\n" "set-option -add global plug_loaded_plugins %{${plugin} }"
}

plug_update () {
    (
        plugin="${1%%.git}"
        plugin_name="${plugin##*/}"

        # shellcheck disable=SC2030,SC2031
        [ -z "${GIT_TERMINAL_PROMPT:-}" ] && export GIT_TERMINAL_PROMPT=0

        printf "%s\n" "evaluate-commands -client ${kak_client:-client0} %{ try %{ buffer *plug* } catch %{ plug-list noupdate } }" | kak -p "${kak_session}"

        lockfile="${kak_opt_plug_install_dir}/.${plugin_name:-global}.plug.kak.lock"
        if [ -d "${lockfile}" ]; then
            plug_fifo_update "${plugin##*/}" "Waiting for .plug.kak.lock"
        fi

        while ! mkdir "${lockfile}" 2>/dev/null; do sleep 1; done
        # shellcheck disable=SC2064
        trap "rmdir '${lockfile}'" EXIT

        [ -n "${plugin}" ] && plugin_list=${plugin} || plugin_list=${kak_opt_plug_plugins}
        for plugin in ${plugin_list}; do
            plugin_name="${plugin##*/}"
            if [ -d "${kak_opt_plug_install_dir}/${plugin_name}" ]; then
                (
                    plugin_log="${TMPDIR:-/tmp}/${plugin_name}-log"
                    printf "%s\n" "hook global -always KakEnd .* %{ nop %sh{rm -rf ${plugin_log}}} " | kak -p "${kak_session}"
                    plug_fifo_update "${plugin_name}" "Updating"
                    cd "${kak_opt_plug_install_dir}/${plugin_name}" && rev=$(git rev-parse HEAD) && git pull --recurse-submodules >> "${plugin_log}" 2>&1
                    status=$?
                    if [ ${status} -ne 0 ]; then
                        plug_fifo_update "${plugin_name}" "Update Error (${status})"
                    else
                        if [ "${rev}" != "$(git rev-parse HEAD)" ]; then
                            printf "%s\n" "evaluate-commands -client ${kak_client:-client0} plug-eval-hooks ${plugin_name}" | kak -p "${kak_session}"
                        else
                            plug_fifo_update "${plugin_name}" "Done"
                        fi
                    fi
                ) > /dev/null 2>&1 < /dev/null &
            fi
            jobs=$(mktemp "${TMPDIR:-/tmp}"/jobs.XXXXXX)
            jobs > "${jobs}"; active=$(wc -l < "${jobs}")
            # TODO: re-check this
            # For some reason I need to multiply the amount of jobs by five here.
            while [ "${active}" -ge $((kak_opt_plug_max_active_downloads * 5)) ]; do
                sleep 1
                jobs > "${jobs}"; active=$(wc -l < "${jobs}")
            done
            rm -rf "${jobs}"
        done
        wait
    ) > /dev/null 2>&1 < /dev/null &

    if [ "${kak_opt_plug_block_ui:-}" = "true" ]; then
        wait
    fi
}


plug_clean () {
    (
        plugin="${1%%.git}"
        plugin_name="${plugin##*/}"

        printf "%s\n" "evaluate-commands -client ${kak_client:-client0} %{ try %{ buffer *plug* } catch %{ plug-list noupdate } }" | kak -p "${kak_session}"

        lockfile="${kak_opt_plug_install_dir}/.${plugin_name:-global}.plug.kak.lock"
        if [ -d "${lockfile}" ]; then
            plug_fifo_update "${plugin_name}" "Waiting for .plug.kak.lock"
        fi

        while ! mkdir "${lockfile}" 2>/dev/null; do sleep 1; done
        # shellcheck disable=SC2064
        trap "rmdir '${lockfile}'" EXIT

        if [ -n "${plugin}" ]; then
            if [ -d "${kak_opt_plug_install_dir}/${plugin_name}" ]; then
                (
                    cd "${kak_opt_plug_install_dir}" && rm -rf "${plugin_name}"
                    plug_fifo_update "${plugin_name}" "Deleted"
                )
            else
                printf "%s\n" "evaluate-commands -client ${kak_client:-client0} echo -markup %{{Error}No such plugin '${plugin}'}" | kak -p "${kak_session}"
                exit
            fi
        else
            for installed_plugin in $(printf "%s\n" "${kak_opt_plug_install_dir}"/*); do
                skip=
                for enabled_plugin in ${kak_opt_plug_plugins}; do
                    [ "${installed_plugin##*/}" = "${enabled_plugin##*/}" ] && { skip=1; break; }
                done
                [ "${skip}" = "1" ] || plugins_to_remove=${plugins_to_remove}" ${installed_plugin}"
            done
            for plugin in ${plugins_to_remove}; do
                plug_fifo_update "${plugin##*/}" "Deleted"
                rm -rf "${plugin}"
            done
        fi
    ) > /dev/null 2>&1 < /dev/null &

    if [ "$kak_opt_plug_block_ui" = "true" ]; then
        wait
    fi
}

plug_eval_hooks () {
    (
        plugin="${1%%.git}"
        plugin_name="${plugin##*/}"
        path_to_plugin="${kak_opt_plug_install_dir:?}/$plugin_name"
        build_dir="${kak_opt_plug_install_dir:?}/.build/$plugin_name"
        hook_file="$build_dir/hooks"

        plugin_log="${TMPDIR:-/tmp}/${plugin_name}-log"
        cd "$path_to_plugin" || exit

        printf "%s\n" "hook global -always KakEnd .* %{ nop %sh{rm -rf ${plugin_log}}}" | kak -p "${kak_session}"
        plug_fifo_update "${plugin_name}" "Running post-update hooks"

        status=0
        if [ -e "$hook_file" ]; then
            # shellcheck disable=SC1090
            (. "$hook_file" >> "$plugin_log" 2>&1)
            status=$?
        fi
        [ ${status} -ne 0 ] && message="Error (${status})" || message="Done"

        plug_fifo_update "${plugin_name}" "${message}"
    ) > /dev/null 2>&1 < /dev/null &

    if [ "$kak_opt_plug_block_ui" = "true" ]; then
        wait
    fi
}

plug_list () {
    noupdate=$1
    tmp=$(mktemp -d "${TMPDIR:-/tmp}/plug-kak.XXXXXXXX")
    fifo="${tmp}/fifo"
    plug_buffer="${tmp}/plug-buffer"
    mkfifo "${fifo}"

    printf "%s\n" "edit! -fifo ${fifo} *plug*
                   set-option buffer filetype plug
                   plug-show-help
                   hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -rf ${tmp} } }
                   map buffer normal '<ret>' ':<space>plug-fifo-operate install-update<ret>'
                   map buffer normal 'H' ':<space>plug-show-help<ret>'
                   map buffer normal 'U' ':<space>plug-fifo-operate update<ret>'
                   map buffer normal 'I' ':<space>plug-fifo-operate install<ret>'
                   map buffer normal 'L' ':<space>plug-fifo-operate log<ret>'
                   map buffer normal 'D' ':<space>plug-fifo-operate clean<ret>'
                   map buffer normal 'R' ':<space>plug-fifo-operate hooks<ret>'"

    # get those plugins which were loaded by plug.kak
    eval "set -- ${kak_opt_plug_plugins}"
    while [ $# -gt 0 ]; do
        if [ -d "${kak_opt_plug_install_dir}/${1##*/}" ]; then
            printf "%s: Installed\n" "$1" >> "${plug_buffer}"
        else
            printf "%s: Not installed\n" "$1" >> "${plug_buffer}"
        fi
        shift
    done

    # get those plugins which have a directory at installation path,
    # but wasn't mentioned in any config file
    for existing_plugin in "${kak_opt_plug_install_dir}"/*; do
        case "${kak_opt_plug_plugins}" in
          (*"${existing_plugin##*/}"*) ;;
          (*)
            printf "%s: Not loaded\n" "${existing_plugin##*/}" >> "${plug_buffer}"
            ;;
        esac
    done

    ( sort "${plug_buffer}" > "${fifo}" )  > /dev/null 2>&1 < /dev/null &

    if [ -z "${noupdate}" ]; then
        (
            # shellcheck disable=SC2030,SC2031
            [ -z "${GIT_TERMINAL_PROMPT:-}" ] && export GIT_TERMINAL_PROMPT=0
            eval "set -- ${kak_opt_plug_plugins}"
            while [ $# -gt 0 ]; do
                plugin_dir="${1##*/}"
                if [ -d "${kak_opt_plug_install_dir}/${plugin_dir}" ]; then (
                    cd "${kak_opt_plug_install_dir}/${plugin_dir}" || exit
                    git fetch > /dev/null 2>&1
                    status=$?
                    if [ ${status} -eq 0 ]; then
                        { IFS= read -r LOCAL; IFS= read -r REMOTE; IFS= read -r BASE; } <<EOF
$(
                        git rev-parse  @ '@{u}'  # prints 2 lines
                        git merge-base @ '@{u}'
)
EOF

                        if [ "${LOCAL}" = "${REMOTE}" ]; then
                            message="Up to date"
                        elif [ "${LOCAL}" = "${BASE}" ]; then
                            message="Update available"
                        elif [ "${REMOTE}" = "${BASE}" ]; then
                            message="Local changes"
                        else
                            message="Installed"
                        fi
                    else
                        message="Fetch Error (${status})"
                    fi
                    plug_fifo_update "$1" "${message}"
                ) > /dev/null 2>&1 < /dev/null & fi
                shift
            done
        ) > /dev/null 2>&1 < /dev/null &
    fi
}

plug_fifo_operate() {
    plugin="${kak_reg_t%:*}"
    case $1 in
        (install-update)
            if [ -d "${kak_opt_plug_install_dir}/${plugin##*/}" ]; then
                plug_update "${plugin}"
            else
                plug_install "${plugin}" true
            fi ;;
        (update)
            if [ -d "${kak_opt_plug_install_dir}/${plugin##*/}" ]; then
                plug_update "${plugin}"
            else
                printf "%s\n" "echo -markup %{{Information}'${plugin}' is not installed}"
            fi ;;
        (install)
            if [ ! -d "${kak_opt_plug_install_dir}/${plugin##*/}" ]; then
                plug_install "${plugin}"
            else
                printf "%s\n" "echo -markup %{{Information}'${plugin}' already installed}"
            fi ;;
        (clean) plug_clean "${plugin}" ;;
        (log) printf "%s\n" "plug-display-log $plugin" ;;
        (hooks) plug_eval_hooks "${plugin##*/}" ;;
        (*) ;;
    esac
}

plug_fifo_update() {
    printf "%s\n" "
        evaluate-commands -draft -buffer *plug* -save-regs \"/\"\"\" %{ try %{
            set-register / \"$1: \"
            set-register dquote %{$2}
            execute-keys -draft /<ret>lGlR
        }}" | kak -p "$kak_session"
}

plug_save_timestamp() {
  plug_tstamp=${EPOCHREALTIME:-}
  if [ -n "$plug_tstamp" ]; then
    plug_tstamp_ms=${plug_tstamp#*.}
    case "$plug_tstamp_ms" in
      (????*) plug_tstamp_ms=${plug_tstamp_ms%"${plug_tstamp_ms#???}"} ;;
      (???)   ;;
      (*)     plug_tstamp= ;;  # redo with date
    esac
    if [ -n "$plug_tstamp" ]; then
      plug_tstamp=${plug_tstamp%.*}${plug_tstamp_ms}
    fi
  fi
  : "${plug_tstamp:=$(date +%s%3N)}"
  if [ -n "$1" ]; then eval "$1=\$plug_tstamp"; fi
}

#  Spell-checker local dictionary
#  LocalWords:  Andrey Listopadov github kak usr config dir Kakoune
#  LocalWords:  expr ModuleLoaded mkdir ln PWD conf shellcheck noload
#  LocalWords:  TMPDIR tmp noupdate lockfile rmdir ret gjO esc KakEnd
#  LocalWords:  nop rf hacky eval fifo filetype BufCloseFifo regs
#  LocalWords:  dquote lGlR
Download .txt
gitextract_em9e3vjj/

├── LICENSE
├── README.md
└── rc/
    ├── plug.kak
    └── plug.sh
Condensed preview — 4 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (52K chars).
[
  {
    "path": "LICENSE",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2018 Andrey Orst\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 14762,
    "preview": "# Project status\n\nBecause I have stopped using Kakoune, this project will not receive active maintenance. The issues sec"
  },
  {
    "path": "rc/plug.kak",
    "chars": 11989,
    "preview": "# Author: Andrey Listopadov\n# plug.kak is a plugin manager for Kakoune. It can install plugins, keep them updated, confi"
  },
  {
    "path": "rc/plug.sh",
    "chars": 21496,
    "preview": "#!/usr/bin/env sh\n\n# Author: Andrey Listopadov\n# https://github.com/andreyorst/plug.kak\n#\n# plug.kak is a plugin manager"
  }
]

About this extraction

This page contains the full source code of the andreyorst/plug.kak GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 4 files (48.2 KB), approximately 12.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!