andreyorst / powerline.kak

Kakoune modeline, but with passion
MIT License
50 stars 8 forks source link
kakoune plugin powerline

powerline.kak

license GitHub release GitHub Release Date GitHub commits (since latest release)

Powerline plugin for Kakoune Editor.

image

This plugin aims to make Kakoune's modeline more context dependent and beautiful. powerline.kak provides coloring, separators, toggling commands, support for git, and a modular system to easily extend powerline.kak with new modules. Some modules, like git and filetype, are shown only if they're available. For example, the filetype module won't display if Kakaoune can't detect a file's type. Also, if you're editing a file without write access, powerline.kak will display a lock symbol near the filename.

Installation

With plug.kak

Add this to your kakrc:

plug "andreyorst/powerline.kak" defer powerline_gruvbox %{
    powerline-theme gruvbox
} config %{
    powerline-start
}

Source your kakrc, or restart Kakoune. Then execute :plug-install. Or, if you don't want to source the configuration file or restart Kakoune, simply run plug-install andreyorst/powerline.kak. Lastly, run powerline-start to activate it.

Without plugin manager

Autoload

Clone, or place a symbolic link to, the repository into your autoload directory. In your kakrc, add a call to powerline-start.

The plugin should now load without any problems. If any errors appear, please open an issue.

By hand

Clone this repository somewhere

mkdir -p ~/.config/kak/plugins
git clone https://github.com/andreyorst/powerline.kak.git ~/.config/kak/plugins/

Source the main script in your kakrc:

source "%val{config}/plugins/powerline.kak/rc/powerline.kak"

Source modules. You can skip those you don't want, but it's highly recommended to source at least bufname.kak and mode_info.kak:

source "%val{config}/plugins/powerline.kak/rc/modules/bufname.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/client.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/filetype.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/git.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/line_column.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/mode_info.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/position.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/session.kak"
source "%val{config}/plugins/powerline.kak/rc/modules/lsp.kak"

And source the theme you want to use:

source "%val{config}/plugins/powerline.kak/rc/themes/base16-gruvbox.kak"

After that, you can enable powerline by adding the following command to your kakrc:

powerline-start

If you want to use built-in themes, you'll need to source theme from the rc/themes folder. This is kind of a tedious thing to do. That's why I recommend using a plugin manager, since it handles all the theming and configuration for you.

After that, you can use powerline.kak.

Configuration

powerline.kak supports these commands:

These options are also available to set, either from within a Kakoune buffer, or else in your kakrc:

All powerline.kak settings executed with commands are applied by default in the context of a buffer, therefore, you can have different powerlines for different buffers. However, a scope can be passed to these commands to set these options at the buffer, window, or global scope. For example, powerline-separator global triangle runs powerline-separator on a global scope, which applies to all buffers, instead of just the current one.

Example configuration using plug.kak

plug "andreyorst/powerline.kak" defer powerline %{
    powerline-format global 'git bufname filetype mode_info line_column position'
    powerline-toggle line_column off
} defer powerline_bufname %{
    set-option global powerline_shorten_bufname 'short'
} defer powerline_gruvbox %{
    powerline-theme gruvbox
} config %{
    powerline-start
}

Lets break this down:

You can add your own configurations here. Since all settings are buffer-dependent you can have different settings for different buffers, filetypes, etc.

Example configuration using kakrc

require-module powerline
set-option global powerline_format 'git bufname filetype mode_info lsp'
set-option global powerline_shorten_bufname name
powerline-start

Making themes

You can create your own themes for powerline.kak. Here's an example of a good theme:

# base16-gruvbox colorscheme for powerline.kak
# based on https://github.com/andreyorst/base16-gruvbox.kak

hook global ModuleLoaded powerline %{ require-module powerline_base16_gruvbox }

provide-module powerline_base16_gruvbox %§
set-option -add global powerline_themes "base16-gruvbox"

define-command -hidden powerline-theme-base16-gruvbox %{
    declare-option -hidden str powerline_color00 "rgb:282828" # fg: bufname
    declare-option -hidden str powerline_color01 "rgb:a89984" # bg: position
    declare-option -hidden str powerline_color02 "rgb:bdae93" # fg: git
    declare-option -hidden str powerline_color03 "rgb:a89984" # bg: bufname
    declare-option -hidden str powerline_color04 "rgb:3c3836" # bg: git
    declare-option -hidden str powerline_color05 "rgb:282828" # fg: position
    declare-option -hidden str powerline_color06 "rgb:bdae93" # fg: line-column, lsp
    declare-option -hidden str powerline_color07 "rgb:d5c4a1" # fg: mode-info
    declare-option -hidden str powerline_color08 "rgb:3c3836" # base background
    declare-option -hidden str powerline_color09 "rgb:504945" # bg: line-column, lsp
    ...
    declare-option -hidden str powerline_color30 "rgb:7c6f64" # unused
    declare-option -hidden str powerline_color31 "rgb:fbf1c7" # unused

    declare-option -hidden str powerline_next_bg %opt{powerline_color08}
    declare-option -hidden str powerline_base_bg %opt{powerline_color08}
}

§

That is, themes for powerline.kak are commands, that define colors in these variables. Each module has foreground and background assets. Note that modifiers like bold are not supported. When defining a theme, please make sure that text at the end of your command and string that you add to the powerline_themes are exactly the same:

