mini.starter documentation

Generated from the main branch of ‘mini.nvim’

mini.starter Start screen

MIT License Copyright (c) 2021 Evgeni Chasnovski


Module

Displayed items are fully customizable both in terms of what they do and how they look (with reasonable defaults). Item selection can be done using prefix query with instant visual feedback.

Key design ideas:

  • All available actions are defined inside items. Each item should have the following info:

    • <action> - function or string for vim.cmd() which is executed when item is chosen. Empty string result in placeholder “inactive” item.

    • <name> - string which will be displayed and used for choosing.

    • <section> - string representing to which section item belongs. There are pre-configured whole sections in MiniStarter.sections.

  • Configure what items are displayed by supplying an array which can be normalized to an array of items. Read about how supplied items are normalized in MiniStarter.refresh().

  • Modify the final look by supplying content hooks: functions which take buffer content (see MiniStarter.get_content()) and identifier as input while returning buffer content as output. There are pre-configured content hook generators in MiniStarter.gen_hook.

  • Choosing an item can be done in two ways:

    • Type prefix query to filter item by matching its name (ignoring case). Displayed information is updated after every typed character. For every item its unique prefix is highlighted.

    • Use Up/Down arrows and hit Enter.

  • Allow multiple simultaneously open Starter buffers.

What is doesn’t do:

  • It doesn’t support fuzzy query for items. And probably will never do.

Setup

This module needs a setup with require('mini.starter').setup({}) (replace {} with your config table). It will create global Lua table MiniStarter which you can use for scripting or manually (with :lua MiniStarter.*).

See MiniStarter.config for config structure and default values. For some configuration examples (including one similar to ‘vim-startify’ and ‘dashboard-nvim’), see MiniStarter-example-config.

You can override runtime config settings locally to buffer inside vim.b.ministarter_config which should have same structure as MiniStarter.config. See mini.nvim-buffer-local-config for more details. Note: vim.b.ministarter_config is copied to Starter buffer from current buffer allowing full customization.

To stop module from showing non-error feedback, set config.silent = true.

Highlight groups

  • MiniStarterCurrent - current item.

  • MiniStarterFooter - footer units.

  • MiniStarterHeader - header units.

  • MiniStarterInactive - inactive item.

  • MiniStarterItem - item name.

  • MiniStarterItemBullet - units from MiniStarter.gen_hook.adding_bullet().

  • MiniStarterItemPrefix - unique query for item.

  • MiniStarterSection - section units.

  • MiniStarterQuery - current query in active items.

To change any highlight group, set it directly with nvim_set_hl().

Disabling

To disable core functionality, set vim.g.ministarter_disable (globally) or vim.b.ministarter_disable (for a buffer) to true. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module’s functionality is left to user. See mini.nvim-disabling-recipes for common recipes.


Example config

Similar to ‘mhinz/vim-startify’

local starter = require('mini.starter')
starter.setup({
  evaluate_single = true,
  items = {
    starter.sections.builtin_actions(),
    starter.sections.recent_files(10, false),
    starter.sections.recent_files(10, true),
    -- Use this if you set up 'mini.sessions'
    starter.sections.sessions(5, true)
  },
  content_hooks = {
    starter.gen_hook.adding_bullet(),
    starter.gen_hook.indexing('all', { 'Builtin actions' }),
    starter.gen_hook.padding(3, 2),
  },
})

Similar to ‘glepnir/dashboard-nvim’

local starter = require('mini.starter')
starter.setup({
  items = {
    starter.sections.telescope(),
  },
  content_hooks = {
    starter.gen_hook.adding_bullet(),
    starter.gen_hook.aligning('center', 'center'),
  },
})

Demo of capabilities

local my_items = {
  { name = 'Echo random number', action = 'lua print(math.random())', section = 'Section 1' },
  function()
    return {
      { name = 'Item #1 from function', action = [[echo 'Item #1']], section = 'From function' },
      { name = 'Placeholder (always inactive) item', action = '', section = 'From function' },
      function()
        return {
          name = 'Item #1 from double function',
          action = [[echo 'Double function']],
          section = 'From double function',
        }
      end,
    }
  end,
  { name = [[Another item in 'Section 1']], action = 'lua print(math.random() + 10)', section = 'Section 1' },
}

