Skip to content

Plugins

Andrej Benz edited this page Dec 1, 2024 · 11 revisions

You can extend Walker by adding a plugin to plugins in your config.

type Plugin struct {
	GeneralModule    `mapstructure:",squash"`
	Cmd              string            `mapstructure:"cmd"`
	CmdAlt           string            `mapstructure:"cmd_alt"`
	Entries          []util.Entry      `mapstructure:"entries"`
	LabelColumn      int               `mapstructure:"label_column"`
	Matching         util.MatchingType `mapstructure:"matching"`
	RecalculateScore bool              `mapstructure:"recalculate_score,omitempty" json:"recalculate_score,omitempty"`
	ResultColumn     int               `mapstructure:"result_column"`
	Separator        string            `mapstructure:"separator"`
	Src              string            `mapstructure:"src"`
	SrcOnce          string            `mapstructure:"src_once"`
	Terminal         bool              `mapstructure:"terminal"`
	Parser           string            `mapstructure:"parser"`
	KvSeparator      string            `mapstructure:"kv_separator"`
}

type GeneralModule struct {
	Delay              int      `mapstructure:"delay"`
	EagerLoading       bool     `mapstructure:"eager_loading"`
	History            bool     `mapstructure:"history"`
	ShowIconWhenSingle bool     `mapstructure:"show_icon_when_single"`
	Icon               string   `mapstructure:"icon"`
	KeepSort           bool     `mapstructure:"keep_sort"`
	Name               string   `mapstructure:"name"`
	MinChars           int      `mapstructure:"min_chars"`
	Placeholder        string   `mapstructure:"placeholder"`
	Prefix             string   `mapstructure:"prefix"`
	Refresh            bool     `mapstructure:"refresh"`
	SwitcherOnly       bool     `mapstructure:"switcher_only"`
	Theme              string   `mapstructure:"theme"`
	ThemeBase          []string `mapstructure:"theme_base"`
	Typeahead          bool     `mapstructure:"typeahead"`
	ShowSubWhenSingle  bool     `mapstructure:"show_sub_when_single"`
	Weight             int      `mapstructure:"weight"`
}

type Entry struct {
	Categories       []string     `mapstructure:"categories,omitempty" json:"categories,omitempty"`
	Class            string       `mapstructure:"class,omitempty" json:"class,omitempty"`
	DragDrop         bool         `mapstructure:"drag_drop,omitempty" json:"drag_drop,omitempty"`
	DragDropData     string       `mapstructure:"drag_drop_data,omitempty" json:"drag_drop_data,omitempty"`
	Exec             string       `mapstructure:"exec,omitempty" json:"exec,omitempty"`
	ExecAlt          string       `mapstructure:"exec_alt,omitempty" json:"exec_alt,omitempty"`
	HideText         bool         `mapstructure:"hide_text,omitempty" json:"hide_text,omitempty"`
	Icon             string       `mapstructure:"icon,omitempty" json:"icon,omitempty"`
	Image            string       `mapstructure:"image,omitempty" json:"image,omitempty"`
	InitialClass     string       `mapstructure:"initial_class,omitempty" json:"initial_class,omitempty"`
	Label            string       `mapstructure:"label,omitempty" json:"label,omitempty"`
	MatchFields      int          `mapstructure:"match_fields,omitempty" json:"match_fields,omitempty"`
	Matching         MatchingType `mapstructure:"matching,omitempty" json:"matching,omitempty"`
	Path             string       `mapstructure:"path,omitempty" json:"path,omitempty"`
	RecalculateScore bool         `mapstructure:"recalculate_score,omitempty" json:"recalculate_score,omitempty"`
	ScoreFinal       float64      `mapstructure:"score_final,omitempty" json:"score_final,omitempty"`
	ScoreFuzzy       float64      `mapstructure:"score_fuzzy,omitempty" json:"score_fuzzy,omitempty"`
	Searchable       string       `mapstructure:"searchable,omitempty" json:"searchable,omitempty"`
	Sub              string       `mapstructure:"sub,omitempty" json:"sub,omitempty"`
	Terminal         bool         `mapstructure:"terminal,omitempty" json:"terminal,omitempty"`
	Prefer           bool         `mapstructure:"prefer,omitempty" json:"prefer,omitempty"`
}

External plugins can return either: json or lines of k/v pairs.

Example for a plugin calling an external command with json:

    {
      "name": "calc",
      "prefix": "=",
      "src": "node ~/somewhere/script.cjs %TERM%"
    },

where script.cjs would contain:

"use strict";
const os = require("os");

const args = process.argv.slice(2);
const term = args.join(" ");

if (term.length < 3) {
  console.log([]);
  return;
}

const { spawnSync } = require("child_process");
const { stderr } = require("process");
const ls = spawnSync("rink", [term]);

if (ls.stderr.toString() !== "") {
  return [{}];
}

const res = ls.stdout.toString();
const lines = res.split(os.EOL);

if (lines[1].includes("No such unit")) {
  console.log([]);
  return;
}

if (lines[1].includes("Expected")) {
  console.log([]);
  return;
}

console.log(
  JSON.stringify([
    {
      label: lines[1],
      sub: "rink",
      exec: `echo '${lines[1]}' | wl-copy`,
      class: "calc",
      matching: 1,
    },
  ]),
);

Example for an external plugin returning k/v pairs:

const fs = require("node:fs");
const path = require("node:path");

const folderPath = "/home/andrej/Pictures";

const isFile = (fileName) => {
  return fs.lstatSync(fileName).isFile();
};

const res = fs
  .readdirSync(folderPath)
  .map((fileName) => {
    return path.join(folderPath, fileName);
  })
  .filter(isFile);

res.forEach((i) => {
  console.log(
    `image=${i};label=${i};exec=xdg-open ${i};exec_alt=wl-copy < ${i};drag_drop=true;drag_drop_data=${i};class=pic;matching=1;`,
  );
});

You can also create plugins without calling any external:

    {
      "name": "nvim",
      "prefix": "~",
      "terminal": true,
      "src_once": "ls -1a ~/.local/share/nvim/sessions",
      "refresh": true,
      "cmd": "nvim -S ~/.local/share/nvim/sessions/%RESULT%"
    }

This will call src_once and cache the result. This input will be used to generate the entries for Walker. On activation cmd will be run.

cmd and cmd_alt can contain %RESULT%, which will be expanded to the result. src and src_once can contain %TERM%, which will be expanded to the search-term.

If not specified, stdin/out will be used.

Example: Power Menu

    {
      "name": "power",
      "placeholder": "Power",
      "switcher_only": true,
      "recalculate_score": true,
      "show_icon_when_single": true,
      "entries": [
        {
          "label": "Shutdown",
          "icon": "system-shutdown",
          "exec": "shutdown now"
        },
        {
          "label": "Reboot",
          "icon": "system-reboot",
          "exec": "reboot"
        },
        {
          "label": "Lock Screen",
          "icon": "system-lock-screen",
          "exec": "playerctl --all-players pause & hyprlock"
        }
      ]
    }

Example: Neovim Sessions

    {
      "name": "nvim",
      "placeholder": "Nvim Sessions",
      "prefix": "~",
      "terminal": true,
      "src_once": "ls -1a ~/.local/share/nvim/sessions",
      "refresh": true,
      "cmd": "nvim -S ~/.local/share/nvim/sessions/%RESULT%"
    }

Example: Calculator

    {
      "name": "calc",
      "prefix": "=",
      "src": "NO_COLOR=\"true\" rink",
      "cmd": "wl-copy",
      "matching": 1
    }
Clone this wiki locally