set-option -add global powerline_themes "base16-gruvbox"
define-command   -hidden powerline-theme-base16-gruvbox %{...}
#                                        ^^^^^^^^^^^^^^
#                                       This is important
#                                     These must be the same

If they are the same powerline.kak will show you completion items with correct theme name and execute this command for you. No need to execute this command manually. All you need to do is powerline-theme base16-gruvbox.

Also make sure to put theme into appropriate module, and require it after main module is loaded via hook:

hook global ModuleLoaded powerline %{ require-module powerline_base16_gruvbox }

There are 32 default colors available for modules. 16 of them are reserved by default powerline.kak modules. Each module should use only two colors - one for foreground and one for background, and only those which are not used by other modules, if possible. These colors are used by default modules:

Module Name Foreground Background
bufname color00 color03
client color13 color12
filetype color10 color11
git color02 color04
line-column color06 color09
mode-info color07 base_bg (color08)
position color05 color01
session color15 color14
lsp color06 color09

Colors from color16 to color31 are declared by the main script, but not used by any of default modules so you could use them in your own modules. Make sure to add comment which module uses those colors if you want to submit your module to powerline.kak.

Writing a module

This is a bit trickier than writing themes, but you can add your own modules to powerline. To create a module you need the following things:

Here's an example of adding a module that shows current position within edited file in percents. This module already exists in powerline.kak but still can be a good example, because it is not existing functionality in Kakoune itself, and needs an update function.

First, lets declare hidden option of str type, that will store our position:

declare-option -hidden str powerline_position ''

We're not giving it a default value, since our next command will handle it:

define-command -hidden powerline-update-position %{ set-option window powerline_position %sh{
    echo "$(($kak_cursor_line * 100 / $kak_buf_line_count))%"
}}

As you can see, we're using set-option in context of a window to update our powerline_pos_percent variable, because we don't want to update position in another window while scrolling the only one of them. Now we need a hook that will update it only when needed. To declare hooks you need to create a function that has this template name powerline-MODULENAME-setup-hooks. It will be called automatically by powerline.kak.

define-command powerline-position-setup-hooks %{
    remove-hooks global powerline-position
    evaluate-commands %sh{
        if [ "$kak_opt_powerline_module_position" = "true" ]; then
            printf "%s\n" "hook -group powerline-position global NormalKey [jk] powerline-update-position"
            printf "%s\n" "hook -group powerline-position global NormalIdle .*  powerline-update-position"
        fi
    }
}

This way powerline.kak will be able to automatically call this function whenever powerline is being rebuild and define these hooks - first to update it frequently while we move with j and k and second to update it via timeout, so it could show actual position after jumps and searches.

Now we need a module command. In powerline.kak every module that you see in your modeline is actually a command, that is being called once when powerline.kak builds modeline for you. In this case, percent position is already an existing module, so here's how it is defined:

define-command -hidden powerline-position %{ evaluate-commands %sh{
    default=$kak_opt_powerline_base_bg
    next_bg=$kak_opt_powerline_next_bg
    normal=$kak_opt_powerline_separator
    thin=$kak_opt_powerline_separator_thin
    if [ "$kak_opt_powerline_module_position" = "true" ]; then
        bg=$kak_opt_powerline_position_bg
        fg=$kak_opt_powerline_position_fg
        [ "$next_bg" = "$bg" ] && separator="{$fg,$bg}$thin" || separator="{$bg,${next_bg:-$default}}$normal"
        echo "set-option -add global powerlinefmt %{$separator{$fg,$bg} ≣ %opt{powerline_position} }"
        echo "set-option global powerline_next_bg $bg"
    fi
}}

set-option -add global powerline_modules 'position'

There's a lot going on, so lets break it down.

First, we define a hidden command, called powerline-position, that will be called by powerline, when powerline-build is executed.

In this command we use evaluate-commands %sh{...} pattern, because modules involve some logic inside them to properly display colors and different separators.

In this shell expansion we're declaring four variables:

After that we have an if statement, that ensures that module isn't toggled off, and we actually need to draw our module in powerline. And if it is on, we do the following:

Now, when we have our module command written we still need one more thing: a toggle command.

A toggle command will be used to toggle our module on and off when we don't need it, but still want it to be in modeline. For example we may not need to know ow percent position in *grep* buffer. The command is defined like so:

define-command -hidden powerline-toggle-position -params ..1 %{ evaluate-commands %sh{
    [ "$kak_opt_powerline_module_position" = "true" ] && value=false || value=true
    if [ -n "$1" ]; then
        [ "$1" = "on" ] && value=true || value=false
    fi
    echo "set-option global powerline_module_position $value"
}}

This command has one optional parameter for on and off switches which are checked inside of it.

This is how you add a module to powerline.kak. So, if you're writing a plugin, you can have this code inside your plugin, or you can send a PR with it and it will be included to powerline.kak as a separate module. But how would powerline.kak know how to execute these commands?

That's a good question. Remember when we added our module name to global module list with:

set-option -add global powerline_modules 'position'

This allows powerline.kak to reconstruct proper command for you, because it knows base name which is powerline-toggle- and a module name which is position. So when you call powerline-toggle position it combines those two and calls powerline-toggle-position for you. All other commands are handled in the same way.