local footer_n_seconds = (function()
  local timer = vim.loop.new_timer()
  local n_seconds = 0
  timer:start(0, 1000, vim.schedule_wrap(function()
    if vim.bo.filetype ~= 'ministarter' then
      timer:stop()
      return
    end
    n_seconds = n_seconds + 1
    MiniStarter.refresh()
  end))

  return function()
    return 'Number of seconds since opening: ' .. n_seconds
  end
end)()

local hook_top_pad_10 = function(content)
  -- Pad from top
  for _ = 1, 10 do
    -- Insert at start a line with single content unit
    table.insert(content, 1, { { type = 'empty', string = '' } })
  end
  return content
end

local starter = require('mini.starter')
starter.setup({
  items = my_items,
  footer = footer_n_seconds,
  content_hooks = { hook_top_pad_10 },
})

Lifecycle

  • Open with MiniStarter.open(). It includes creating buffer with appropriate options, mappings, behavior; call to MiniStarter.refresh(); issue MiniStarterOpened User event.

  • Wait for user to choose an item. This is done using following logic:

    • Typing any character from MiniStarter.config.query_updaters leads to updating query. Read more in MiniStarter.add_to_query().

    • <BS> deletes latest character from query.

    • <Down>/<Up>, <C-n>/<C-p>, <M-j>/<M-k> move current item.

    • <CR> executes action of current item.

    • <C-c> closes Starter buffer.

  • Evaluate current item when appropriate (after <CR> or when there is a single item and MiniStarter.config.evaluate_single is true). This executes item’s action.


setup()

MiniStarter.setup({config})

Module setup

Parameters

{config} (table|nil) Module config table. See MiniStarter.config.

Usage

require('mini.starter').setup() -- use default config
-- OR
require('mini.starter').setup({}) -- replace {} with your config table

config

MiniStarter.config

Defaults

MiniStarter.config = {
  -- Whether to open Starter buffer on VimEnter. Not opened if Neovim was
  -- started with intent to show something else.
  autoopen = true,

  -- Whether to evaluate action of single active item
  evaluate_single = false,

  -- Items to be displayed. Should be an array with the following elements:
  -- - Item: table with <action>, <name>, and <section> keys.
  -- - Function: should return one of these three categories.
  -- - Array: elements of these three types (i.e. item, array, function).
  -- If `nil` (default), default items will be used (see |mini.starter|).
  items = nil,

  -- Header to be displayed before items. Converted to single string via
  -- `tostring` (use `\n` to display several lines). If function, it is
  -- evaluated first. If `nil` (default), polite greeting will be used.
  header = nil,

  -- Footer to be displayed after items. Converted to single string via
  -- `tostring` (use `\n` to display several lines). If function, it is
  -- evaluated first. If `nil` (default), default usage help will be shown.
  footer = nil,

  -- Array  of functions to be applied consecutively to initial content.
  -- Each function should take and return content for Starter buffer (see
  -- |mini.starter| and |MiniStarter.get_content()| for more details).
  content_hooks = nil,

  -- Characters to update query. Each character will have special buffer
  -- mapping overriding your global ones. Be careful to not add `:` as it
  -- allows you to go into command mode.
  query_updaters = 'abcdefghijklmnopqrstuvwxyz0123456789_-.',

  -- Whether to disable showing non-error feedback
  silent = false,
}

open()

MiniStarter.open({buf_id})

Open Starter buffer

  • Create buffer if necessary and move into it.

  • Set buffer options. Note that settings are done with :noautocmd to achieve a massive speedup.

  • Set buffer mappings. Besides basic mappings (described inside “Lifecycle of Starter buffer” of mini.starter), map every character from MiniStarter.config.query_updaters to add itself to query with MiniStarter.add_to_query().

  • Populate buffer with MiniStarter.refresh().

  • Issue custom MiniStarterOpened event to allow acting upon opening Starter buffer. Use it with autocmd User MiniStarterOpened <your command>.

Note: to fully use it in autocommand, use autocmd-nested. Example:

local starter_open = function() MiniStarter.open() end
local au_opts = { nested = true, callback = starter_open }
vim.api.nvim_create_autocmd('TabNewEntered', au_opts)

Parameters

{buf_id} (number|nil) Identifier of existing valid buffer (see bufnr()) to open inside. Default: create a new one.


refresh()

MiniStarter.refresh({buf_id})

