@@ -11,6 +11,7 @@ use which::which;
1111use crate :: {
1212 neovide,
1313 plugin_config:: { LauncherType , PluginConfig , SocketType } ,
14+ terminals:: { RunArg , Terminal } ,
1415 utils:: { self , is_port_in_use} ,
1516} ;
1617
@@ -21,6 +22,7 @@ const VAR_CLASSNAME: &str = "{CLASSNAME}";
2122const VAR_ADDRESS : & str = "{ADDR}" ;
2223const VAR_LINE : & str = "{LINE}" ;
2324const VAR_FILE : & str = "{FILE}" ;
25+ const VAR_NVIM : & str = "{NVIM}" ;
2426
2527#[ derive( Debug ) ]
2628struct Launcher ( PathBuf , Vec < String > ) ;
@@ -32,10 +34,21 @@ impl Launcher {
3234 let exe = self . 0 ;
3335 let args = self . 1 ;
3436
35- let out = Command :: new ( exe) . args ( args) . output ( ) ?;
37+ let mut cmd = Command :: new ( exe) ;
38+ cmd. args ( args) ;
39+
40+ tracing:: debug!( "Command Run: {cmd:?}" ) ;
41+
42+ let out = cmd. output ( ) ?;
43+
44+ if !out. stdout . is_empty ( ) {
45+ tracing:: debug!( "Command Out: {}" , String :: from_utf8( out. stdout) ?) ;
46+ }
3647
3748 if !out. stderr . is_empty ( ) {
38- bail ! ( String :: from_utf8( out. stderr) ?) ;
49+ let res = String :: from_utf8 ( out. stderr ) ?;
50+ tracing:: error!( "Command Err: {res}" ) ;
51+ bail ! ( res) ;
3952 }
4053
4154 Ok ( ( ) )
@@ -59,14 +72,6 @@ impl Launcher {
5972 }
6073}
6174
62- const DEFAULT_TERMINALS : [ ( & str , & str , & str ) ; 5 ] = [
63- ( "alacritty" , "--class=" , "-e" ) ,
64- ( "foot" , "--app-id=" , "-e" ) ,
65- ( "ghostty" , "--class=" , "-e" ) ,
66- ( "kitty" , "--class=" , "-e" ) ,
67- ( "st" , "-c=" , "-e" ) ,
68- ] ;
69-
7075fn create_launcher ( cfg : & PluginConfig , nvim : & String ) -> Result < Launcher > {
7176 match cfg. launcher_type {
7277 Some ( LauncherType :: Neovide ) => {
@@ -90,9 +95,9 @@ fn create_launcher(cfg: &PluginConfig, nvim: &String) -> Result<Launcher> {
9095
9196 let mut args = Vec :: new ( ) ;
9297
93- if let Some ( extra_args ) = & cfg. extra_arguments {
94- for extra_arg in extra_args {
95- args. push ( extra_arg . clone ( ) ) ;
98+ if let Some ( exe_args ) = & cfg. arguments {
99+ for exe_arg in exe_args {
100+ args. push ( exe_arg . clone ( ) ) ;
96101 }
97102 }
98103
@@ -120,131 +125,52 @@ fn create_launcher(cfg: &PluginConfig, nvim: &String) -> Result<Launcher> {
120125 Ok ( Launcher ( executable. clone ( ) , args) )
121126 }
122127 Some ( LauncherType :: Terminal ) => {
123- let executable: Option < PathBuf > = cfg. executable . clone ( ) . map ( Into :: into) ;
124-
125- let executable = if let Some ( exe) = executable
126- && exe. exists ( )
127- {
128- let class_arg = & cfg. terminal_class_argument ;
129- let run_arg = & cfg. terminal_run_argument ;
130- let mut args = Vec :: new ( ) ;
131-
132- if let Some ( extra_args) = & cfg. extra_arguments {
133- for extra_arg in extra_args {
134- args. push ( extra_arg. clone ( ) ) ;
135- }
136- }
137-
138- // only add class on linux
139- if cfg ! ( target_os = "linux" )
140- && let Some ( class_arg) = class_arg
141- {
142- if class_arg. ends_with ( '=' ) {
143- args. push ( class_arg. clone ( ) + VAR_CLASSNAME ) ;
144- } else {
145- args. push ( class_arg. clone ( ) ) ;
146- args. push ( VAR_CLASSNAME . to_string ( ) ) ;
147- }
148- }
128+ let mut args = Vec :: new ( ) ;
149129
150- if let Some ( run_arg) = run_arg {
151- if run_arg. ends_with ( '=' ) {
152- args. push ( run_arg. clone ( ) + nvim) ;
153- } else {
154- args. push ( run_arg. clone ( ) ) ;
155- args. push ( nvim. clone ( ) ) ;
156- }
130+ if let Some ( exe_args) = & cfg. arguments {
131+ for exe_arg in exe_args {
132+ args. push ( exe_arg. clone ( ) ) ;
157133 }
158-
159- args. push ( "--listen" . to_string ( ) ) ;
160- args. push ( VAR_ADDRESS . to_string ( ) ) ;
161-
162- args. push ( "--remote" . to_string ( ) ) ;
163- args. push ( VAR_LINE . to_string ( ) ) ;
164- args. push ( VAR_FILE . to_string ( ) ) ;
165-
166- Some ( Launcher ( exe, args) )
167- } else {
168- None
169134 }
170- . or_else ( || {
171- let mut args = Vec :: new ( ) ;
172135
173- if let Some ( extra_args) = & cfg. extra_arguments {
174- for extra_arg in extra_args {
175- args. push ( extra_arg. clone ( ) ) ;
176- }
177- }
178-
179- // executable specifies only the name of which terminal we want to use
180- if let Some ( exe_name) = & cfg. executable
181- && let Some ( ( name, class_arg, run_arg) ) = DEFAULT_TERMINALS
182- . iter ( )
183- . find ( |( name, _, _) | * name == exe_name)
184- && let Ok ( path) = which ( name)
185- {
186- // only add class on linux
187- if cfg ! ( target_os = "linux" ) {
188- if class_arg. ends_with ( '=' ) {
189- args. push ( ( * class_arg) . to_string ( ) + VAR_CLASSNAME ) ;
190- } else {
191- args. push ( ( * class_arg) . to_string ( ) ) ;
192- args. push ( VAR_CLASSNAME . to_string ( ) ) ;
193- }
194- }
195-
196- if run_arg. ends_with ( '=' ) {
197- args. push ( ( * run_arg) . to_string ( ) + nvim) ;
198- } else {
199- args. push ( ( * run_arg) . to_string ( ) ) ;
200- args. push ( ( * nvim) . clone ( ) ) ;
201- }
136+ if let Some ( executable) = & cfg. executable . clone ( ) . map ( PathBuf :: from)
137+ && executable. is_absolute ( )
138+ && executable. exists ( )
139+ {
140+ let term = Terminal {
141+ executable : cfg. executable . clone ( ) . unwrap ( ) ,
142+ arguments : Vec :: new ( ) ,
143+ run_arg : None ,
144+ class_arg : None ,
145+ } ;
146+
147+ tracing:: debug!( "Terminal specified by absolute path {term:?}" ) ;
148+
149+ return make_launcher_from_terminal ( & term, args, nvim)
150+ . context ( ERR_TERMINAL_NOT_FOUND ) ;
151+ } else if let Some ( exe_name) = & cfg. executable
152+ && let Some ( term) = Terminal :: find_by_name ( exe_name)
153+ && term. find_executable ( ) . is_some ( )
154+ {
155+ tracing:: debug!( "Looking for terminal by name {exe_name} found {term:?}" ) ;
202156
203- args. push ( "--listen" . to_string ( ) ) ;
204- args. push ( VAR_ADDRESS . to_string ( ) ) ;
157+ // executable specifies only the name o f which terminal we want to use
158+ return make_launcher_from_terminal ( & term, args, nvim)
159+ . context ( ERR_TERMINAL_NOT_FOUND ) ;
160+ }
205161
206- args . push ( "--remote" . to_string ( ) ) ;
207- args . push ( VAR_LINE . to_string ( ) ) ;
208- args . push ( VAR_FILE . to_string ( ) ) ;
162+ tracing :: debug! (
163+ "No terminal specific terminal specified or not found, looking for available one..."
164+ ) ;
209165
210- return Some ( Launcher ( path , args ) ) ;
211- }
166+ if let Some ( term ) = Terminal :: find_available ( ) {
167+ tracing :: debug! ( "Found {term:?}" ) ;
212168
213- // try finding one of our supported default terminals
214- for ( name, class_arg, run_arg) in & DEFAULT_TERMINALS {
215- if let Ok ( path) = which ( name) {
216- // only add class on linux
217- if cfg ! ( target_os = "linux" ) {
218- if class_arg. ends_with ( '=' ) {
219- args. push ( ( * class_arg) . to_string ( ) + VAR_CLASSNAME ) ;
220- } else {
221- args. push ( ( * class_arg) . to_string ( ) ) ;
222- args. push ( VAR_CLASSNAME . to_string ( ) ) ;
223- }
224- }
225-
226- if run_arg. ends_with ( '=' ) {
227- args. push ( ( * run_arg) . to_string ( ) + nvim) ;
228- } else {
229- args. push ( ( * run_arg) . to_string ( ) ) ;
230- args. push ( ( * nvim) . clone ( ) ) ;
231- }
232-
233- args. push ( "--listen" . to_string ( ) ) ;
234- args. push ( VAR_ADDRESS . to_string ( ) ) ;
235-
236- args. push ( "--remote" . to_string ( ) ) ;
237- args. push ( VAR_LINE . to_string ( ) ) ;
238- args. push ( VAR_FILE . to_string ( ) ) ;
239-
240- return Some ( Launcher ( path, args) ) ;
241- }
242- }
243- None
244- } )
245- . context ( ERR_TERMINAL_NOT_FOUND ) ?;
169+ return make_launcher_from_terminal ( & term, args, nvim)
170+ . context ( ERR_TERMINAL_NOT_FOUND ) ;
171+ }
246172
247- Ok ( executable )
173+ bail ! ( ERR_TERMINAL_NOT_FOUND ) ;
248174 }
249175 None => {
250176 if let Ok ( launcher) = create_launcher (
@@ -272,6 +198,57 @@ fn create_launcher(cfg: &PluginConfig, nvim: &String) -> Result<Launcher> {
272198 }
273199}
274200
201+ fn make_launcher_from_terminal (
202+ term : & Terminal ,
203+ mut args : Vec < String > ,
204+ nvim : & String ,
205+ ) -> Option < Launcher > {
206+ let exe_path = term. find_executable ( ) ?;
207+
208+ // prepend our arguments
209+ for arg in term. arguments . iter ( ) . rev ( ) {
210+ args. insert ( 0 , arg. clone ( ) ) ;
211+ }
212+
213+ // only add class on linux
214+ if cfg ! ( target_os = "linux" )
215+ && let Some ( class_arg) = & term. class_arg
216+ {
217+ if class_arg. ends_with ( '=' ) {
218+ args. push ( ( * class_arg) . clone ( ) + VAR_CLASSNAME ) ;
219+ } else {
220+ args. push ( ( * class_arg) . clone ( ) ) ;
221+ args. push ( VAR_CLASSNAME . to_string ( ) ) ;
222+ }
223+ }
224+
225+ if let Some ( run_arg) = & term. run_arg {
226+ match run_arg {
227+ RunArg :: Arg ( run_arg) => {
228+ if run_arg. ends_with ( '=' ) {
229+ args. push ( ( * run_arg) . clone ( ) + nvim) ;
230+ } else {
231+ args. push ( ( * run_arg) . clone ( ) ) ;
232+ args. push ( ( * nvim) . clone ( ) ) ;
233+ }
234+ }
235+ RunArg :: End => {
236+ args. push ( "--" . to_string ( ) ) ;
237+ args. push ( nvim. clone ( ) ) ;
238+ }
239+ }
240+ }
241+
242+ args. push ( "--listen" . to_string ( ) ) ;
243+ args. push ( VAR_ADDRESS . to_string ( ) ) ;
244+
245+ args. push ( "--remote" . to_string ( ) ) ;
246+ args. push ( VAR_LINE . to_string ( ) ) ;
247+ args. push ( VAR_FILE . to_string ( ) ) ;
248+
249+ Some ( Launcher ( exe_path, args) )
250+ }
251+
275252fn nvim_open_file_remote ( nvim : & str , server : & str , file : & str , line : Option < usize > ) -> Result < ( ) > {
276253 let remote_cmd = if let Some ( line) = line {
277254 format ! ( "+{line} {file}" )
@@ -421,7 +398,9 @@ pub fn run(
421398 launcher. filter_params ( |s| s != VAR_LINE )
422399 } ;
423400
424- let launcher = launcher. apply_var ( VAR_FILE , file_str) ;
401+ let launcher = launcher
402+ . apply_var ( VAR_FILE , file_str)
403+ . apply_var ( VAR_NVIM , & nvim) ;
425404
426405 match plugin_config. socket_type {
427406 Some ( SocketType :: Fsock ) => run_fsock ( launcher, & nvim, & root_dir, file_str, line) ?,
0 commit comments