nvim_api/
global.rs

1use std::path::{Path, PathBuf};
2
3use nvim_types::{
4    self as nvim,
5    conversion::{FromObject, ToObject},
6    Array,
7    Dictionary,
8    Integer,
9    Object,
10};
11
12use crate::choose;
13use crate::ffi::global::*;
14use crate::iterator::SuperIterator;
15use crate::opts::*;
16use crate::types::*;
17use crate::StringOrFunction;
18use crate::LUA_INTERNAL_CALL;
19use crate::{Buffer, TabPage, Window};
20use crate::{Error, Result};
21
22/// Binding to [`nvim_chan_send`](https://neovim.io/doc/user/api.html#nvim_chan_send()).
23///
24/// Sends data to a channel.
25pub fn chan_send(channel_id: u32, data: &str) -> Result<()> {
26    let mut err = nvim::Error::new();
27    let data = nvim::String::from(data);
28    unsafe { nvim_chan_send(channel_id.into(), data.non_owning(), &mut err) };
29    choose!(err, ())
30}
31
32/// Binding to [`nvim_create_buf`](https://neovim.io/doc/user/api.html#nvim_create_buf()).
33///
34/// Creates a new, empty, unnamed buffer.
35pub fn create_buf(is_listed: bool, is_scratch: bool) -> Result<Buffer> {
36    let mut err = nvim::Error::new();
37    let handle = unsafe { nvim_create_buf(is_listed, is_scratch, &mut err) };
38    choose!(err, Ok(handle.into()))
39}
40
41/// Binding to [`nvim_create_user_command`](https://neovim.io/doc/user/api.html#nvim_create_user_command()).
42///
43/// Creates a new [user command](https://neovim.io/doc/user/map.html#user-commands).
44pub fn create_user_command<Cmd>(
45    name: &str,
46    command: Cmd,
47    opts: &CreateCommandOpts,
48) -> Result<()>
49where
50    Cmd: StringOrFunction<CommandArgs, ()>,
51{
52    let name = nvim::String::from(name);
53    let command = command.to_object();
54    let opts = KeyDict_user_command::from(opts);
55    let mut err = nvim::Error::new();
56    unsafe {
57        nvim_create_user_command(
58            name.non_owning(),
59            command.non_owning(),
60            &opts,
61            &mut err,
62        )
63    };
64    choose!(err, ())
65}
66
67/// Binding to [`nvim_del_current_line`](https://neovim.io/doc/user/api.html#nvim_del_current_line()).
68///
69/// Deletes the current line.
70pub fn del_current_line() -> Result<()> {
71    let mut err = nvim::Error::new();
72    unsafe { nvim_del_current_line(&mut err) };
73    choose!(err, ())
74}
75
76/// Binding to [`nvim_del_keymap`](https://neovim.io/doc/user/api.html#nvim_del_keymap()).
77///
78/// Unmaps a global mapping for the given mode. To unmap a buffer-local mapping
79/// use [`Buffer::del_keymap`] instead.
80pub fn del_keymap(mode: Mode, lhs: &str) -> Result<()> {
81    let mode = nvim::String::from(mode);
82    let lhs = nvim::String::from(lhs);
83    let mut err = nvim::Error::new();
84    unsafe {
85        nvim_del_keymap(
86            LUA_INTERNAL_CALL,
87            mode.non_owning(),
88            lhs.non_owning(),
89            &mut err,
90        )
91    };
92    choose!(err, ())
93}
94
95/// Binding to [`nvim_del_mark`](https://neovim.io/doc/user/api.html#nvim_del_mark()).
96///
97/// Deletes an uppercase/file named mark. Returns an error if a lowercase or
98/// buffer-local named mark is used. Use [`Buffer::del_mark`] to delete a
99/// buffer-local mark.
100pub fn del_mark(name: char) -> Result<()> {
101    let name = nvim::String::from(name);
102    let mut err = nvim::Error::new();
103    let was_deleted = unsafe { nvim_del_mark(name.non_owning(), &mut err) };
104    choose!(
105        err,
106        match was_deleted {
107            true => Ok(()),
108            _ => Err(Error::custom("Couldn't delete mark")),
109        }
110    )
111}
112
113/// Binding to [`nvim_del_user_command`](https://neovim.io/doc/user/api.html#nvim_del_user_command()).
114///
115/// Deletes a global user-defined command.  Use [`Buffer::del_user_command`] to
116/// delete a buffer-local command.
117pub fn del_user_command(name: &str) -> Result<()> {
118    let name = nvim::String::from(name);
119    let mut err = nvim::Error::new();
120    unsafe { nvim_del_user_command(name.non_owning(), &mut err) };
121    choose!(err, ())
122}
123
124/// Binding to [`nvim_del_var`](https://neovim.io/doc/user/api.html#nvim_del_var()).
125///
126/// Removes a global (`g:`) variable.
127pub fn del_var(name: &str) -> Result<()> {
128    let name = nvim::String::from(name);
129    let mut err = nvim::Error::new();
130    unsafe { nvim_del_var(name.non_owning(), &mut err) };
131    choose!(err, ())
132}
133
134/// Binding to [`nvim_echo`](https://neovim.io/doc/user/api.html#nvim_echo()).
135///
136/// Echoes a message to the Neovim message area.
137pub fn echo<'hl, Text, Chunks>(chunks: Chunks, history: bool) -> Result<()>
138where
139    Chunks: IntoIterator<Item = (Text, Option<&'hl str>)>,
140    Text: Into<nvim::String>,
141{
142    let chunks = chunks
143        .into_iter()
144        .map(|(text, hlgroup)| {
145            Array::from_iter([
146                Object::from(text.into()),
147                Object::from(hlgroup.map(|hl| hl.to_owned())),
148            ])
149        })
150        .collect::<Array>();
151
152    let mut err = nvim::Error::new();
153    let opts = Dictionary::new();
154    unsafe {
155        nvim_echo(chunks.non_owning(), history, opts.non_owning(), &mut err)
156    };
157    choose!(err, ())
158}
159
160/// Binding to [`nvim_err_write`](https://neovim.io/doc/user/api.html#nvim_err_write()).
161///
162/// Writes a message to the Neovim error buffer. Does not append a newline
163/// (`"\n"`); the message gets buffered and won't be displayed until a linefeed
164/// is written.
165pub fn err_write(str: &str) {
166    unsafe { nvim_err_write(nvim::String::from(str).non_owning()) }
167}
168
169/// Binding to [`nvim_err_writeln`](https://neovim.io/doc/user/api.html#nvim_err_writeln()).
170///
171/// Writes a message to the Neovim error buffer. Appends a newline (`"\n"`), so
172/// the buffer is flushed and displayed.
173pub fn err_writeln(str: &str) {
174    unsafe { nvim_err_writeln(nvim::String::from(str).non_owning()) }
175}
176
177/// Binding to [`nvim_eval_statusline`](https://neovim.io/doc/user/api.html#nvim_eval_statusline()).
178///
179/// Evaluates a string to be displayed in the statusline.
180pub fn eval_statusline(
181    str: &str,
182    opts: &EvalStatuslineOpts,
183) -> Result<StatuslineInfos> {
184    let str = nvim::String::from(str);
185    let opts = KeyDict_eval_statusline::from(opts);
186    let mut err = nvim::Error::new();
187    let dict =
188        unsafe { nvim_eval_statusline(str.non_owning(), &opts, &mut err) };
189    choose!(err, Ok(StatuslineInfos::from_object(dict.into())?))
190}
191
192/// Binding to [`nvim_feedkeys`](https://neovim.io/doc/user/api.html#nvim_feedkeys()).
193pub fn feedkeys(keys: &str, mode: Mode, escape_ks: bool) {
194    let keys = nvim::String::from(keys);
195    let mode = nvim::String::from(mode);
196    unsafe { nvim_feedkeys(keys.non_owning(), mode.non_owning(), escape_ks) }
197}
198
199/// Binding to [`nvim_get_all_options_info`](https://neovim.io/doc/user/api.html#nvim_get_all_options_info()).
200///
201/// Gets the option information for all options.
202pub fn get_all_options_info() -> Result<impl SuperIterator<OptionInfos>> {
203    let mut err = nvim::Error::new();
204    let infos = unsafe { nvim_get_all_options_info(&mut err) };
205    choose!(
206        err,
207        Ok({
208            infos
209                .into_iter()
210                .map(|(_, optinf)| OptionInfos::from_object(optinf).unwrap())
211        })
212    )
213}
214
215/// Binding to [`nvim_get_chan_info`](https://neovim.io/doc/user/api.html#nvim_get_chan_info()).
216///
217/// Gets information about a channel.
218pub fn get_chan_info(channel_id: u32) -> Result<ChannelInfos> {
219    let mut err = nvim::Error::new();
220    let infos = unsafe { nvim_get_chan_info(channel_id.into(), &mut err) };
221    choose!(err, Ok(ChannelInfos::from_object(infos.into())?))
222}
223
224/// Binding to [`nvim_get_color_by_name`](https://neovim.io/doc/user/api.html#nvim_get_color_by_name()).
225///
226/// Returns the 24-bit RGB value of a `crate::api::get_color_map` color name or
227/// "#rrggbb" hexadecimal string.
228pub fn get_color_by_name(name: &str) -> Result<u32> {
229    let name = nvim::String::from(name);
230    let color = unsafe { nvim_get_color_by_name(name.non_owning()) };
231    (color != -1).then(|| color.try_into().unwrap()).ok_or_else(|| {
232        Error::custom(format!("{name} is not a valid color name"))
233    })
234}
235
236/// Binding to [`nvim_get_color_map`](https://neovim.io/doc/user/api.html#nvim_get_color_map()).
237///
238/// Returns an iterator over tuples representing color names and 24-bit RGB
239/// values (e.g. 65535).
240pub fn get_color_map() -> impl SuperIterator<(String, u32)> {
241    unsafe { nvim_get_color_map() }.into_iter().map(|(k, v)| {
242        (String::try_from(k).unwrap(), u32::from_object(v).unwrap())
243    })
244}
245
246/// Binding to [`nvim_get_commands`](https://neovim.io/doc/user/api.html#nvim_get_commands()).
247///
248/// Returns an iterator over the infos of the global ex commands. Only
249/// user-defined commands are returned, not builtin ones.
250pub fn get_commands(
251    opts: &GetCommandsOpts,
252) -> Result<impl SuperIterator<CommandInfos>> {
253    let opts = KeyDict_get_commands::from(opts);
254    let mut err = nvim::Error::new();
255    let cmds = unsafe { nvim_get_commands(&opts, &mut err) };
256    choose!(
257        err,
258        Ok({
259            cmds.into_iter()
260                .map(|(_, cmd)| CommandInfos::from_object(cmd).unwrap())
261        })
262    )
263}
264
265/// Binding to [`nvim_get_context`](https://neovim.io/doc/user/api.html#nvim_get_context()).
266///
267/// Returns a snapshot of the current editor state.
268pub fn get_context(opts: &GetContextOpts) -> Result<EditorContext> {
269    let opts = KeyDict_context::from(opts);
270    let mut err = nvim::Error::new();
271    let ctx = unsafe { nvim_get_context(&opts, &mut err) };
272    choose!(err, Ok(EditorContext::from_object(ctx.into())?))
273}
274
275/// Binding to [`nvim_get_current_buf`](https://neovim.io/doc/user/api.html#nvim_get_current_buf()).
276///
277/// Gets the current buffer.
278pub fn get_current_buf() -> Buffer {
279    unsafe { nvim_get_current_buf() }.into()
280}
281
282/// Binding to [`nvim_get_current_line`](https://neovim.io/doc/user/api.html#nvim_get_current_line()).
283///
284/// Gets the current line in the current bufferr.
285pub fn get_current_line() -> Result<String> {
286    let mut err = nvim::Error::new();
287    let str = unsafe { nvim_get_current_line(&mut err) };
288    choose!(err, str.try_into().map_err(From::from))
289}
290
291/// Binding to [`nvim_get_current_tabpage`](https://neovim.io/doc/user/api.html#nvim_get_current_tabpage()).
292///
293/// Gets the current tabpage.
294pub fn get_current_tabpage() -> TabPage {
295    unsafe { nvim_get_current_tabpage() }.into()
296}
297
298/// Binding to [`nvim_get_current_win`](https://neovim.io/doc/user/api.html#nvim_get_current_win()).
299///
300/// Gets the current window.
301pub fn get_current_win() -> Window {
302    unsafe { nvim_get_current_win() }.into()
303}
304
305/// Binding to [`nvim_get_hl_by_id`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_id()).
306///
307/// Gets a highlight definition by id.
308pub fn get_hl_by_id(hl_id: u32, rgb: bool) -> Result<HighlightInfos> {
309    let mut err = nvim::Error::new();
310    let hl = unsafe { nvim_get_hl_by_id(hl_id.into(), rgb, &mut err) };
311    choose!(err, Ok(HighlightInfos::from_object(hl.into())?))
312}
313
314/// Binding to [`nvim_get_hl_by_name`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_name()).
315///
316/// Gets a highlight definition by name.
317pub fn get_hl_by_name(name: &str, rgb: bool) -> Result<HighlightInfos> {
318    let name = nvim::String::from(name);
319    let mut err = nvim::Error::new();
320    let hl = unsafe { nvim_get_hl_by_name(name.non_owning(), rgb, &mut err) };
321    choose!(err, Ok(HighlightInfos::from_object(hl.into())?))
322}
323
324/// Binding to [`nvim_get_hl_id_by_name`](https://neovim.io/doc/user/api.html#nvim_get_hl_id_by_name()).
325///
326/// Gets a highlight definition by name.
327pub fn get_hl_id_by_name(name: &str) -> Result<u32> {
328    let name = nvim::String::from(name);
329    let id = unsafe { nvim_get_hl_id_by_name(name.non_owning()) };
330    id.try_into().map_err(Into::into)
331}
332
333/// Binding to [`nvim_get_keymap`](https://neovim.io/doc/user/api.html#nvim_get_keymap()).
334///
335/// Returns an iterator over the global mapping definitions.
336pub fn get_keymap(mode: Mode) -> impl SuperIterator<KeymapInfos> {
337    let mode = nvim::String::from(mode);
338    unsafe { nvim_get_keymap(LUA_INTERNAL_CALL, mode.non_owning()) }
339        .into_iter()
340        .map(|obj| KeymapInfos::from_object(obj).unwrap())
341}
342
343/// Binding to [`nvim_get_mark`](https://neovim.io/doc/user/api.html#nvim_get_mark()).
344///
345/// Returns a tuple `(row, col, buffer, buffername)` representing the position
346/// of the named mark. Marks are (1,0)-indexed.
347pub fn get_mark(
348    name: char,
349    opts: &GetMarkOpts,
350) -> Result<(usize, usize, Buffer, String)> {
351    let name = nvim::String::from(name);
352    let opts = Dictionary::from(opts);
353    let mut err = nvim::Error::new();
354    let mark = unsafe {
355        nvim_get_mark(name.non_owning(), opts.non_owning(), &mut err)
356    };
357    choose!(err, {
358        let mut iter = mark.into_iter();
359        let row = usize::from_object(iter.next().expect("row is present"))?;
360        let col = usize::from_object(iter.next().expect("col is present"))?;
361        let buffer =
362            Buffer::from_object(iter.next().expect("buffer is present"))?;
363        let buffername =
364            String::from_object(iter.next().expect("buffername is present"))?;
365        Ok((row, col, buffer, buffername))
366    })
367}
368
369/// Binding to [`nvim_get_mode`](https://neovim.io/doc/user/api.html#nvim_get_mode()).
370///
371/// Gets the current mode. The [`blocking`](GotMode::blocking) field of
372/// [`GotMode`] is `true` if Neovim is waiting for input.
373pub fn get_mode() -> Result<GotMode> {
374    Ok(GotMode::from_object(unsafe { nvim_get_mode() }.into())?)
375}
376
377/// Binding to [`nvim_get_option`](https://neovim.io/doc/user/api.html#nvim_get_option()).
378///
379/// Gets the value of a global option.
380pub fn get_option<Opt>(name: &str) -> Result<Opt>
381where
382    Opt: FromObject,
383{
384    let name = nvim::String::from(name);
385    let mut err = nvim::Error::new();
386    let obj = unsafe { nvim_get_option(name.non_owning(), &mut err) };
387    choose!(err, Ok(Opt::from_object(obj)?))
388}
389
390/// Binding to [`nvim_get_option_info`](https://neovim.io/doc/user/api.html#nvim_get_option_info()).
391///
392/// Gets all the informations related to an option.
393pub fn get_option_info(name: &str) -> Result<OptionInfos> {
394    let name = nvim::String::from(name);
395    let mut err = nvim::Error::new();
396    let obj = unsafe { nvim_get_option_info(name.non_owning(), &mut err) };
397    choose!(err, Ok(OptionInfos::from_object(obj.into())?))
398}
399
400/// Binding to [`nvim_get_option_value`](https://neovim.io/doc/user/api.html#nvim_get_option_value()).
401///
402/// Gets the local value of an option if it exists, or the global value
403/// otherwise. Local values always correspond to the current buffer or window.
404///
405/// To get a buffer-local orr window-local option for a specific buffer of
406/// window consider using [`Buffer::get_option`] or [`Window::get_option`] instead.
407pub fn get_option_value<Opt>(name: &str, opts: &OptionValueOpts) -> Result<Opt>
408where
409    Opt: FromObject,
410{
411    let name = nvim::String::from(name);
412    let opts = KeyDict_option::from(opts);
413    let mut err = nvim::Error::new();
414    let obj =
415        unsafe { nvim_get_option_value(name.non_owning(), &opts, &mut err) };
416    choose!(err, Ok(Opt::from_object(obj)?))
417}
418
419/// Binding to [`nvim_get_proc`](https://neovim.io/doc/user/api.html#nvim_get_proc()).
420///
421/// Gets informations about a process with a given `pid`.
422pub fn get_proc(pid: u32) -> Result<ProcInfos> {
423    let mut err = nvim::Error::new();
424    let obj = unsafe { nvim_get_proc(pid.into(), &mut err) };
425    choose!(err, Ok(ProcInfos::from_object(obj)?))
426}
427
428/// Binding to [`nvim_get_proc_children`](https://neovim.io/doc/user/api.html#nvim_get_proc_children()).
429///
430/// Gets the immediate children of process `pid`.
431pub fn get_proc_children(pid: u32) -> Result<impl SuperIterator<u32>> {
432    let mut err = nvim::Error::new();
433    let procs = unsafe { nvim_get_proc_children(pid.into(), &mut err) };
434    choose!(
435        err,
436        Ok(procs.into_iter().map(|obj| u32::from_object(obj).unwrap()))
437    )
438}
439
440/// Binding to [`nvim_get_runtime_file`](https://neovim.io/doc/user/api.html#nvim_get_runtime_file()).
441///
442/// Returns an iterator over all the files matching `name` in the runtime path.
443pub fn get_runtime_file(
444    name: impl AsRef<Path>,
445    get_all: bool,
446) -> Result<impl SuperIterator<PathBuf>> {
447    let name = nvim::String::from(name.as_ref().to_owned());
448    let mut err = nvim::Error::new();
449    let files =
450        unsafe { nvim_get_runtime_file(name.non_owning(), get_all, &mut err) };
451    choose!(
452        err,
453        Ok({
454            files.into_iter().map(|obj| {
455                PathBuf::from(nvim::String::from_object(obj).unwrap())
456            })
457        })
458    )
459}
460
461/// Binding to [`nvim_get_var`](https://neovim.io/doc/user/api.html#nvim_get_var()).
462///
463/// Gets a global (`g:`) variable.
464pub fn get_var<Var>(name: &str) -> Result<Var>
465where
466    Var: FromObject,
467{
468    let mut err = nvim::Error::new();
469    let name = nvim::String::from(name);
470    let obj = unsafe { nvim_get_var(name.non_owning(), &mut err) };
471    choose!(err, Ok(Var::from_object(obj)?))
472}
473
474/// Binding to [`nvim_get_vvar`](https://neovim.io/doc/user/api.html#nvim_get_vvar()).
475///
476/// Gets a `v:` variable.
477pub fn get_vvar<Var>(name: &str) -> Result<Var>
478where
479    Var: FromObject,
480{
481    let name = nvim::String::from(name);
482    let mut err = nvim::Error::new();
483    let obj = unsafe { nvim_get_vvar(name.non_owning(), &mut err) };
484    choose!(err, Ok(Var::from_object(obj)?))
485}
486
487/// Binding to [`nvim_input`](https://neovim.io/doc/user/api.html#nvim_input()).
488///
489/// Queues raw user-input. Unlike [`api::feedkeys`](feedkeys) this uses a
490/// low-level input buffer and the call is non-blocking.
491///
492/// Returns the number of bytes written to the buffer.
493pub fn input<Input>(keys: Input) -> Result<usize>
494where
495    Input: Into<nvim::String>,
496{
497    unsafe { nvim_input(keys.into().non_owning()) }
498        .try_into()
499        .map_err(From::from)
500}
501
502/// Binding to [`nvim_input_mouse`](https://neovim.io/doc/user/api.html#nvim_input_mouse()).
503///
504/// Send mouse event from GUI. The call is non-blocking.
505pub fn input_mouse(
506    button: MouseButton,
507    action: MouseAction,
508    modifier: &str,
509    grid: u32,
510    row: usize,
511    col: usize,
512) -> Result<()> {
513    let button = nvim::String::from(button);
514    let action = nvim::String::from(action);
515    let modifier = nvim::String::from(modifier);
516    let mut err = nvim::Error::new();
517    unsafe {
518        nvim_input_mouse(
519            button.non_owning(),
520            action.non_owning(),
521            modifier.non_owning(),
522            grid.into(),
523            row.try_into()?,
524            col.try_into()?,
525            &mut err,
526        )
527    };
528    choose!(err, ())
529}
530
531/// Binding to [`nvim_list_bufs`](https://neovim.io/doc/user/api.html#nvim_list_bufs()).
532///
533/// Gets the current list of [`Buffer`]s, including unlisted (unloaded/deleted)
534/// buffers (like `:ls!`). Use [`Buffer::is_loaded`] to check if a
535/// buffer is loaded.
536pub fn list_bufs() -> impl SuperIterator<Buffer> {
537    unsafe { nvim_list_bufs() }
538        .into_iter()
539        .map(|obj| Buffer::from_object(obj).unwrap())
540}
541
542/// Binding to [`nvim_list_chans`](https://neovim.io/doc/user/api.html#nvim_list_chans()).
543///
544/// Returns an iterator over the informations about all the open channels.
545pub fn list_chans() -> impl SuperIterator<ChannelInfos> {
546    unsafe { nvim_list_chans() }
547        .into_iter()
548        .map(|obj| ChannelInfos::from_object(obj).unwrap())
549}
550
551/// Binding to [`nvim_list_runtime_paths`](https://neovim.io/doc/user/api.html#nvim_list_runtime_paths()).
552///
553/// Gets the paths contained in https://neovim's runtimepath.
554pub fn list_runtime_paths() -> Result<impl SuperIterator<PathBuf>> {
555    let mut err = nvim::Error::new();
556    let paths = unsafe { nvim_list_runtime_paths(&mut err) };
557    choose!(
558        err,
559        Ok({
560            paths.into_iter().map(|obj| {
561                PathBuf::from(nvim::String::from_object(obj).unwrap())
562            })
563        })
564    )
565}
566
567/// Binding to [`nvim_list_bufs`](https://neovim.io/doc/user/api.html#nvim_list_bufs()).
568///
569/// Gets the current list of `Tabpage`s.
570pub fn list_tabpages() -> impl SuperIterator<TabPage> {
571    unsafe { nvim_list_tabpages() }
572        .into_iter()
573        .map(|obj| TabPage::from_object(obj).unwrap())
574}
575
576/// Binding to [`nvim_list_uis`](https://neovim.io/doc/user/api.html#nvim_list_uis()).
577///
578/// Returns an iterator over the informations about all the attached UIs.
579pub fn list_uis() -> impl SuperIterator<UiInfos> {
580    unsafe { nvim_list_uis() }
581        .into_iter()
582        .map(|obj| UiInfos::from_object(obj).unwrap())
583}
584
585/// Binding to [`nvim_list_wins`](https://neovim.io/doc/user/api.html#nvim_list_wins()).
586///
587/// Gets the current list of `Window`s.
588pub fn list_wins() -> impl SuperIterator<Window> {
589    unsafe { nvim_list_wins() }
590        .into_iter()
591        .map(|obj| Window::from_object(obj).unwrap())
592}
593
594/// Binding to [`nvim_load_context`](https://neovim.io/doc/user/api.html#nvim_load_context()).
595///
596/// Sets the current editor state from the given [`EditorContext`].
597pub fn load_context(ctx: EditorContext) {
598    let ctx = Dictionary::from(ctx);
599    let _ = unsafe { nvim_load_context(ctx.non_owning()) };
600}
601
602/// Binding to [`nvim_notify`](https://neovim.io/doc/user/api.html#nvim_notify()).
603pub fn notify(
604    msg: &str,
605    log_level: LogLevel,
606    opts: &NotifyOpts,
607) -> Result<()> {
608    let msg = nvim::String::from(msg);
609    let opts = Dictionary::from(opts);
610    let mut err = nvim::Error::new();
611    let _ = unsafe {
612        nvim_notify(
613            msg.non_owning(),
614            log_level as Integer,
615            opts.non_owning(),
616            &mut err,
617        )
618    };
619    choose!(err, ())
620}
621
622/// Binding to [`nvim_open_term`](https://neovim.io/doc/user/api.html#nvim_open_term()).
623///
624/// Opens a terminal instance in a buffer. Returns the id of a channel that can
625/// be used to send data to the instance via
626/// [`nvim_oxi::api::chan_send`](chan_send).
627pub fn open_term(buffer: &Buffer, opts: &OpenTermOpts) -> Result<u32> {
628    let opts = Dictionary::from(opts);
629    let mut err = nvim::Error::new();
630    let channel_id =
631        unsafe { nvim_open_term(buffer.0, opts.non_owning(), &mut err) };
632    choose!(
633        err,
634        match channel_id {
635            0 => Err(Error::custom("Couldn't create terminal instance")),
636            other => Ok(other.try_into().expect("always positive")),
637        }
638    )
639}
640
641/// Binding to [`nvim_out_write`](https://neovim.io/doc/user/api.html#nvim_out_write()).
642///
643/// Writes a message to the Vim output buffer, without appending a "\n". The
644/// message is buffered and won't be displayed until a linefeed is written.
645pub fn out_write<Msg>(str: Msg)
646where
647    Msg: Into<nvim::String>,
648{
649    unsafe { nvim_out_write(str.into().non_owning()) }
650}
651
652/// Binding to [`nvim_paste`](https://neovim.io/doc/user/api.html#nvim_paste()).
653///
654/// Returns `true` if the client may continue the paste, `false` if it must
655/// cancel it.
656pub fn paste<Data>(data: Data, crlf: bool, phase: PastePhase) -> Result<bool>
657where
658    Data: Into<nvim::String>,
659{
660    let mut err = nvim::Error::new();
661    let go_on = unsafe {
662        nvim_paste(data.into().non_owning(), crlf, phase as Integer, &mut err)
663    };
664    choose!(err, Ok(go_on))
665}
666
667/// Binding to [`nvim_put`](https://neovim.io/doc/user/api.html#nvim_put()).
668///
669/// Puts text at cursor, in any mode.
670pub fn put<Line, Lines>(
671    lines: Lines,
672    reg_type: RegisterType,
673    after: bool,
674    follow: bool,
675) -> Result<()>
676where
677    Lines: Iterator<Item = Line>,
678    Line: Into<nvim::String>,
679{
680    let lines = lines.into_iter().map(Into::into).collect::<Array>();
681    let reg_type = nvim::String::from(reg_type);
682    let mut err = nvim::Error::new();
683    unsafe {
684        nvim_put(
685            lines.non_owning(),
686            reg_type.non_owning(),
687            after,
688            follow,
689            &mut err,
690        )
691    };
692    choose!(err, ())
693}
694
695/// Binding to [`nvim_replace_termcodes`](https://neovim.io/doc/user/api.html#nvim_replace_termcodes()).
696///
697/// Replaces terminal codes and keycodes (`<CR>`, `<Esc>`, ...) in a string
698/// with the internal representation.
699pub fn replace_termcodes<Input>(
700    str: Input,
701    from_part: bool,
702    do_lt: bool,
703    special: bool,
704) -> nvim::String
705where
706    Input: Into<nvim::String>,
707{
708    let str = str.into();
709    unsafe {
710        nvim_replace_termcodes(str.non_owning(), from_part, do_lt, special)
711    }
712}
713
714/// Binding to [`nvim_select_popupmenu_item`](https://neovim.io/doc/user/api.html#nvim_select_popupmenu_item()).
715///
716/// Selects an item in the completion popupmenu.
717pub fn select_popupmenu_item(
718    item: usize,
719    insert: bool,
720    finish: bool,
721    opts: &SelectPopupMenuItemOpts,
722) -> Result<()> {
723    let opts = Dictionary::from(opts);
724    let mut err = nvim::Error::new();
725    unsafe {
726        nvim_select_popupmenu_item(
727            item.try_into()?,
728            insert,
729            finish,
730            opts.non_owning(),
731            &mut err,
732        )
733    };
734    choose!(err, ())
735}
736
737/// Binding to [`nvim_set_current_buf`](https://neovim.io/doc/user/api.html#nvim_set_current_buf()).
738///
739/// Sets the current buffer.
740pub fn set_current_buf(buf: &Buffer) -> Result<()> {
741    let mut err = nvim::Error::new();
742    unsafe { nvim_set_current_buf(buf.0, &mut err) };
743    choose!(err, ())
744}
745
746/// Binding to [`nvim_set_current_dir`](https://neovim.io/doc/user/api.html#nvim_set_current_dir()).
747///
748/// Changes the global working directory.
749pub fn set_current_dir<Dir>(dir: Dir) -> Result<()>
750where
751    Dir: AsRef<Path>,
752{
753    let dir = nvim::String::from(dir.as_ref().to_owned());
754    let mut err = nvim::Error::new();
755    unsafe { nvim_set_current_dir(dir.non_owning(), &mut err) };
756    choose!(err, ())
757}
758
759/// Binding to [`nvim_set_current_line`](https://neovim.io/doc/user/api.html#nvim_set_current_line()).
760///
761/// Sets the current line.
762pub fn set_current_line<Line>(line: Line) -> Result<()>
763where
764    Line: Into<nvim::String>,
765{
766    let mut err = nvim::Error::new();
767    unsafe { nvim_set_current_line(line.into().non_owning(), &mut err) };
768    choose!(err, ())
769}
770
771/// Binding to [`nvim_set_current_tabpage`](https://neovim.io/doc/user/api.html#nvim_set_current_tabpage()).
772///
773/// Sets the current tabpage.
774pub fn set_current_tabpage(tabpage: &TabPage) -> Result<()> {
775    let mut err = nvim::Error::new();
776    unsafe { nvim_set_current_tabpage(tabpage.0, &mut err) };
777    choose!(err, ())
778}
779
780/// Binding to [`nvim_set_current_win`](https://neovim.io/doc/user/api.html#nvim_set_current_win()).
781///
782/// Sets the current window.
783pub fn set_current_win(win: &Window) -> Result<()> {
784    let mut err = nvim::Error::new();
785    unsafe { nvim_set_current_win(win.0, &mut err) };
786    choose!(err, ())
787}
788
789/// Binding to [`nvim_set_hl`](https://neovim.io/doc/user/api.html#nvim_set_hl()).
790///
791/// Sets a highlight group.
792pub fn set_hl(ns_id: u32, name: &str, opts: &SetHighlightOpts) -> Result<()> {
793    let name = nvim::String::from(name);
794    let opts = KeyDict_highlight::from(opts);
795    let mut err = nvim::Error::new();
796    unsafe {
797        nvim_set_hl(ns_id as Integer, name.non_owning(), &opts, &mut err)
798    };
799    choose!(err, ())
800}
801
802/// Binding to [`nvim_set_keymap`](https://neovim.io/doc/user/api.html#nvim_set_keymap()).
803///
804/// Sets a global mapping for the given mode. To set a buffer-local mapping use
805/// [`Buffer::set_keymap`] instead.
806pub fn set_keymap(
807    mode: Mode,
808    lhs: &str,
809    rhs: &str,
810    opts: &SetKeymapOpts,
811) -> Result<()> {
812    let mode = nvim::String::from(mode);
813    let lhs = nvim::String::from(lhs);
814    let rhs = nvim::String::from(rhs);
815    let opts = KeyDict_keymap::from(opts);
816    let mut err = nvim::Error::new();
817    unsafe {
818        nvim_set_keymap(
819            LUA_INTERNAL_CALL,
820            mode.non_owning(),
821            lhs.non_owning(),
822            rhs.non_owning(),
823            &opts,
824            &mut err,
825        )
826    };
827    choose!(err, ())
828}
829
830/// Binding to [`nvim_set_option`](https://neovim.io/doc/user/api.html#nvim_set_option()).
831///
832/// Sets the global value of an option.
833pub fn set_option<Opt>(name: &str, value: Opt) -> Result<()>
834where
835    Opt: ToObject,
836{
837    let name = nvim::String::from(name);
838    let mut err = nvim::Error::new();
839    unsafe {
840        nvim_set_option(
841            LUA_INTERNAL_CALL,
842            name.non_owning(),
843            value.to_object()?.non_owning(),
844            &mut err,
845        )
846    };
847    choose!(err, ())
848}
849
850/// Binding to [`nvim_set_option_value`](https://neovim.io/doc/user/api.html#nvim_set_option_value()).
851///
852/// Sets the value of an option. The behaviour of this function matches that of
853/// `:set`: for global-local options, both the global and local value are set
854/// unless specified otherwise in the [`scope`](OptionValueOptsBuilder::scope)
855/// field of `opts`.
856pub fn set_option_value<Opt>(
857    name: &str,
858    value: Opt,
859    opts: &OptionValueOpts,
860) -> Result<()>
861where
862    Opt: ToObject,
863{
864    let name = nvim::String::from(name);
865    let opts = KeyDict_option::from(opts);
866    let mut err = nvim::Error::new();
867    unsafe {
868        nvim_set_option_value(
869            name.non_owning(),
870            value.to_object()?.non_owning(),
871            &opts,
872            &mut err,
873        )
874    };
875    choose!(err, ())
876}
877
878/// Binding to [`nvim_set_var`](https://neovim.io/doc/user/api.html#nvim_set_var()).
879///
880/// Sets a global (`g:`) variable.
881pub fn set_var<Var>(name: &str, value: Var) -> Result<()>
882where
883    Var: ToObject,
884{
885    let name = nvim::String::from(name);
886    let value = value.to_object()?;
887    let mut err = nvim::Error::new();
888    unsafe { nvim_set_var(name.non_owning(), value.non_owning(), &mut err) };
889    choose!(err, ())
890}
891
892/// Binding to [`nvim_set_vvar`](https://neovim.io/doc/user/api.html#nvim_set_vvar()).
893///
894/// Sets a `v:` variable, if it's not readonly.
895pub fn set_vvar<Var>(name: &str, value: Var) -> Result<()>
896where
897    Var: ToObject,
898{
899    let name = nvim::String::from(name);
900    let value = value.to_object()?;
901    let mut err = nvim::Error::new();
902    unsafe { nvim_set_vvar(name.non_owning(), value.non_owning(), &mut err) };
903    choose!(err, ())
904}
905
906/// Binding to [`nvim_strwidth`](https://neovim.io/doc/user/api.html#nvim_strwidth()).
907///
908/// Calculates the number of display cells occupied by `text`. Control
909/// characters like `<Tab>` count as one cell.
910pub fn strwidth(text: &str) -> Result<usize> {
911    let text = nvim::String::from(text);
912    let mut err = nvim::Error::new();
913    let width = unsafe { nvim_strwidth(text.non_owning(), &mut err) };
914    choose!(err, Ok(width.try_into().expect("always positive")))
915}