Refresh Starter buffer

  • Normalize MiniStarter.config.items:

    • Flatten: recursively (in depth-first fashion) parse its elements. If function is found, execute it and continue with parsing its output (this allows deferring item collection up until it is actually needed). If proper item is found (table with fields action, name, section), add it to output.

    • Sort: order first by section and then by item id (both in order of appearance).

  • Normalize MiniStarter.config.header and MiniStarter.config.footer to be multiple lines by splitting at \n. If function - evaluate it first.

  • Make initial buffer content (see MiniStarter.get_content() for a description of what a buffer content is). It consist from content lines with single content unit:

    • First lines contain strings of normalized header.

    • Body is for normalized items. Section names have own lines preceded by empty line.

    • Last lines contain separate strings of normalized footer.

  • Sequentially apply hooks from MiniStarter.config.content_hooks to content. All hooks are applied with (content, buf_id) signature. Output of one hook serves as first argument to the next.

  • Gather final items from content with MiniStarter.content_to_items().

  • Convert content to buffer lines with MiniStarter.content_to_lines() and add them to buffer.

  • Add highlighting of content units.

  • Position cursor.

  • Make current query. This results into some items being marked as “inactive” and updating highlighting of current query on “active” items.

Note: this function is executed on every VimResized to allow more responsive behavior.

Parameters

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


close()

MiniStarter.close({buf_id})

Close Starter buffer

Parameters

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


sections

MiniStarter.sections

Table of pre-configured sections


sections.builtin_actions()

MiniStarter.sections.builtin_actions()

Section with builtin actions

Return

(table) Array of items.


sections.sessions()

MiniStarter.sections.sessions({n}, {recent})

Section with mini.sessions sessions

Sessions are taken from MiniSessions.detected. Notes:

  • If it shows “‘mini.sessions’ is not set up”, it means that you didn’t call require('mini.sessions').setup().

  • If it shows “There are no detected sessions in ‘mini.sessions’”, it means that there are no sessions at the current sessions directory. Either create session or supply different directory where session files are stored (see MiniSessions.setup()).

  • Local session (if detected) is always displayed first.

Parameters

{n} (number|nil) Number of returned items. Default: 5.

{recent} (boolean|nil) Whether to use recent sessions (instead of alphabetically by name). Default: true.

Return

(function) Function which returns array of items.


sections.recent_files()

MiniStarter.sections.recent_files({n}, {current_dir}, {show_path})

Section with most recently used files

Files are taken from v:oldfiles.

Parameters

{n} (number|nil) Number of returned items. Default: 5.

{current_dir} (boolean|nil) Whether to return files only from current working directory and its subdirectories. Default: false.

{show_path} (boolean|function|nil) Whether to append file name with its path. If callable, will be called with full path and should return string to be directly appended to file name. Default: true.

Return

(function) Function which returns array of items.


sections.pick()

MiniStarter.sections.pick()

Section with mini.pick pickers

Notes:

  • All actions require ‘mini.pick’ module of ‘mini.nvim’.

  • “Command history”, “Explorer”, and “Visited paths” items require mini.extra module of ‘mini.nvim’.

  • “Visited paths” items requires mini.visits module of ‘mini.nvim’.

Return

(function) Function which returns array of items.


sections.telescope()

MiniStarter.sections.telescope()

Section with basic Telescope pickers relevant to start screen

Notes:

Return

(function) Function which returns array of items.


gen_hook

MiniStarter.gen_hook

Table with pre-configured content hook generators

Each element is a function which returns content hook. So to use them inside MiniStarter.setup(), call them.


gen_hook.padding()

MiniStarter.gen_hook.padding({left}, {top})

Hook generator for padding

Output is a content hook which adds constant padding from left and top. This allows tweaking the screen position of buffer content.

Parameters

{left} (number|nil) Number of empty spaces to add to start of each content line. Default: 0.

{top} (number|nil) Number of empty lines to add to start of content. Default: 0.

Return

(function) Content hook.


gen_hook.adding_bullet()

MiniStarter.gen_hook.adding_bullet({bullet}, {place_cursor})

Hook generator for adding bullet to items

Output is a content hook which adds supplied string to be displayed to the left of item.

Parameters

{bullet} (string|nil) String to be placed to the left of item name. Default: “░”.

{place_cursor} (boolean|nil) Whether to place cursor on the first character of bullet when corresponding item becomes current. Default: true.

Return

(function) Content hook.


gen_hook.indexing()

MiniStarter.gen_hook.indexing({grouping}, {exclude_sections})

Hook generator for indexing items

Output is a content hook which adds unique index to the start of item’s name. It results into shortening queries required to choose an item (at expense of clarity).

