nvrim/
vim_opts.rs

1//! Vim option helpers and bulk setters exposed to Lua.
2//!
3//! Provides a dictionary `vim_opts.dict()` with batch application (`set_all`) and granular option mutation
4//! utilities wrapping [`nvim_oxi::api::set_option_value`], emitting notifications via
5//! Uses `ytil_noxi::notify::error` on failure.
6
7use core::fmt::Debug;
8use core::marker::Copy;
9use std::fmt::Write as _;
10
11use nvim_oxi::Dictionary;
12use nvim_oxi::api::opts::OptionOpts;
13use nvim_oxi::api::opts::OptionOptsBuilder;
14use nvim_oxi::api::opts::OptionScope;
15use nvim_oxi::conversion::FromObject;
16use nvim_oxi::conversion::ToObject;
17
18/// [`Dictionary`] of `vim.opts` helpers.
19pub fn dict() -> Dictionary {
20    dict! {
21        "set_all": fn_from!(set_all),
22    }
23}
24
25/// Sets a Vim option by `name` to `value` within the given [`OptionOpts`].
26///
27/// Errors are notified to Nvim via [`ytil_noxi::notify::error`].
28pub fn set<Opt: ToObject + Debug + Copy>(name: &str, value: Opt, opts: &OptionOpts) {
29    if let Err(err) = nvim_oxi::api::set_option_value(name, value, opts) {
30        ytil_noxi::notify::error(format!(
31            "error setting option | name={name:?} value={value:#?} opts={opts:#?} error={err:#?}"
32        ));
33    }
34}
35
36/// Gets a Vim option by `name` within the given [`OptionOpts`].
37///
38/// Errors are notified to Nvim via [`ytil_noxi::notify::error`].
39pub fn get<Opt: FromObject + Debug>(name: &str, opts: &OptionOpts) -> Option<Opt> {
40    match nvim_oxi::api::get_option_value(name, opts) {
41        Ok(value) => Some(value),
42        Err(err) => {
43            ytil_noxi::notify::error(format!(
44                "error getting option | name={name:?} opts={opts:#?} error={err:#?}"
45            ));
46            None
47        }
48    }
49}
50
51/// Appends to a var named `name` the supplied value `value`.
52///
53/// The current value is read as a [`String`] and modified by appending the supplied one with a
54/// comma.
55///
56/// Errors are notified to Nvim via `ytil_noxi::notify::error`.
57pub fn append(name: &str, value: &str, opts: &OptionOpts) {
58    let Ok(mut cur_value) = nvim_oxi::api::get_option_value::<String>(name, opts).inspect_err(|err| {
59        ytil_noxi::notify::error(format!(
60            "error getting option current value | name={name:?} opts={opts:#?} value_to_append={value:#?} error={err:#?}"
61        ));
62    }) else {
63        return;
64    };
65    // This shenanigan with `comma` and `write!` is to avoid additional allocations
66    let comma = if cur_value.is_empty() { "" } else { "," };
67    if let Err(err) = write!(cur_value, "{comma}{value}") {
68        ytil_noxi::notify::error(format!(
69            "error appending option value | name={name:?} cur_value={cur_value} append_value={value} opts={opts:#?} error={err:#?}"
70        ));
71    }
72    set(name, &*cur_value, opts);
73}
74
75/// Returns [`OptionOpts`] configured for the global scope.
76pub fn global_scope() -> OptionOpts {
77    OptionOptsBuilder::default().scope(OptionScope::Global).build()
78}
79
80/// Sets the desired Nvim options.
81fn set_all(_: ()) {
82    let global_scope = global_scope();
83
84    set("autoindent", true, &global_scope);
85    set("backspace", "indent,eol,start", &global_scope);
86    set("breakindent", true, &global_scope);
87    set("completeopt", "menuone,noselect", &global_scope);
88    set("cursorline", false, &global_scope);
89    set("expandtab", true, &global_scope);
90    set("fillchars", "eob: ", &global_scope);
91    set("hlsearch", true, &global_scope);
92    set("ignorecase", true, &global_scope);
93    set("laststatus", 3, &global_scope);
94    set("list", true, &global_scope);
95    set("number", false, &global_scope);
96    set("relativenumber", false, &global_scope);
97    set("shiftwidth", 2, &global_scope);
98    set("shortmess", "ascIF", &global_scope);
99    set("showmode", false, &global_scope);
100    set("showtabline", 0, &global_scope);
101    set("sidescroll", 1, &global_scope);
102    set("signcolumn", "no", &global_scope);
103    set("smartcase", true, &global_scope);
104    set("splitbelow", true, &global_scope);
105    set("splitright", true, &global_scope);
106    set(
107        "statuscolumn",
108        r#"%{%v:lua.require("statuscolumn").draw(v:lnum)%}"#,
109        &global_scope,
110    );
111    set(
112        "statusline",
113        r#"%{%v:lua.require("statusline").draw()%}"#,
114        &global_scope,
115    );
116    set("swapfile", false, &global_scope);
117    set("tabstop", 2, &global_scope);
118    set("undofile", true, &global_scope);
119    set("updatetime", 250, &global_scope);
120    set("wrap", true, &global_scope);
121
122    append("clipboard", "unnamedplus", &global_scope);
123    append("iskeyword", "-", &global_scope);
124    append("jumpoptions", "stack", &global_scope);
125}