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
22pub 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
34pub 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
45pub 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
56pub 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
77pub 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
97pub 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
109pub 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
139pub fn err_write(str: &str) {
147 unsafe { nvim_err_write(nvim::String::from(str).as_nvim_str()) }
148}
149
150pub fn err_writeln(str: &str) {
157 unsafe { nvim_err_writeln(nvim::String::from(str).as_nvim_str()) }
158}
159
160pub 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
177pub 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
188pub 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
199pub 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
213pub 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
225pub 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
236pub fn get_current_buf() -> Buffer {
242 unsafe { nvim_get_current_buf() }.into()
243}
244
245pub 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
256pub fn get_current_tabpage() -> TabPage {
262 unsafe { nvim_get_current_tabpage() }.into()
263}
264
265pub fn get_current_win() -> Window {
271 unsafe { nvim_get_current_win() }.into()
272}
273
274pub 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
315pub 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
326pub 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
337pub 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
349pub 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
376pub fn get_mode() -> Result<GotMode> {
383 unsafe { nvim_get_mode(types::arena()) }.try_into().map_err(Into::into)
384}
385
386pub 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
397pub 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
413pub 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
442pub 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
458pub 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
474pub 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")] LUA_INTERNAL_CALL,
490 keys.into().as_nvim_str(),
491 )
492 }
493 .try_into()
494 .map_err(From::from)
495}
496
497pub 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
528pub 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
541pub fn list_chans() -> impl SuperIterator<ChannelInfos> {
547 unsafe { nvim_list_chans() }
548 .into_iter()
549 .map(|obj| ChannelInfos::from_object(obj).unwrap())
550}
551
552pub 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
570pub fn list_tabpages() -> impl SuperIterator<TabPage> {
576 unsafe { nvim_list_tabpages() }
577 .into_iter()
578 .map(|obj| TabPage::from_object(obj).unwrap())
579}
580
581pub 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
592pub 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
603pub fn load_context(ctx: EditorContext) {
609 let ctx = Dictionary::from(ctx);
610 let _ = unsafe { nvim_load_context(ctx.non_owning()) };
611}
612
613pub 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
635pub 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
654pub 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
667pub 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
690pub 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
720pub 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
741pub 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
765pub 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
776pub 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
791pub 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
811pub 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
822pub 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
833pub 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
853pub 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
865pub 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
882pub 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
911pub 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
927pub 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
943pub 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}