nvim_oxi_api/
vim.rs

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