Parameters

{grouping} (string|nil) One of “all” (number indexing across all sections) or “section” (letter-number indexing within each section). Default: “all”.

{exclude_sections} (table|nil) Array of section names (values of section element of item) for which index won’t be added. Default: {}.

Return

(function) Content hook.


gen_hook.aligning()

MiniStarter.gen_hook.aligning({horizontal}, {vertical})

Hook generator for aligning content

Output is a content hook which independently aligns content horizontally and vertically. Window width and height are taken from first window in current tabpage displaying the Starter buffer.

Basically, this computes left and top pads for MiniStarter.gen_hook.padding() such that output lines would appear aligned in certain way.

Parameters

{horizontal} (string|nil) One of “left”, “center”, “right”. Default: “left”.

{vertical} (string|nil) One of “top”, “center”, “bottom”. Default: “top”.

Return

(function) Content hook.


get_content()

MiniStarter.get_content({buf_id})

Get content of Starter buffer

Generally, buffer content is a table in the form of “2d array” (or rather “2d list” because number of elements can differ):

  • Each element represents content line: an array with content units to be displayed in one buffer line.

  • Each content unit is a table with at least the following elements:

    • “type” - string with type of content. Something like “item”, “section”, “header”, “footer”, “empty”, etc.

    • “string” - which string should be displayed. May be an empty string.

    • “hl” - which highlighting should be applied to content string. May be nil for no highlighting.

See MiniStarter.content_to_lines() for converting content to buffer lines and MiniStarter.content_to_items() - to list of parsed items.

Notes:

  • Content units with type “item” also have item element with all information about an item it represents. Those elements are used directly to create an array of items used for query.

Parameters

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


content_coords()

MiniStarter.content_coords({content}, {predicate})

Helper to iterate through content

Basically, this traverses content “2d array” (in depth-first fashion; top to bottom, left to right) and returns “coordinates” of units for which predicate is true-ish.

Parameters

{content} (table|nil) Content “2d array”. Default: content of current buffer.

{predicate} (function|string|nil) Predictate to filter units. If it is:

  • Function, then it is evaluated with unit as input.

  • String, then it checks unit to have this type (allows easy getting of units with some type).

  • nil, all units are kept.

Return

(table) Array of resulting units’ coordinates. Each coordinate is a table with <line> and <unit> keys. To retrieve actual unit from coordinate c, use content[c.line][c.unit].


content_to_lines()

MiniStarter.content_to_lines({content})

Convert content to buffer lines

One buffer line is made by concatenating string element of units within same content line.

Parameters

{content} (table|nil) Content “2d array”. Default: content of current buffer.

Return

(table) Array of strings for each buffer line.


content_to_items()

MiniStarter.content_to_items({content})

Convert content to items

Parse content (in depth-first fashion) and retrieve each item from item element of content units with type “item”. This also:

  • Computes some helper information about how item will be actually displayed (after MiniStarter.content_to_lines()) and minimum number of prefix characters needed for a particular item to be queried single.

  • Modifies item’s name element taking it from corresponding string element of content unit. This allows modifying item’s name at the stage of content hooks (like, for example, in MiniStarter.gen_hook.indexing()).

Parameters

{content} (table|nil) Content “2d array”. Default: content of current buffer.

Return

(table) Array of items.


eval_current_item()

MiniStarter.eval_current_item({buf_id})

Evaluate current item

Note that it resets current query before evaluation, as it is rarely needed any more.

Parameters

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


update_current_item()

MiniStarter.update_current_item({direction}, {buf_id})

Update current item

This makes next (with respect to direction) active item to be current.

Parameters

{direction} (string) One of “next” or “previous”.

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


add_to_query()

MiniStarter.add_to_query({char}, {buf_id})

Add character to current query

  • Update current query by appending char to its end (only if it results into at least one active item) or delete latest character if char is nil.

  • Recompute status of items: “active” if its name starts with new query, “inactive” otherwise.

  • Update highlighting: whole strings for “inactive” items, current query for “active” items.

Parameters

{char} (string|nil) Single character to be added to query. If nil, deletes latest character from query.

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.


set_query()

MiniStarter.set_query({query}, {buf_id})

Set current query

Parameters

{query} (string|nil) Query to be set (only if it results into at least one active item). Default: nil for setting query to empty string, which essentially resets query.

{buf_id} (number|nil) Buffer identifier of a valid Starter buffer. Default: current buffer.