use std::path::{Path, PathBuf};
use nvim_types::{
self as nvim,
conversion::{FromObject, ToObject},
Array,
Dictionary,
Integer,
Object,
};
use crate::choose;
use crate::ffi::global::*;
use crate::iterator::SuperIterator;
use crate::opts::*;
use crate::types::*;
use crate::StringOrFunction;
use crate::LUA_INTERNAL_CALL;
use crate::{Buffer, TabPage, Window};
use crate::{Error, Result};
pub fn chan_send(channel_id: u32, data: &str) -> Result<()> {
let mut err = nvim::Error::new();
let data = nvim::String::from(data);
unsafe { nvim_chan_send(channel_id.into(), data.non_owning(), &mut err) };
choose!(err, ())
}
pub fn create_buf(is_listed: bool, is_scratch: bool) -> Result<Buffer> {
let mut err = nvim::Error::new();
let handle = unsafe { nvim_create_buf(is_listed, is_scratch, &mut err) };
choose!(err, Ok(handle.into()))
}
pub fn create_user_command<Cmd>(
name: &str,
command: Cmd,
opts: &CreateCommandOpts,
) -> Result<()>
where
Cmd: StringOrFunction<CommandArgs, ()>,
{
let name = nvim::String::from(name);
let command = command.to_object();
let opts = KeyDict_user_command::from(opts);
let mut err = nvim::Error::new();
unsafe {
nvim_create_user_command(
name.non_owning(),
command.non_owning(),
&opts,
&mut err,
)
};
choose!(err, ())
}
pub fn del_current_line() -> Result<()> {
let mut err = nvim::Error::new();
unsafe { nvim_del_current_line(&mut err) };
choose!(err, ())
}
pub fn del_keymap(mode: Mode, lhs: &str) -> Result<()> {
let mode = nvim::String::from(mode);
let lhs = nvim::String::from(lhs);
let mut err = nvim::Error::new();
unsafe {
nvim_del_keymap(
LUA_INTERNAL_CALL,
mode.non_owning(),
lhs.non_owning(),
&mut err,
)
};
choose!(err, ())
}
pub fn del_mark(name: char) -> Result<()> {
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
let was_deleted = unsafe { nvim_del_mark(name.non_owning(), &mut err) };
choose!(
err,
match was_deleted {
true => Ok(()),
_ => Err(Error::custom("Couldn't delete mark")),
}
)
}
pub fn del_user_command(name: &str) -> Result<()> {
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
unsafe { nvim_del_user_command(name.non_owning(), &mut err) };
choose!(err, ())
}
pub fn del_var(name: &str) -> Result<()> {
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
unsafe { nvim_del_var(name.non_owning(), &mut err) };
choose!(err, ())
}
pub fn echo<'hl, Text, Chunks>(chunks: Chunks, history: bool) -> Result<()>
where
Chunks: IntoIterator<Item = (Text, Option<&'hl str>)>,
Text: Into<nvim::String>,
{
let chunks = chunks
.into_iter()
.map(|(text, hlgroup)| {
Array::from_iter([
Object::from(text.into()),
Object::from(hlgroup.map(|hl| hl.to_owned())),
])
})
.collect::<Array>();
let mut err = nvim::Error::new();
let opts = Dictionary::new();
unsafe {
nvim_echo(chunks.non_owning(), history, opts.non_owning(), &mut err)
};
choose!(err, ())
}
pub fn err_write(str: &str) {
unsafe { nvim_err_write(nvim::String::from(str).non_owning()) }
}
pub fn err_writeln(str: &str) {
unsafe { nvim_err_writeln(nvim::String::from(str).non_owning()) }
}
pub fn eval_statusline(
str: &str,
opts: &EvalStatuslineOpts,
) -> Result<StatuslineInfos> {
let str = nvim::String::from(str);
let opts = KeyDict_eval_statusline::from(opts);
let mut err = nvim::Error::new();
let dict =
unsafe { nvim_eval_statusline(str.non_owning(), &opts, &mut err) };
choose!(err, Ok(StatuslineInfos::from_object(dict.into())?))
}
pub fn feedkeys(keys: &str, mode: Mode, escape_ks: bool) {
let keys = nvim::String::from(keys);
let mode = nvim::String::from(mode);
unsafe { nvim_feedkeys(keys.non_owning(), mode.non_owning(), escape_ks) }
}
pub fn get_all_options_info() -> Result<impl SuperIterator<OptionInfos>> {
let mut err = nvim::Error::new();
let infos = unsafe { nvim_get_all_options_info(&mut err) };
choose!(
err,
Ok({
infos
.into_iter()
.map(|(_, optinf)| OptionInfos::from_object(optinf).unwrap())
})
)
}
pub fn get_chan_info(channel_id: u32) -> Result<ChannelInfos> {
let mut err = nvim::Error::new();
let infos = unsafe { nvim_get_chan_info(channel_id.into(), &mut err) };
choose!(err, Ok(ChannelInfos::from_object(infos.into())?))
}
pub fn get_color_by_name(name: &str) -> Result<u32> {
let name = nvim::String::from(name);
let color = unsafe { nvim_get_color_by_name(name.non_owning()) };
(color != -1).then(|| color.try_into().unwrap()).ok_or_else(|| {
Error::custom(format!("{name} is not a valid color name"))
})
}
pub fn get_color_map() -> impl SuperIterator<(String, u32)> {
unsafe { nvim_get_color_map() }.into_iter().map(|(k, v)| {
(String::try_from(k).unwrap(), u32::from_object(v).unwrap())
})
}
pub fn get_commands(
opts: &GetCommandsOpts,
) -> Result<impl SuperIterator<CommandInfos>> {
let opts = KeyDict_get_commands::from(opts);
let mut err = nvim::Error::new();
let cmds = unsafe { nvim_get_commands(&opts, &mut err) };
choose!(
err,
Ok({
cmds.into_iter()
.map(|(_, cmd)| CommandInfos::from_object(cmd).unwrap())
})
)
}
pub fn get_context(opts: &GetContextOpts) -> Result<EditorContext> {
let opts = KeyDict_context::from(opts);
let mut err = nvim::Error::new();
let ctx = unsafe { nvim_get_context(&opts, &mut err) };
choose!(err, Ok(EditorContext::from_object(ctx.into())?))
}
pub fn get_current_buf() -> Buffer {
unsafe { nvim_get_current_buf() }.into()
}
pub fn get_current_line() -> Result<String> {
let mut err = nvim::Error::new();
let str = unsafe { nvim_get_current_line(&mut err) };
choose!(err, str.try_into().map_err(From::from))
}
pub fn get_current_tabpage() -> TabPage {
unsafe { nvim_get_current_tabpage() }.into()
}
pub fn get_current_win() -> Window {
unsafe { nvim_get_current_win() }.into()
}
pub fn get_hl_by_id(hl_id: u32, rgb: bool) -> Result<HighlightInfos> {
let mut err = nvim::Error::new();
let hl = unsafe { nvim_get_hl_by_id(hl_id.into(), rgb, &mut err) };
choose!(err, Ok(HighlightInfos::from_object(hl.into())?))
}
pub fn get_hl_by_name(name: &str, rgb: bool) -> Result<HighlightInfos> {
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
let hl = unsafe { nvim_get_hl_by_name(name.non_owning(), rgb, &mut err) };
choose!(err, Ok(HighlightInfos::from_object(hl.into())?))
}
pub fn get_hl_id_by_name(name: &str) -> Result<u32> {
let name = nvim::String::from(name);
let id = unsafe { nvim_get_hl_id_by_name(name.non_owning()) };
id.try_into().map_err(Into::into)
}
pub fn get_keymap(mode: Mode) -> impl SuperIterator<KeymapInfos> {
let mode = nvim::String::from(mode);
unsafe { nvim_get_keymap(LUA_INTERNAL_CALL, mode.non_owning()) }
.into_iter()
.map(|obj| KeymapInfos::from_object(obj).unwrap())
}
pub fn get_mark(
name: char,
opts: &GetMarkOpts,
) -> Result<(usize, usize, Buffer, String)> {
let name = nvim::String::from(name);
let opts = Dictionary::from(opts);
let mut err = nvim::Error::new();
let mark = unsafe {
nvim_get_mark(name.non_owning(), opts.non_owning(), &mut err)
};
choose!(err, {
let mut iter = mark.into_iter();
let row = usize::from_object(iter.next().expect("row is present"))?;
let col = usize::from_object(iter.next().expect("col is present"))?;
let buffer =
Buffer::from_object(iter.next().expect("buffer is present"))?;
let buffername =
String::from_object(iter.next().expect("buffername is present"))?;
Ok((row, col, buffer, buffername))
})
}
pub fn get_mode() -> Result<GotMode> {
Ok(GotMode::from_object(unsafe { nvim_get_mode() }.into())?)
}
pub fn get_option<Opt>(name: &str) -> Result<Opt>
where
Opt: FromObject,
{
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
let obj = unsafe { nvim_get_option(name.non_owning(), &mut err) };
choose!(err, Ok(Opt::from_object(obj)?))
}
pub fn get_option_info(name: &str) -> Result<OptionInfos> {
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
let obj = unsafe { nvim_get_option_info(name.non_owning(), &mut err) };
choose!(err, Ok(OptionInfos::from_object(obj.into())?))
}
pub fn get_option_value<Opt>(name: &str, opts: &OptionValueOpts) -> Result<Opt>
where
Opt: FromObject,
{
let name = nvim::String::from(name);
let opts = KeyDict_option::from(opts);
let mut err = nvim::Error::new();
let obj =
unsafe { nvim_get_option_value(name.non_owning(), &opts, &mut err) };
choose!(err, Ok(Opt::from_object(obj)?))
}
pub fn get_proc(pid: u32) -> Result<ProcInfos> {
let mut err = nvim::Error::new();
let obj = unsafe { nvim_get_proc(pid.into(), &mut err) };
choose!(err, Ok(ProcInfos::from_object(obj)?))
}
pub fn get_proc_children(pid: u32) -> Result<impl SuperIterator<u32>> {
let mut err = nvim::Error::new();
let procs = unsafe { nvim_get_proc_children(pid.into(), &mut err) };
choose!(
err,
Ok(procs.into_iter().map(|obj| u32::from_object(obj).unwrap()))
)
}
pub fn get_runtime_file(
name: impl AsRef<Path>,
get_all: bool,
) -> Result<impl SuperIterator<PathBuf>> {
let name = nvim::String::from(name.as_ref().to_owned());
let mut err = nvim::Error::new();
let files =
unsafe { nvim_get_runtime_file(name.non_owning(), get_all, &mut err) };
choose!(
err,
Ok({
files.into_iter().map(|obj| {
PathBuf::from(nvim::String::from_object(obj).unwrap())
})
})
)
}
pub fn get_var<Var>(name: &str) -> Result<Var>
where
Var: FromObject,
{
let mut err = nvim::Error::new();
let name = nvim::String::from(name);
let obj = unsafe { nvim_get_var(name.non_owning(), &mut err) };
choose!(err, Ok(Var::from_object(obj)?))
}
pub fn get_vvar<Var>(name: &str) -> Result<Var>
where
Var: FromObject,
{
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
let obj = unsafe { nvim_get_vvar(name.non_owning(), &mut err) };
choose!(err, Ok(Var::from_object(obj)?))
}
pub fn input<Input>(keys: Input) -> Result<usize>
where
Input: Into<nvim::String>,
{
unsafe { nvim_input(keys.into().non_owning()) }
.try_into()
.map_err(From::from)
}
pub fn input_mouse(
button: MouseButton,
action: MouseAction,
modifier: &str,
grid: u32,
row: usize,
col: usize,
) -> Result<()> {
let button = nvim::String::from(button);
let action = nvim::String::from(action);
let modifier = nvim::String::from(modifier);
let mut err = nvim::Error::new();
unsafe {
nvim_input_mouse(
button.non_owning(),
action.non_owning(),
modifier.non_owning(),
grid.into(),
row.try_into()?,
col.try_into()?,
&mut err,
)
};
choose!(err, ())
}
pub fn list_bufs() -> impl SuperIterator<Buffer> {
unsafe { nvim_list_bufs() }
.into_iter()
.map(|obj| Buffer::from_object(obj).unwrap())
}
pub fn list_chans() -> impl SuperIterator<ChannelInfos> {
unsafe { nvim_list_chans() }
.into_iter()
.map(|obj| ChannelInfos::from_object(obj).unwrap())
}
pub fn list_runtime_paths() -> Result<impl SuperIterator<PathBuf>> {
let mut err = nvim::Error::new();
let paths = unsafe { nvim_list_runtime_paths(&mut err) };
choose!(
err,
Ok({
paths.into_iter().map(|obj| {
PathBuf::from(nvim::String::from_object(obj).unwrap())
})
})
)
}
pub fn list_tabpages() -> impl SuperIterator<TabPage> {
unsafe { nvim_list_tabpages() }
.into_iter()
.map(|obj| TabPage::from_object(obj).unwrap())
}
pub fn list_uis() -> impl SuperIterator<UiInfos> {
unsafe { nvim_list_uis() }
.into_iter()
.map(|obj| UiInfos::from_object(obj).unwrap())
}
pub fn list_wins() -> impl SuperIterator<Window> {
unsafe { nvim_list_wins() }
.into_iter()
.map(|obj| Window::from_object(obj).unwrap())
}
pub fn load_context(ctx: EditorContext) {
let ctx = Dictionary::from(ctx);
let _ = unsafe { nvim_load_context(ctx.non_owning()) };
}
pub fn notify(
msg: &str,
log_level: LogLevel,
opts: &NotifyOpts,
) -> Result<()> {
let msg = nvim::String::from(msg);
let opts = Dictionary::from(opts);
let mut err = nvim::Error::new();
let _ = unsafe {
nvim_notify(
msg.non_owning(),
log_level as Integer,
opts.non_owning(),
&mut err,
)
};
choose!(err, ())
}
pub fn open_term(buffer: &Buffer, opts: &OpenTermOpts) -> Result<u32> {
let opts = Dictionary::from(opts);
let mut err = nvim::Error::new();
let channel_id =
unsafe { nvim_open_term(buffer.0, opts.non_owning(), &mut err) };
choose!(
err,
match channel_id {
0 => Err(Error::custom("Couldn't create terminal instance")),
other => Ok(other.try_into().expect("always positive")),
}
)
}
pub fn out_write<Msg>(str: Msg)
where
Msg: Into<nvim::String>,
{
unsafe { nvim_out_write(str.into().non_owning()) }
}
pub fn paste<Data>(data: Data, crlf: bool, phase: PastePhase) -> Result<bool>
where
Data: Into<nvim::String>,
{
let mut err = nvim::Error::new();
let go_on = unsafe {
nvim_paste(data.into().non_owning(), crlf, phase as Integer, &mut err)
};
choose!(err, Ok(go_on))
}
pub fn put<Line, Lines>(
lines: Lines,
reg_type: RegisterType,
after: bool,
follow: bool,
) -> Result<()>
where
Lines: Iterator<Item = Line>,
Line: Into<nvim::String>,
{
let lines = lines.into_iter().map(Into::into).collect::<Array>();
let reg_type = nvim::String::from(reg_type);
let mut err = nvim::Error::new();
unsafe {
nvim_put(
lines.non_owning(),
reg_type.non_owning(),
after,
follow,
&mut err,
)
};
choose!(err, ())
}
pub fn replace_termcodes<Input>(
str: Input,
from_part: bool,
do_lt: bool,
special: bool,
) -> nvim::String
where
Input: Into<nvim::String>,
{
let str = str.into();
unsafe {
nvim_replace_termcodes(str.non_owning(), from_part, do_lt, special)
}
}
pub fn select_popupmenu_item(
item: usize,
insert: bool,
finish: bool,
opts: &SelectPopupMenuItemOpts,
) -> Result<()> {
let opts = Dictionary::from(opts);
let mut err = nvim::Error::new();
unsafe {
nvim_select_popupmenu_item(
item.try_into()?,
insert,
finish,
opts.non_owning(),
&mut err,
)
};
choose!(err, ())
}
pub fn set_current_buf(buf: &Buffer) -> Result<()> {
let mut err = nvim::Error::new();
unsafe { nvim_set_current_buf(buf.0, &mut err) };
choose!(err, ())
}
pub fn set_current_dir<Dir>(dir: Dir) -> Result<()>
where
Dir: AsRef<Path>,
{
let dir = nvim::String::from(dir.as_ref().to_owned());
let mut err = nvim::Error::new();
unsafe { nvim_set_current_dir(dir.non_owning(), &mut err) };
choose!(err, ())
}
pub fn set_current_line<Line>(line: Line) -> Result<()>
where
Line: Into<nvim::String>,
{
let mut err = nvim::Error::new();
unsafe { nvim_set_current_line(line.into().non_owning(), &mut err) };
choose!(err, ())
}
pub fn set_current_tabpage(tabpage: &TabPage) -> Result<()> {
let mut err = nvim::Error::new();
unsafe { nvim_set_current_tabpage(tabpage.0, &mut err) };
choose!(err, ())
}
pub fn set_current_win(win: &Window) -> Result<()> {
let mut err = nvim::Error::new();
unsafe { nvim_set_current_win(win.0, &mut err) };
choose!(err, ())
}
pub fn set_hl(ns_id: u32, name: &str, opts: &SetHighlightOpts) -> Result<()> {
let name = nvim::String::from(name);
let opts = KeyDict_highlight::from(opts);
let mut err = nvim::Error::new();
unsafe {
nvim_set_hl(ns_id as Integer, name.non_owning(), &opts, &mut err)
};
choose!(err, ())
}
pub fn set_keymap(
mode: Mode,
lhs: &str,
rhs: &str,
opts: &SetKeymapOpts,
) -> Result<()> {
let mode = nvim::String::from(mode);
let lhs = nvim::String::from(lhs);
let rhs = nvim::String::from(rhs);
let opts = KeyDict_keymap::from(opts);
let mut err = nvim::Error::new();
unsafe {
nvim_set_keymap(
LUA_INTERNAL_CALL,
mode.non_owning(),
lhs.non_owning(),
rhs.non_owning(),
&opts,
&mut err,
)
};
choose!(err, ())
}
pub fn set_option<Opt>(name: &str, value: Opt) -> Result<()>
where
Opt: ToObject,
{
let name = nvim::String::from(name);
let mut err = nvim::Error::new();
unsafe {
nvim_set_option(
LUA_INTERNAL_CALL,
name.non_owning(),
value.to_object()?.non_owning(),
&mut err,
)
};
choose!(err, ())
}
pub fn set_option_value<Opt>(
name: &str,
value: Opt,
opts: &OptionValueOpts,
) -> Result<()>
where
Opt: ToObject,
{
let name = nvim::String::from(name);
let opts = KeyDict_option::from(opts);
let mut err = nvim::Error::new();
unsafe {
nvim_set_option_value(
name.non_owning(),
value.to_object()?.non_owning(),
&opts,
&mut err,
)
};
choose!(err, ())
}
pub fn set_var<Var>(name: &str, value: Var) -> Result<()>
where
Var: ToObject,
{
let name = nvim::String::from(name);
let value = value.to_object()?;
let mut err = nvim::Error::new();
unsafe { nvim_set_var(name.non_owning(), value.non_owning(), &mut err) };
choose!(err, ())
}
pub fn set_vvar<Var>(name: &str, value: Var) -> Result<()>
where
Var: ToObject,
{
let name = nvim::String::from(name);
let value = value.to_object()?;
let mut err = nvim::Error::new();
unsafe { nvim_set_vvar(name.non_owning(), value.non_owning(), &mut err) };
choose!(err, ())
}
pub fn strwidth(text: &str) -> Result<usize> {
let text = nvim::String::from(text);
let mut err = nvim::Error::new();
let width = unsafe { nvim_strwidth(text.non_owning(), &mut err) };
choose!(err, Ok(width.try_into().expect("always positive")))
}