1use std::path::{Path, PathBuf};
2
3use 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::vim::*;
14use crate::opts::*;
15use crate::types::*;
16use crate::SuperIterator;
17use crate::LUA_INTERNAL_CALL;
18use crate::{Buffer, TabPage, Window};
19use crate::{Error, Result};
20
21pub fn chan_send(channel_id: u32, data: &str) -> Result<()> {
27 let mut err = nvim::Error::new();
28 let data = nvim::String::from(data);
29 unsafe { nvim_chan_send(channel_id.into(), data.non_owning(), &mut err) };
30 choose!(err, ())
31}
32
33pub fn create_buf(is_listed: bool, is_scratch: bool) -> Result<Buffer> {
39 let mut err = nvim::Error::new();
40 let handle = unsafe { nvim_create_buf(is_listed, is_scratch, &mut err) };
41 choose!(err, Ok(handle.into()))
42}
43
44pub fn del_current_line() -> Result<()> {
50 let mut err = nvim::Error::new();
51 unsafe {
52 nvim_del_current_line(
53 #[cfg(feature = "neovim-0-10")] types::arena(),
55 &mut err,
56 )
57 };
58 choose!(err, ())
59}
60
61pub fn del_keymap(mode: Mode, lhs: &str) -> Result<()> {
68 let mode = nvim::String::from(mode);
69 let lhs = nvim::String::from(lhs);
70 let mut err = nvim::Error::new();
71 unsafe {
72 nvim_del_keymap(
73 LUA_INTERNAL_CALL,
74 mode.non_owning(),
75 lhs.non_owning(),
76 &mut err,
77 )
78 };
79 choose!(err, ())
80}
81
82pub fn del_mark(name: char) -> Result<()> {
90 let name = nvim::String::from(name);
91 let mut err = nvim::Error::new();
92 let was_deleted = unsafe { nvim_del_mark(name.non_owning(), &mut err) };
93 choose!(
94 err,
95 match was_deleted {
96 true => Ok(()),
97 _ => Err(Error::custom("Couldn't delete mark")),
98 }
99 )
100}
101
102pub fn del_var(name: &str) -> Result<()> {
108 let name = nvim::String::from(name);
109 let mut err = nvim::Error::new();
110 unsafe { nvim_del_var(name.non_owning(), &mut err) };
111 choose!(err, ())
112}
113
114pub fn echo<'hl, Text, Chunks>(
120 chunks: Chunks,
121 history: bool,
122 opts: &EchoOpts,
123) -> Result<()>
124where
125 Chunks: IntoIterator<Item = (Text, Option<&'hl str>)>,
126 Text: Into<nvim::String>,
127{
128 let chunks = chunks
129 .into_iter()
130 .map(|(text, hlgroup)| {
131 Array::from_iter([
132 Object::from(text.into()),
133 Object::from(hlgroup.map(|hl| hl.to_owned())),
134 ])
135 })
136 .collect::<Array>();
137
138 let mut err = nvim::Error::new();
139 unsafe { nvim_echo(chunks.non_owning(), history, opts, &mut err) };
140 choose!(err, ())
141}
142
143pub fn err_write(str: &str) {
151 unsafe { nvim_err_write(nvim::String::from(str).non_owning()) }
152}
153
154pub fn err_writeln(str: &str) {
161 unsafe { nvim_err_writeln(nvim::String::from(str).non_owning()) }
162}
163
164pub fn eval_statusline(
170 str: &str,
171 opts: &EvalStatuslineOpts,
172) -> Result<StatuslineInfos> {
173 let str = nvim::String::from(str);
174 let mut err = nvim::Error::new();
175 let dict = unsafe {
176 nvim_eval_statusline(
177 str.non_owning(),
178 opts,
179 #[cfg(feature = "neovim-0-10")] types::arena(),
181 &mut err,
182 )
183 };
184 choose!(err, Ok(StatuslineInfos::from_object(dict.into())?))
185}
186
187pub fn feedkeys(keys: &str, mode: Mode, escape_ks: bool) {
191 let keys = nvim::String::from(keys);
192 let mode = nvim::String::from(mode);
193 unsafe { nvim_feedkeys(keys.non_owning(), mode.non_owning(), escape_ks) }
194}
195
196pub fn get_chan_info(channel_id: u32) -> Result<ChannelInfos> {
202 let mut err = nvim::Error::new();
203 let infos = unsafe { nvim_get_chan_info(channel_id.into(), &mut err) };
204 choose!(err, Ok(ChannelInfos::from_object(infos.into())?))
205}
206
207pub fn get_color_by_name(name: &str) -> Result<u32> {
214 let name = nvim::String::from(name);
215 let color = unsafe { nvim_get_color_by_name(name.non_owning()) };
216 (color != -1).then(|| color.try_into().unwrap()).ok_or_else(|| {
217 Error::custom(format!("{name:?} is not a valid color name"))
218 })
219}
220
221pub fn get_color_map() -> impl SuperIterator<(String, u32)> {
228 unsafe {
229 nvim_get_color_map(
230 #[cfg(feature = "neovim-0-10")] types::arena(),
232 )
233 }
234 .into_iter()
235 .map(|(k, v)| (k.to_string_lossy().into(), u32::from_object(v).unwrap()))
236}
237
238pub fn get_context(opts: &GetContextOpts) -> Result<EditorContext> {
244 let mut err = nvim::Error::new();
245 let ctx = unsafe {
246 nvim_get_context(
247 opts,
248 #[cfg(feature = "neovim-0-10")] types::arena(),
250 &mut err,
251 )
252 };
253 choose!(err, Ok(EditorContext::from_object(ctx.into())?))
254}
255
256pub fn get_current_buf() -> Buffer {
262 unsafe { nvim_get_current_buf() }.into()
263}
264
265pub fn get_current_line() -> Result<String> {
271 let mut err = nvim::Error::new();
272 let s = unsafe {
273 nvim_get_current_line(
274 #[cfg(feature = "neovim-0-10")] types::arena(),
276 &mut err,
277 )
278 };
279 choose!(err, Ok(s.to_string_lossy().into()))
280}
281
282pub fn get_current_tabpage() -> TabPage {
288 unsafe { nvim_get_current_tabpage() }.into()
289}
290
291pub fn get_current_win() -> Window {
297 unsafe { nvim_get_current_win() }.into()
298}
299
300#[cfg(feature = "neovim-0-10")] #[cfg_attr(
307 docsrs,
308 doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
309)]
310pub fn get_hl(
311 ns_id: u32,
312 opts: &GetHighlightOpts,
313) -> Result<GetHlInfos<impl SuperIterator<(types::String, HighlightInfos)>>> {
314 let mut err = nvim::Error::new();
315 let dict = unsafe {
316 nvim_get_hl(ns_id as Integer, opts, types::arena(), &mut err)
317 };
318 if err.is_err() {
319 return Err(err.into());
320 }
321
322 let is_map = dict
323 .iter()
324 .next()
325 .map(|(_, hl_infos)| {
326 let d = types::serde::Deserializer::new(hl_infos.clone());
327 <HighlightInfos as serde::Deserialize>::deserialize(d).is_ok()
328 })
329 .unwrap_or(false);
330
331 if is_map {
332 let iter = dict.into_iter().map(|(hl_name, hl_infos)| {
333 let infos = HighlightInfos::from_object(hl_infos).unwrap();
334 (hl_name, infos)
335 });
336 Ok(GetHlInfos::Map(iter))
337 } else {
338 HighlightInfos::from_object(dict.into())
339 .map(GetHlInfos::Single)
340 .map_err(Into::into)
341 }
342}
343
344pub fn get_hl_id_by_name(name: &str) -> Result<u32> {
350 let name = nvim::String::from(name);
351 let id = unsafe { nvim_get_hl_id_by_name(name.non_owning()) };
352 id.try_into().map_err(Into::into)
353}
354
355#[cfg(feature = "neovim-0-10")] #[cfg_attr(
362 docsrs,
363 doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
364)]
365pub fn get_hl_ns(opts: &GetNamespaceOpts) -> Result<i64> {
366 let mut err = nvim::Error::new();
367 let res = unsafe { nvim_get_hl_ns(opts, &mut err) };
368 choose!(err, Ok(res))
369}
370
371pub fn get_keymap(mode: Mode) -> impl SuperIterator<KeymapInfos> {
377 let mode = nvim::String::from(mode);
378 let keymaps = unsafe {
379 nvim_get_keymap(
380 mode.non_owning(),
381 #[cfg(feature = "neovim-0-10")] types::arena(),
383 )
384 };
385 keymaps.into_iter().map(|obj| KeymapInfos::from_object(obj).unwrap())
386}
387
388pub fn get_mark(
395 name: char,
396 opts: &GetMarkOpts,
397) -> Result<(usize, usize, Buffer, String)> {
398 let name = nvim::String::from(name);
399 #[cfg(not(feature = "neovim-0-10"))] let opts = Dictionary::from(opts);
401 let mut err = nvim::Error::new();
402 let mark = unsafe {
403 nvim_get_mark(
404 name.non_owning(),
405 #[cfg(not(feature = "neovim-0-10"))] opts.non_owning(),
407 #[cfg(feature = "neovim-0-10")] opts,
409 #[cfg(feature = "neovim-0-10")] types::arena(),
411 &mut err,
412 )
413 };
414 choose!(err, {
415 let mut iter = mark.into_iter();
416 let row = usize::from_object(iter.next().expect("row is present"))?;
417 let col = usize::from_object(iter.next().expect("col is present"))?;
418 let buffer =
419 Buffer::from_object(iter.next().expect("buffer is present"))?;
420 let buffername =
421 String::from_object(iter.next().expect("buffername is present"))?;
422 Ok((row, col, buffer, buffername))
423 })
424}
425
426pub fn get_mode() -> Result<GotMode> {
433 Ok(GotMode::from_object(
434 unsafe {
435 nvim_get_mode(
436 #[cfg(feature = "neovim-0-10")] types::arena(),
438 )
439 }
440 .into(),
441 )?)
442}
443
444pub fn get_proc(pid: u32) -> Result<ProcInfos> {
450 let mut err = nvim::Error::new();
451 let obj = unsafe {
452 nvim_get_proc(
453 pid.into(),
454 #[cfg(feature = "neovim-0-10")] types::arena(),
456 &mut err,
457 )
458 };
459 choose!(err, Ok(ProcInfos::from_object(obj)?))
460}
461
462pub fn get_proc_children(pid: u32) -> Result<impl SuperIterator<u32>> {
468 let mut err = nvim::Error::new();
469 let procs = unsafe {
470 nvim_get_proc_children(
471 pid.into(),
472 #[cfg(feature = "neovim-0-10")] types::arena(),
474 &mut err,
475 )
476 };
477 choose!(
478 err,
479 Ok(procs.into_iter().map(|obj| u32::from_object(obj).unwrap()))
480 )
481}
482
483pub fn get_runtime_file(
489 name: impl AsRef<Path>,
490 get_all: bool,
491) -> Result<impl SuperIterator<PathBuf>> {
492 let name = nvim::String::from(name.as_ref());
493 let mut err = nvim::Error::new();
494 let files = unsafe {
495 nvim_get_runtime_file(
496 name.non_owning(),
497 get_all,
498 #[cfg(feature = "neovim-0-10")] types::arena(),
500 &mut err,
501 )
502 };
503 choose!(
504 err,
505 Ok({
506 files.into_iter().map(|obj| {
507 PathBuf::from(nvim::String::from_object(obj).unwrap())
508 })
509 })
510 )
511}
512
513pub fn get_var<Var>(name: &str) -> Result<Var>
519where
520 Var: FromObject,
521{
522 let mut err = nvim::Error::new();
523 let name = nvim::String::from(name);
524 let obj = unsafe {
525 nvim_get_var(
526 name.non_owning(),
527 #[cfg(feature = "neovim-0-10")] types::arena(),
529 &mut err,
530 )
531 };
532 choose!(err, Ok(Var::from_object(obj)?))
533}
534
535pub fn get_vvar<Var>(name: &str) -> Result<Var>
541where
542 Var: FromObject,
543{
544 let name = nvim::String::from(name);
545 let mut err = nvim::Error::new();
546 let obj = unsafe {
547 nvim_get_vvar(
548 name.non_owning(),
549 #[cfg(feature = "neovim-0-10")] types::arena(),
551 &mut err,
552 )
553 };
554 choose!(err, Ok(Var::from_object(obj)?))
555}
556
557pub fn input<Input>(keys: Input) -> Result<usize>
566where
567 Input: Into<nvim::String>,
568{
569 unsafe { nvim_input(keys.into().non_owning()) }
570 .try_into()
571 .map_err(From::from)
572}
573
574pub fn input_mouse(
580 button: MouseButton,
581 action: MouseAction,
582 modifier: &str,
583 grid: u32,
584 row: usize,
585 col: usize,
586) -> Result<()> {
587 let button = nvim::String::from(button);
588 let action = nvim::String::from(action);
589 let modifier = nvim::String::from(modifier);
590 let mut err = nvim::Error::new();
591 unsafe {
592 nvim_input_mouse(
593 button.non_owning(),
594 action.non_owning(),
595 modifier.non_owning(),
596 grid.into(),
597 row.try_into()?,
598 col.try_into()?,
599 &mut err,
600 )
601 };
602 choose!(err, ())
603}
604
605pub fn list_bufs() -> impl SuperIterator<Buffer> {
615 let bufs = unsafe {
616 nvim_list_bufs(
617 #[cfg(feature = "neovim-0-10")] types::arena(),
619 )
620 };
621 bufs.into_iter().map(|obj| Buffer::from_object(obj).unwrap())
622}
623
624pub fn list_chans() -> impl SuperIterator<ChannelInfos> {
630 unsafe { nvim_list_chans() }
631 .into_iter()
632 .map(|obj| ChannelInfos::from_object(obj).unwrap())
633}
634
635pub fn list_runtime_paths() -> Result<impl SuperIterator<PathBuf>> {
641 let mut err = nvim::Error::new();
642 let paths = unsafe {
643 nvim_list_runtime_paths(
644 #[cfg(feature = "neovim-0-10")] types::arena(),
646 &mut err,
647 )
648 };
649 choose!(
650 err,
651 Ok({
652 paths.into_iter().map(|obj| {
653 PathBuf::from(nvim::String::from_object(obj).unwrap())
654 })
655 })
656 )
657}
658
659pub fn list_tabpages() -> impl SuperIterator<TabPage> {
665 unsafe { nvim_list_tabpages() }
666 .into_iter()
667 .map(|obj| TabPage::from_object(obj).unwrap())
668}
669
670pub fn list_uis() -> impl SuperIterator<UiInfos> {
676 unsafe {
677 nvim_list_uis(
678 #[cfg(feature = "neovim-0-10")] types::arena(),
680 )
681 }
682 .into_iter()
683 .map(|obj| UiInfos::from_object(obj).unwrap())
684}
685
686pub fn list_wins() -> impl SuperIterator<Window> {
692 unsafe {
693 nvim_list_wins(
694 #[cfg(feature = "neovim-0-10")] types::arena(),
696 )
697 }
698 .into_iter()
699 .map(|obj| Window::from_object(obj).unwrap())
700}
701
702pub fn load_context(ctx: EditorContext) {
708 let ctx = Dictionary::from(ctx);
709 let _ = unsafe { nvim_load_context(ctx.non_owning()) };
710}
711
712pub fn notify(
716 msg: &str,
717 log_level: LogLevel,
718 opts: &NotifyOpts,
719) -> Result<()> {
720 let msg = nvim::String::from(msg);
721 let opts = Dictionary::from(opts);
722 let mut err = nvim::Error::new();
723 let _ = unsafe {
724 nvim_notify(
725 msg.non_owning(),
726 log_level as Integer,
727 opts.non_owning(),
728 &mut err,
729 )
730 };
731 choose!(err, ())
732}
733
734pub fn open_term(buffer: &Buffer, opts: &OpenTermOpts) -> Result<u32> {
742 #[cfg(not(feature = "neovim-0-10"))] let opts = Dictionary::from(opts);
744 let mut err = nvim::Error::new();
745 let channel_id = unsafe {
746 nvim_open_term(
747 buffer.0,
748 #[cfg(not(feature = "neovim-0-10"))] opts.non_owning(),
750 #[cfg(feature = "neovim-0-10")] opts,
752 &mut err,
753 )
754 };
755 choose!(
756 err,
757 match channel_id {
758 0 => Err(Error::custom("Couldn't create terminal instance")),
759 other => Ok(other.try_into().expect("always positive")),
760 }
761 )
762}
763
764pub fn out_write<Msg>(str: Msg)
771where
772 Msg: Into<nvim::String>,
773{
774 unsafe { nvim_out_write(str.into().non_owning()) }
775}
776
777pub fn paste<Data>(data: Data, crlf: bool, phase: PastePhase) -> Result<bool>
784where
785 Data: Into<nvim::String>,
786{
787 let mut err = nvim::Error::new();
788 let go_on = unsafe {
789 nvim_paste(
790 data.into().non_owning(),
791 crlf,
792 phase as Integer,
793 #[cfg(feature = "neovim-0-10")] types::arena(),
795 &mut err,
796 )
797 };
798 choose!(err, Ok(go_on))
799}
800
801pub fn put<Line, Lines>(
807 lines: Lines,
808 reg_type: RegisterType,
809 after: bool,
810 follow: bool,
811) -> Result<()>
812where
813 Lines: Iterator<Item = Line>,
814 Line: Into<nvim::String>,
815{
816 let lines = lines.into_iter().map(Into::into).collect::<Array>();
817 let reg_type = nvim::String::from(reg_type);
818 let mut err = nvim::Error::new();
819 unsafe {
820 nvim_put(
821 lines.non_owning(),
822 reg_type.non_owning(),
823 after,
824 follow,
825 &mut err,
826 )
827 };
828 choose!(err, ())
829}
830
831pub fn replace_termcodes<Input>(
838 str: Input,
839 from_part: bool,
840 do_lt: bool,
841 special: bool,
842) -> nvim::String
843where
844 Input: Into<nvim::String>,
845{
846 let str = str.into();
847 unsafe {
848 nvim_replace_termcodes(str.non_owning(), from_part, do_lt, special)
849 }
850}
851
852pub fn select_popupmenu_item(
858 item: usize,
859 insert: bool,
860 finish: bool,
861 opts: &SelectPopupMenuItemOpts,
862) -> Result<()> {
863 #[cfg(not(feature = "neovim-0-10"))] let opts = Dictionary::from(opts);
865 let mut err = nvim::Error::new();
866 unsafe {
867 nvim_select_popupmenu_item(
868 item.try_into()?,
869 insert,
870 finish,
871 #[cfg(not(feature = "neovim-0-10"))] opts.non_owning(),
873 #[cfg(feature = "neovim-0-10")] opts,
875 &mut err,
876 )
877 };
878 choose!(err, ())
879}
880
881pub fn set_current_buf(buf: &Buffer) -> Result<()> {
887 let mut err = nvim::Error::new();
888 unsafe { nvim_set_current_buf(buf.0, &mut err) };
889 choose!(err, ())
890}
891
892pub fn set_current_dir<Dir>(dir: Dir) -> Result<()>
898where
899 Dir: AsRef<Path>,
900{
901 let dir = nvim::String::from(dir.as_ref());
902 let mut err = nvim::Error::new();
903 unsafe { nvim_set_current_dir(dir.non_owning(), &mut err) };
904 choose!(err, ())
905}
906
907pub fn set_current_line<Line>(line: Line) -> Result<()>
913where
914 Line: Into<nvim::String>,
915{
916 let mut err = nvim::Error::new();
917 unsafe {
918 nvim_set_current_line(
919 line.into().non_owning(),
920 #[cfg(feature = "neovim-0-10")] types::arena(),
922 &mut err,
923 )
924 };
925 choose!(err, ())
926}
927
928pub fn set_current_tabpage(tabpage: &TabPage) -> Result<()> {
934 let mut err = nvim::Error::new();
935 unsafe { nvim_set_current_tabpage(tabpage.0, &mut err) };
936 choose!(err, ())
937}
938
939pub fn set_current_win(win: &Window) -> Result<()> {
945 let mut err = nvim::Error::new();
946 unsafe { nvim_set_current_win(win.0, &mut err) };
947 choose!(err, ())
948}
949
950pub fn set_hl(ns_id: u32, name: &str, opts: &SetHighlightOpts) -> Result<()> {
956 let name = nvim::String::from(name);
957 let mut err = nvim::Error::new();
958 unsafe {
959 nvim_set_hl(
960 #[cfg(feature = "neovim-0-10")] LUA_INTERNAL_CALL,
962 ns_id as Integer,
963 name.non_owning(),
964 opts,
965 &mut err,
966 )
967 };
968 choose!(err, ())
969}
970
971#[cfg(feature = "neovim-0-10")] #[cfg_attr(
979 docsrs,
980 doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
981)]
982pub fn set_hl_ns(ns_id: u32) -> Result<()> {
983 let mut err = nvim::Error::new();
984 unsafe { nvim_set_hl_ns(ns_id as Integer, &mut err) };
985 choose!(err, ())
986}
987
988#[cfg(feature = "neovim-0-10")] #[cfg_attr(
1001 docsrs,
1002 doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
1003)]
1004pub fn set_hl_ns_fast(ns_id: u32) -> Result<()> {
1005 let mut err = nvim::Error::new();
1006 unsafe { nvim_set_hl_ns_fast(ns_id as Integer, &mut err) };
1007 choose!(err, ())
1008}
1009
1010pub fn set_keymap(
1017 mode: Mode,
1018 lhs: &str,
1019 rhs: &str,
1020 opts: &SetKeymapOpts,
1021) -> Result<()> {
1022 let mode = nvim::String::from(mode);
1023 let lhs = nvim::String::from(lhs);
1024 let rhs = nvim::String::from(rhs);
1025 let mut err = nvim::Error::new();
1026 unsafe {
1027 nvim_set_keymap(
1028 LUA_INTERNAL_CALL,
1029 mode.non_owning(),
1030 lhs.non_owning(),
1031 rhs.non_owning(),
1032 opts,
1033 &mut err,
1034 )
1035 };
1036 choose!(err, ())
1037}
1038
1039pub fn set_var<Var>(name: &str, value: Var) -> Result<()>
1045where
1046 Var: ToObject,
1047{
1048 let name = nvim::String::from(name);
1049 let value = value.to_object()?;
1050 let mut err = nvim::Error::new();
1051 unsafe { nvim_set_var(name.non_owning(), value.non_owning(), &mut err) };
1052 choose!(err, ())
1053}
1054
1055pub fn set_vvar<Var>(name: &str, value: Var) -> Result<()>
1061where
1062 Var: ToObject,
1063{
1064 let name = nvim::String::from(name);
1065 let value = value.to_object()?;
1066 let mut err = nvim::Error::new();
1067 unsafe { nvim_set_vvar(name.non_owning(), value.non_owning(), &mut err) };
1068 choose!(err, ())
1069}
1070
1071pub fn strwidth(text: &str) -> Result<usize> {
1078 let text = nvim::String::from(text);
1079 let mut err = nvim::Error::new();
1080 let width = unsafe { nvim_strwidth(text.non_owning(), &mut err) };
1081 choose!(err, Ok(width.try_into().expect("always positive")))
1082}