Skip to main content

nvrim/plugins/
opener.rs

1use nvim_oxi::Dictionary;
2use ytil_zellij::Direction;
3
4use crate::buffer::token_under_cursor;
5use crate::buffer::token_under_cursor::TokenUnderCursor;
6
7pub fn dict() -> Dictionary {
8    dict! {
9        "open_token_under_cursor": fn_from!(open_token_under_cursor),
10        "copy_enclosing_function": fn_from!(copy_enclosing_function),
11        "reveal_in_finder": fn_from!(reveal_in_finder),
12    }
13}
14
15fn copy_enclosing_function(_: ()) -> Option<()> {
16    let file_path = ytil_noxi::buffer::get_absolute_path(Some(&nvim_oxi::api::get_current_buf()))?;
17    let enclosing_fn = ytil_noxi::tree_sitter::get_enclosing_fn_name_of_position(&file_path)?;
18    ytil_sys::file::cp_to_system_clipboard(&mut enclosing_fn.as_bytes())
19        .inspect_err(|err| {
20            ytil_noxi::notify::error(format!(
21                "error copying content to system clipboard | content={enclosing_fn:?} error={err:#?}"
22            ));
23        })
24        .ok()?;
25    nvim_oxi::print!("Enclosing fn name copied to clipboard: {enclosing_fn}");
26    Some(())
27}
28
29fn open_token_under_cursor(_: ()) -> Option<()> {
30    let token_under_cursor = token_under_cursor::get(())?;
31
32    match token_under_cursor {
33        TokenUnderCursor::BinaryFile(_) | TokenUnderCursor::MaybeTextFile { .. } => None,
34        TokenUnderCursor::TextFile { path, lnum, col } => {
35            let open = if ytil_zellij::is_active() {
36                open_in_zellij_pane
37            } else {
38                open_in_nvim_split
39            };
40            open(&path, lnum, col)
41        }
42        TokenUnderCursor::Url(arg) | TokenUnderCursor::Directory(arg) => ytil_sys::open(&arg)
43            .inspect_err(|err| {
44                ytil_noxi::notify::error(format!("{err:?}"));
45            })
46            .ok(),
47    }
48}
49
50fn open_in_zellij_pane(path: &str, lnum: Option<i64>, col: Option<i64>) -> Option<()> {
51    let cursor_cmd = format!("call cursor({}, {})", lnum.unwrap_or_default(), col.unwrap_or_default());
52
53    let result = ytil_zellij::pane_count().and_then(|pane_count| {
54        if pane_count > 1 {
55            ytil_zellij::move_focus(Direction::Right)?;
56            let is_nvim =
57                ytil_zellij::focused_pane_command()?.is_some_and(|cmd| cmd.contains("nvim") || cmd.contains("vim"));
58            if is_nvim {
59                ytil_zellij::write_byte(0x1b)?;
60                ytil_zellij::write_chars(&format!(":edit {path} | {cursor_cmd}\r"))?;
61            } else {
62                let cursor_arg = format!("+'{cursor_cmd}'");
63                ytil_zellij::write_chars(&format!("nvim {cursor_arg} {path}\r"))?;
64            }
65            return Ok(());
66        }
67        let cursor_arg = format!("+'{cursor_cmd}'");
68        ytil_zellij::new_pane(Direction::Right, &["nvim", &cursor_arg, path])?;
69        ytil_zellij::resize_increase(Direction::Left, 3)?;
70        Ok(())
71    });
72
73    result
74        .inspect_err(|err| ytil_noxi::notify::error(format!("{err:#?}")))
75        .ok()
76}
77
78fn open_in_nvim_split(path: &str, lnum: Option<i64>, col: Option<i64>) -> Option<()> {
79    let open_path_cmd = format!(
80        "edit {path} | call cursor({}, {})",
81        lnum.unwrap_or_default(),
82        col.unwrap_or_default()
83    );
84
85    let vim_script = if let Some(win_num) =
86        ytil_noxi::window::find_with_buffer("").and_then(|(win, _)| ytil_noxi::window::get_number(&win))
87    {
88        format!("{win_num} wincmd w | {open_path_cmd}")
89    } else {
90        let width = crate::layout::compute_width(70)?;
91        format!("vsplit | vertical resize {width} | {open_path_cmd}")
92    };
93
94    ytil_noxi::common::exec_vim_script(&vim_script, None);
95    Some(())
96}
97
98fn reveal_in_finder(_: ()) -> Option<()> {
99    let file_path = ytil_noxi::buffer::get_absolute_path(Some(&nvim_oxi::api::get_current_buf()))?;
100    let Some(parent) = file_path.parent() else {
101        ytil_noxi::notify::error(format!(
102            "error no parent for current buffer file path | file_path={}",
103            file_path.display()
104        ));
105        return None;
106    };
107    let Some(parent_str) = parent.to_str() else {
108        ytil_noxi::notify::error(format!(
109            "error parent path is not valid UTF-8 | path={}",
110            parent.display()
111        ));
112        return None;
113    };
114    ytil_sys::open(parent_str)
115        .inspect_err(|err| {
116            ytil_noxi::notify::error(format!("error opening path | path={} error={err:#?}", parent.display()));
117        })
118        .ok()?;
119    Some(())
120}