1use crate::cli::Shell;
2use crate::config::{get_base_config_dir, get_config_dir};
3use anyhow::Result;
4use std::fs;
5use std::io::Write;
6use std::path::PathBuf;
7
8const FISH_PICKER_FUNCTION: &str = r#"function try-rs-picker
9 set -l picker_args --inline-picker
10
11 if set -q TRY_RS_PICKER_HEIGHT
12 if string match -qr '^[0-9]+$' -- "$TRY_RS_PICKER_HEIGHT"
13 set picker_args $picker_args --inline-height $TRY_RS_PICKER_HEIGHT
14 end
15 end
16
17 if status --is-interactive
18 printf "\n"
19 end
20
21 set command (command try-rs $picker_args | string collect)
22 set command_status $status
23
24 if test $command_status -eq 0; and test -n "$command"
25 eval $command
26 end
27
28 if status --is-interactive
29 printf "\033[A"
30 commandline -f repaint
31 end
32end
33"#;
34
35pub fn get_shell_content(shell: &Shell) -> String {
38 let completions = get_completions_script(shell);
39 match shell {
40 Shell::Fish => {
41 format!(
42 r#"function try-rs
43 # Pass flags/options directly to stdout without capturing
44 for arg in $argv
45 if string match -q -- '-*' $arg
46 command try-rs $argv
47 return
48 end
49 end
50
51 # Captures the output of the binary (stdout) which is the "cd" command
52 # The TUI is rendered on stderr, so it doesn't interfere.
53 set command (command try-rs $argv | string collect)
54 set command_status $status
55
56 if test $command_status -eq 0; and test -n "$command"
57 eval $command
58 end
59end
60
61{picker_function}
62
63{completions}"#,
64 picker_function = FISH_PICKER_FUNCTION,
65 )
66 }
67 Shell::Zsh => {
68 format!(
69 r#"try-rs() {{
70 # Pass flags/options directly to stdout without capturing
71 for arg in "$@"; do
72 case "$arg" in
73 -*) command try-rs "$@"; return ;;
74 esac
75 done
76
77 # Captures the output of the binary (stdout) which is the "cd" command
78 # The TUI is rendered on stderr, so it doesn't interfere.
79 local output
80 output=$(command try-rs "$@")
81
82 if [ -n "$output" ]; then
83 eval "$output"
84 fi
85}}
86
87{completions}"#
88 )
89 }
90 Shell::Bash => {
91 format!(
92 r#"try-rs() {{
93 # Pass flags/options directly to stdout without capturing
94 for arg in "$@"; do
95 case "$arg" in
96 -*) command try-rs "$@"; return ;;
97 esac
98 done
99
100 # Captures the output of the binary (stdout) which is the "cd" command
101 # The TUI is rendered on stderr, so it doesn't interfere.
102 local output
103 output=$(command try-rs "$@")
104
105 if [ -n "$output" ]; then
106 eval "$output"
107 fi
108}}
109
110{completions}"#
111 )
112 }
113 Shell::PowerShell => {
114 format!(
115 r#"# try-rs integration for PowerShell
116function try-rs {{
117 # Pass flags/options directly to stdout without capturing
118 foreach ($a in $args) {{
119 if ($a -like '-*') {{
120 & try-rs.exe @args
121 return
122 }}
123 }}
124
125 # Captures the output of the binary (stdout) which is the "cd" or editor command
126 # The TUI is rendered on stderr, so it doesn't interfere.
127 $command = (try-rs.exe @args)
128
129 if ($command) {{
130 Invoke-Expression $command
131 }}
132}}
133
134{completions}"#
135 )
136 }
137 Shell::NuShell => {
138 format!(
139 r#"def --env --wrapped try-rs [
140 name_or_url?: string@__try_rs_complete
141 ...args
142] {{
143 let all_args = (if $name_or_url == null {{ [] }} else {{ [$name_or_url] }} | append $args)
144
145 # Pass flags/options directly to stdout without capturing
146 if ($all_args | any {{ |arg| $arg | str starts-with '-' }}) {{
147 ^try-rs ...$all_args
148 return
149 }}
150
151 # Capture output. Stderr (TUI) goes directly to terminal.
152 let output = (^try-rs ...$all_args | str trim)
153
154 if ($output | is-not-empty) {{
155 if ($output | str starts-with "cd ") {{
156 # Grabs the path out of stdout returned by the binary and removes the single quotes
157 let path = ($output | str replace --regex '^cd ' '' | str replace --all "'" "" | str replace --all '"' "")
158 if ($path | path exists) {{
159 cd $path
160 }}
161 }} else {{
162 # If it's not a cd command, it's likely an editor command
163 nu -c $output
164 }}
165 }}
166}}
167
168{completions}"#,
169 completions = get_completions_script(shell),
170 )
171 }
172 }
173}
174
175pub fn get_completions_script(shell: &Shell) -> String {
178 match shell {
179 Shell::Fish => {
180 r#"# try-rs tab completion for directory names
181function __try_rs_get_tries_path
182 # Check TRY_PATH environment variable first
183 if set -q TRY_PATH
184 echo $TRY_PATH
185 return
186 end
187
188 # Try to read from config file
189 set -l config_paths "$HOME/.config/try-rs/config.toml" "$HOME/.try-rs/config.toml"
190 for config_path in $config_paths
191 if test -f $config_path
192 set -l tries_path (command grep -E '^\s*tries_path\s*=' $config_path 2>/dev/null | command sed 's/.*=\s*"\?\([^"]*\)"\?.*/\1/' | command sed "s|~|$HOME|" | string trim)
193 if test -n "$tries_path"
194 echo $tries_path
195 return
196 end
197 end
198 end
199
200 # Default path
201 echo "$HOME/work/tries"
202end
203
204function __try_rs_complete_directories
205 set -l tries_path (__try_rs_get_tries_path)
206
207 if test -d $tries_path
208 # List directories in tries_path, filtering by current token
209 command ls -1 $tries_path 2>/dev/null | while read -l dir
210 if test -d "$tries_path/$dir"
211 echo $dir
212 end
213 end
214 end
215end
216
217complete -f -c try-rs -n '__fish_use_subcommand' -a '(__try_rs_complete_directories)' -d 'Try directory'
218"#.to_string()
219 }
220 Shell::Zsh => {
221 r#"# try-rs tab completion for directory names
222_try_rs_get_tries_path() {
223 # Check TRY_PATH environment variable first
224 if [[ -n "${TRY_PATH}" ]]; then
225 echo "${TRY_PATH}"
226 return
227 fi
228
229 # Try to read from config file
230 local config_paths=("$HOME/.config/try-rs/config.toml" "$HOME/.try-rs/config.toml")
231 for config_path in "${config_paths[@]}"; do
232 if [[ -f "$config_path" ]]; then
233 local tries_path=$(grep -E '^\s*tries_path\s*=' "$config_path" 2>/dev/null | sed 's/.*=\s*"\?\([^"]*\)"\?.*/\1/' | sed "s|~|$HOME|" | tr -d '[:space:]')
234 if [[ -n "$tries_path" ]]; then
235 echo "$tries_path"
236 return
237 fi
238 fi
239 done
240
241 # Default path
242 echo "$HOME/work/tries"
243}
244
245_try_rs_complete() {
246 local cur="${COMP_WORDS[COMP_CWORD]}"
247 local tries_path=$(_try_rs_get_tries_path)
248 local -a dirs=()
249
250 if [[ -d "$tries_path" ]]; then
251 # Get list of directories
252 while IFS= read -r dir; do
253 dirs+=("$dir")
254 done < <(ls -1 "$tries_path" 2>/dev/null | while read -r dir; do
255 if [[ -d "$tries_path/$dir" ]]; then
256 echo "$dir"
257 fi
258 done)
259 fi
260
261 COMPREPLY=($(compgen -W "${dirs[*]}" -- "$cur"))
262}
263
264complete -o default -F _try_rs_complete try-rs
265"#.to_string()
266 }
267 Shell::Bash => {
268 r#"# try-rs tab completion for directory names
269_try_rs_get_tries_path() {
270 # Check TRY_PATH environment variable first
271 if [[ -n "${TRY_PATH}" ]]; then
272 echo "${TRY_PATH}"
273 return
274 fi
275
276 # Try to read from config file
277 local config_paths=("$HOME/.config/try-rs/config.toml" "$HOME/.try-rs/config.toml")
278 for config_path in "${config_paths[@]}"; do
279 if [[ -f "$config_path" ]]; then
280 local tries_path=$(grep -E '^[[:space:]]*tries_path[[:space:]]*=' "$config_path" 2>/dev/null | sed 's/.*=[[:space:]]*"\?\([^"]*\)"\?.*/\1/' | sed "s|~|$HOME|" | tr -d '[:space:]')
281 if [[ -n "$tries_path" ]]; then
282 echo "$tries_path"
283 return
284 fi
285 fi
286 done
287
288 # Default path
289 echo "$HOME/work/tries"
290}
291
292_try_rs_complete() {
293 local cur="${COMP_WORDS[COMP_CWORD]}"
294 local tries_path=$(_try_rs_get_tries_path)
295 local dirs=""
296
297 if [[ -d "$tries_path" ]]; then
298 # Get list of directories
299 while IFS= read -r dir; do
300 if [[ -d "$tries_path/$dir" ]]; then
301 dirs="$dirs $dir"
302 fi
303 done < <(ls -1 "$tries_path" 2>/dev/null)
304 fi
305
306 COMPREPLY=($(compgen -W "$dirs" -- "$cur"))
307}
308
309complete -o default -F _try_rs_complete try-rs
310"#.to_string()
311 }
312 Shell::PowerShell => {
313 r#"# try-rs tab completion for directory names
314Register-ArgumentCompleter -CommandName try-rs -ScriptBlock {
315 param($wordToComplete, $commandAst, $cursorPosition)
316
317 # Get tries path from environment variable or default
318 $triesPath = $env:TRY_PATH
319 if (-not $triesPath) {
320 # Try to read from config file
321 $configPaths = @(
322 "$env:USERPROFILE/.config/try-rs/config.toml",
323 "$env:USERPROFILE/.try-rs/config.toml"
324 )
325 foreach ($configPath in $configPaths) {
326 if (Test-Path $configPath) {
327 $content = Get-Content $configPath -Raw
328 if ($content -match 'tries_path\s*=\s*["'']?([^"'']+)["'']?') {
329 $triesPath = $matches[1].Replace('~', $env:USERPROFILE).Trim()
330 break
331 }
332 }
333 }
334 }
335
336 # Default path
337 if (-not $triesPath) {
338 $triesPath = "$env:USERPROFILE/work/tries"
339 }
340
341 # Get directories
342 if (Test-Path $triesPath) {
343 Get-ChildItem -Path $triesPath -Directory |
344 Where-Object { $_.Name -like "$wordToComplete*" } |
345 ForEach-Object {
346 [System.Management.Automation.CompletionResult]::new(
347 $_.Name,
348 $_.Name,
349 'ParameterValue',
350 $_.Name
351 )
352 }
353 }
354}
355"#.to_string()
356 }
357 Shell::NuShell => {
358 r#"# try-rs tab completion for directory names
359# Add this to your Nushell config or env file
360
361export def __try_rs_get_tries_path [] {
362 # Check TRY_PATH environment variable first
363 if ($env.TRY_PATH? | is-not-empty) {
364 return $env.TRY_PATH
365 }
366
367 # Try to read from config file
368 let config_paths = [
369 ($env.HOME | path join ".config" "try-rs" "config.toml"),
370 ($env.HOME | path join ".try-rs" "config.toml")
371 ]
372
373 for config_path in $config_paths {
374 if ($config_path | path exists) {
375 let content = (open $config_path | str trim)
376 if ($content =~ 'tries_path\\s*=\\s*"?([^"]+)"?') {
377 let path = ($content | parse -r 'tries_path\\s*=\\s*"?([^"]+)"?' | get capture0.0? | default "")
378 if ($path | is-not-empty) {
379 return ($path | str replace "~" $env.HOME)
380 }
381 }
382 }
383 }
384
385 # Default path
386 ($env.HOME | path join "work" "tries")
387}
388
389export def __try_rs_complete [context: string] {
390 let tries_path = (__try_rs_get_tries_path)
391
392 if ($tries_path | path exists) {
393 ls $tries_path | where type == "dir" | get name | path basename
394 } else {
395 []
396 }
397}
398"#.to_string()
399 }
400 }
401}
402
403pub fn get_completion_script_only(shell: &Shell) -> String {
405 let completions = get_completions_script(shell);
406 match shell {
407 Shell::NuShell => {
408 r#"# try-rs tab completion for directory names
410# Add this to your Nushell config
411
412def __try_rs_get_tries_path [] {
413 if ($env.TRY_PATH? | is-not-empty) {
414 return $env.TRY_PATH
415 }
416
417 let config_paths = [
418 ($env.HOME | path join ".config" "try-rs" "config.toml"),
419 ($env.HOME | path join ".try-rs" "config.toml")
420 ]
421
422 for config_path in $config_paths {
423 if ($config_path | path exists) {
424 let content = (open $config_path | str trim)
425 if ($content =~ 'tries_path\\s*=\\s*"?([^"]+)"?') {
426 let path = ($content | parse -r 'tries_path\\s*=\\s*"?([^"]+)"?' | get capture0.0? | default "")
427 if ($path | is-not-empty) {
428 return ($path | str replace "~" $env.HOME)
429 }
430 }
431 }
432 }
433
434 ($env.HOME | path join "work" "tries")
435}
436
437def __try_rs_complete [context: string] {
438 let tries_path = (__try_rs_get_tries_path)
439
440 if ($tries_path | path exists) {
441 ls $tries_path | where type == "dir" | get name | path basename
442 } else {
443 []
444 }
445}
446
447# Register completion
448export extern try-rs [
449 name_or_url?: string@__try_rs_complete
450 destination?: string
451 --setup: string
452 --setup-stdout: string
453 --completions: string
454 --shallow-clone(-s)
455 --worktree(-w): string
456]
457"#.to_string()
458 }
459 _ => completions,
460 }
461}
462
463pub fn get_shell_integration_path(shell: &Shell) -> PathBuf {
464 let config_dir = match shell {
465 Shell::Fish => get_base_config_dir(),
466 _ => get_config_dir(),
467 };
468
469 match shell {
470 Shell::Fish => get_fish_functions_dir().join("try-rs.fish"),
471 Shell::Zsh => config_dir.join("try-rs.zsh"),
472 Shell::Bash => config_dir.join("try-rs.bash"),
473 Shell::PowerShell => config_dir.join("try-rs.ps1"),
474 Shell::NuShell => config_dir.join("try-rs.nu"),
475 }
476}
477
478fn get_fish_functions_dir() -> PathBuf {
479 if let Ok(output) = std::process::Command::new("fish")
480 .args(["-c", "echo $__fish_config_dir"])
481 .output()
482 {
483 if output.status.success() {
484 let output_str = String::from_utf8_lossy(&output.stdout);
485 let path = PathBuf::from(output_str.trim()).join("functions");
486 if path.exists() || path.parent().map(|p| p.exists()).unwrap_or(false) {
487 return path;
488 }
489 }
490 }
491 get_base_config_dir().join("fish").join("functions")
492}
493
494fn write_fish_picker_function() -> Result<PathBuf> {
495 let file_path = get_fish_functions_dir().join("try-rs-picker.fish");
496 if let Some(parent) = file_path.parent()
497 && !parent.exists()
498 {
499 fs::create_dir_all(parent)?;
500 }
501 fs::write(&file_path, FISH_PICKER_FUNCTION)?;
502 eprintln!(
503 "Fish picker function file created at: {}",
504 file_path.display()
505 );
506 Ok(file_path)
507}
508
509pub fn is_shell_integration_configured(shell: &Shell) -> bool {
510 get_shell_integration_path(shell).exists()
511}
512
513fn append_source_to_rc(rc_path: &std::path::Path, source_cmd: &str) -> Result<()> {
515 if rc_path.exists() {
516 let content = fs::read_to_string(rc_path)?;
517 if !content.contains(source_cmd) && !content.contains("# try-rs integration") {
519 let mut file = fs::OpenOptions::new().append(true).open(rc_path)?;
520 writeln!(file, "\n# try-rs integration")?;
521 writeln!(file, "{}", source_cmd)?;
522 eprintln!("Added configuration to {}", rc_path.display());
523 } else {
524 eprintln!("Configuration already present in {}", rc_path.display());
525 }
526 } else {
527 eprintln!(
528 "You need to add the following line to {}:",
529 rc_path.display()
530 );
531 eprintln!("{}", source_cmd);
532 }
533 Ok(())
534}
535
536fn write_shell_integration(shell: &Shell) -> Result<std::path::PathBuf> {
538 let file_path = get_shell_integration_path(shell);
539 if let Some(parent) = file_path.parent()
540 && !parent.exists()
541 {
542 fs::create_dir_all(parent)?;
543 }
544 fs::write(&file_path, get_shell_content(shell))?;
545 eprintln!(
546 "{:?} function file created at: {}",
547 shell,
548 file_path.display()
549 );
550 Ok(file_path)
551}
552
553pub fn setup_shell(shell: &Shell) -> Result<()> {
555 let file_path = write_shell_integration(shell)?;
556 let home_dir = dirs::home_dir().expect("Could not find home directory");
557
558 match shell {
559 Shell::Fish => {
560 let _picker_path = write_fish_picker_function()?;
561 let fish_config_path = home_dir.join(".config").join("fish").join("config.fish");
562 eprintln!(
563 "You may need to restart your shell or run 'source {}' to apply changes.",
564 file_path.display()
565 );
566 eprintln!(
567 "Optional: append the following to {} to bind Ctrl+T:",
568 fish_config_path.display()
569 );
570 eprintln!("bind \\ct try-rs-picker");
571 eprintln!("bind -M insert \\ct try-rs-picker");
572 }
573 Shell::Zsh => {
574 let source_cmd = format!("source '{}'", file_path.display());
575 append_source_to_rc(&home_dir.join(".zshrc"), &source_cmd)?;
576 }
577 Shell::Bash => {
578 let source_cmd = format!("source '{}'", file_path.display());
579 append_source_to_rc(&home_dir.join(".bashrc"), &source_cmd)?;
580 }
581 Shell::PowerShell => {
582 let profile_path_ps7 = home_dir
583 .join("Documents")
584 .join("PowerShell")
585 .join("Microsoft.PowerShell_profile.ps1");
586 let profile_path_ps5 = home_dir
587 .join("Documents")
588 .join("WindowsPowerShell")
589 .join("Microsoft.PowerShell_profile.ps1");
590 let profile_path = if profile_path_ps7.exists() {
591 profile_path_ps7
592 } else if profile_path_ps5.exists() {
593 profile_path_ps5
594 } else {
595 profile_path_ps7
596 };
597
598 if let Some(parent) = profile_path.parent()
599 && !parent.exists()
600 {
601 fs::create_dir_all(parent)?;
602 }
603
604 let source_cmd = format!(". '{}'", file_path.display());
605 if profile_path.exists() {
606 append_source_to_rc(&profile_path, &source_cmd)?;
607 } else {
608 let mut file = fs::File::create(&profile_path)?;
609 writeln!(file, "# try-rs integration")?;
610 writeln!(file, "{}", source_cmd)?;
611 eprintln!(
612 "PowerShell profile created and configured at: {}",
613 profile_path.display()
614 );
615 }
616
617 eprintln!(
618 "You may need to restart your shell or run '. {}' to apply changes.",
619 profile_path.display()
620 );
621 eprintln!(
622 "If you get an error about running scripts, you may need to run: Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned"
623 );
624 }
625 Shell::NuShell => {
626 let nu_config_path = dirs::config_dir()
627 .expect("Could not find config directory")
628 .join("nushell")
629 .join("config.nu");
630 let source_cmd = format!("source '{}'", file_path.display());
631 if nu_config_path.exists() {
632 append_source_to_rc(&nu_config_path, &source_cmd)?;
633 } else {
634 eprintln!("Could not find config.nu at {}", nu_config_path.display());
635 eprintln!("Please add the following line manually:");
636 eprintln!("{}", source_cmd);
637 }
638 }
639 }
640
641 Ok(())
642}
643
644pub fn generate_completions(shell: &Shell) -> Result<()> {
646 let script = get_completion_script_only(shell);
647 print!("{}", script);
648 Ok(())
649}
650
651pub fn get_installed_shells() -> Vec<Shell> {
652 let mut shells = Vec::new();
653 for shell in [
654 Shell::Fish,
655 Shell::Zsh,
656 Shell::Bash,
657 Shell::PowerShell,
658 Shell::NuShell,
659 ] {
660 if is_shell_installed(&shell) {
661 shells.push(shell);
662 }
663 }
664 shells
665}
666
667fn is_shell_installed(shell: &Shell) -> bool {
668 let shell_name = match shell {
669 Shell::Fish => "fish",
670 Shell::Zsh => "zsh",
671 Shell::Bash => "bash",
672 Shell::PowerShell => "pwsh",
673 Shell::NuShell => "nu",
674 };
675
676 let output = std::process::Command::new("whereis")
677 .arg(shell_name)
678 .output();
679
680 match output {
681 Ok(out) => {
682 let result = String::from_utf8_lossy(&out.stdout);
683 let trimmed = result.trim();
684 !trimmed.is_empty()
685 && !trimmed.ends_with(':')
686 && trimmed.starts_with(&format!("{}: ", shell_name))
687 }
688 Err(_) => false,
689 }
690}
691
692pub fn clear_shell_setup() -> Result<()> {
693 let installed_shells = get_installed_shells();
694
695 if installed_shells.is_empty() {
696 eprintln!("No supported shells found on this system.");
697 return Ok(());
698 }
699
700 eprintln!("Detected shells: {:?}\n", installed_shells);
701
702 eprintln!("Files to be removed:");
703
704 for shell in &installed_shells {
705 let paths = get_shell_config_paths(shell);
706
707 for path in &paths {
708 eprintln!(" - {}", path.display());
709 }
710
711 match shell {
712 Shell::Fish => {
713 let fish_functions = get_fish_functions_dir();
714 eprintln!(
715 " - {}",
716 fish_functions.join("try-rs-picker.fish").display()
717 );
718 }
719 _ => {}
720 }
721 }
722
723 eprintln!("\nRemoving files...");
724
725 for shell in &installed_shells {
726 clear_shell_config(shell)?;
727 }
728
729 eprintln!("\nDone! Shell integration removed.");
730 Ok(())
731}
732
733fn clear_shell_config(shell: &Shell) -> Result<()> {
734 let integration_file = get_shell_integration_path(shell);
735 if integration_file.exists() {
736 fs::remove_file(&integration_file)?;
737 eprintln!("Removed integration file: {}", integration_file.display());
738 }
739
740 if let Shell::Fish = shell {
741 let picker_path = get_fish_functions_dir().join("try-rs-picker.fish");
742 if picker_path.exists() {
743 fs::remove_file(&picker_path)?;
744 eprintln!("Removed picker file: {}", picker_path.display());
745 }
746 }
747
748 let home_dir = dirs::home_dir().expect("Could not find home directory");
750 let rc_files = match shell {
751 Shell::Zsh => vec![home_dir.join(".zshrc")],
752 Shell::Bash => vec![home_dir.join(".bashrc")],
753 Shell::NuShell => vec![dirs::config_dir()
754 .expect("Could not find config directory")
755 .join("nushell")
756 .join("config.nu")],
757 Shell::PowerShell => {
758 let profile_path_ps7 = home_dir
759 .join("Documents")
760 .join("PowerShell")
761 .join("Microsoft.PowerShell_profile.ps1");
762 let profile_path_ps5 = home_dir
763 .join("Documents")
764 .join("WindowsPowerShell")
765 .join("Microsoft.PowerShell_profile.ps1");
766 vec![profile_path_ps7, profile_path_ps5]
767 },
768 _ => vec![],
769 };
770
771 for rc_path in rc_files {
772 if rc_path.exists() {
773 remove_source_from_rc(&rc_path)?;
774 }
775 }
776
777 Ok(())
778}
779
780fn remove_source_from_rc(rc_path: &std::path::Path) -> Result<()> {
781 let content = fs::read_to_string(rc_path)?;
782 if content.contains("try-rs") {
783 let mut lines: Vec<String> = content.lines().map(|s| s.to_string()).collect();
784 let initial_count = lines.len();
785
786 lines.retain(|line| {
788 !line.contains("# try-rs integration") &&
789 !(line.contains("source") && line.contains("try-rs")) &&
790 !(line.contains(".") && line.contains("try-rs") && rc_path.extension().map_or(false, |ext| ext == "ps1"))
791 });
792
793 if lines.len() < initial_count {
794 let mut new_content = lines.join("\n");
795 if !new_content.is_empty() && !new_content.ends_with('\n') {
796 new_content.push('\n');
797 }
798 fs::write(rc_path, new_content)?;
799 eprintln!("Cleaned up integration lines from {}", rc_path.display());
800 }
801 }
802 Ok(())
803}
804
805fn get_shell_config_paths(shell: &Shell) -> Vec<PathBuf> {
806 let mut paths = Vec::new();
807 let config_dir = get_base_config_dir();
808
809 match shell {
810 Shell::Fish => {
811 let fish_functions = get_fish_functions_dir();
812 paths.push(fish_functions.join("try-rs.fish"));
813 }
814 Shell::Zsh => {
815 paths.push(config_dir.join("try-rs.zsh"));
816 }
817 Shell::Bash => {
818 paths.push(config_dir.join("try-rs.bash"));
819 }
820 Shell::PowerShell => {
821 paths.push(config_dir.join("try-rs.ps1"));
822 }
823 Shell::NuShell => {
824 paths.push(config_dir.join("try-rs.nu"));
825 }
826 }
827
828 paths
829}
830