@@ -29,16 +29,23 @@ use crate::config::Config;
2929use crate :: constants:: {
3030 section_header, ACTION_CHANGE_BRANCH_NAME , ACTION_CREATE_NEW_BRANCH , ACTION_USE_LOCAL_BRANCH ,
3131 ACTION_USE_WORKTREE_NAME , BRANCH_OPTION_SELECT_BRANCH , BRANCH_OPTION_SELECT_TAG , CHAR_DOT ,
32- CONFIG_FILE_NAME , DEFAULT_EMPTY_STRING , DEFAULT_REPO_NAME , DEFAULT_WORKTREE_CLEANUP_DAYS ,
32+ CONFIG_FILE_NAME , DEFAULT_BRANCH_DETACHED , DEFAULT_BRANCH_UNKNOWN , DEFAULT_EDITOR_UNIX ,
33+ DEFAULT_EDITOR_WINDOWS , DEFAULT_EMPTY_STRING , DEFAULT_MENU_SELECTION , DEFAULT_REPO_NAME ,
34+ DEFAULT_WORKTREE_CLEANUP_DAYS , EMOJI_DETACHED , EMOJI_FOLDER , EMOJI_HOME , EMOJI_LOCKED ,
35+ ENV_EDITOR , ENV_VISUAL , ERROR_CUSTOM_PATH_EMPTY , ERROR_WORKTREE_NAME_EMPTY ,
3336 FUZZY_SEARCH_THRESHOLD , GIT_CRITICAL_DIRS , GIT_DIR , GIT_REMOTE_PREFIX , GIT_RESERVED_NAMES ,
34- HOOK_POST_CREATE , HOOK_POST_SWITCH , HOOK_PRE_REMOVE , ICON_ARROW , ICON_LIST , ICON_LOCAL_BRANCH ,
37+ HEADER_CREATE_WORKTREE , HEADER_SEARCH_WORKTREES , HEADER_WORKTREES , HOOK_POST_CREATE ,
38+ HOOK_POST_SWITCH , HOOK_PRE_REMOVE , ICON_ARROW , ICON_LIST , ICON_LOCAL_BRANCH ,
3539 ICON_REMOTE_BRANCH , ICON_SWITCH , ICON_TAG_INDICATOR , INFO_TIP , INFO_USE_CREATE ,
3640 INVALID_FILESYSTEM_CHARS , LABEL_BRANCH , LABEL_MODIFIED , LABEL_NAME , LABEL_NO , LABEL_PATH ,
37- LABEL_YES , MAX_WORKTREE_NAME_LENGTH , MIN_PATH_COMPONENTS_FOR_SUBDIR ,
38- PATH_COMPONENT_SECOND_INDEX , PROGRESS_BAR_TICK_MILLIS , TAG_MESSAGE_TRUNCATE_LENGTH ,
39- UI_BRANCH_COL_EXTRA_WIDTH , UI_FOOTER_LINES , UI_HEADER_LINES , UI_MIN_ITEMS_PER_PAGE ,
40- UI_MODIFIED_COL_WIDTH , UI_NAME_COL_MIN_WIDTH , UI_PATH_COL_WIDTH , WARNING_NO_WORKTREES ,
41- WINDOWS_RESERVED_CHARS , WORKTREES_SUBDIR , WORKTREE_LOCATION_CUSTOM_PATH ,
41+ LABEL_YES , MAX_WORKTREE_NAME_LENGTH , MIN_PATH_COMPONENTS_FOR_SUBDIR , MSG_ALREADY_IN_WORKTREE ,
42+ MSG_NO_WORKTREES_TO_SEARCH , MSG_SEARCH_FUZZY_ENABLED , PATH_COMPONENT_SECOND_INDEX ,
43+ PROGRESS_BAR_TICK_MILLIS , PROMPT_CONFLICT_ACTION , PROMPT_CUSTOM_PATH , PROMPT_SELECT_BRANCH ,
44+ PROMPT_SELECT_BRANCH_OPTION , PROMPT_SELECT_TAG , PROMPT_SELECT_WORKTREE_LOCATION ,
45+ PROMPT_SELECT_WORKTREE_SWITCH , PROMPT_WORKTREE_NAME , SEARCH_CURRENT_INDICATOR ,
46+ TAG_MESSAGE_TRUNCATE_LENGTH , UI_BRANCH_COL_EXTRA_WIDTH , UI_FOOTER_LINES , UI_HEADER_LINES ,
47+ UI_MIN_ITEMS_PER_PAGE , UI_MODIFIED_COL_WIDTH , UI_NAME_COL_MIN_WIDTH , UI_PATH_COL_WIDTH ,
48+ WARNING_NO_WORKTREES , WINDOWS_RESERVED_CHARS , WORKTREES_SUBDIR , WORKTREE_LOCATION_CUSTOM_PATH ,
4249 WORKTREE_LOCATION_SAME_LEVEL , WORKTREE_LOCATION_SUBDIRECTORY ,
4350} ;
4451use crate :: file_copy;
@@ -84,13 +91,13 @@ fn get_worktree_icon_internal(is_current: bool) -> colored::ColoredString {
8491#[ allow( dead_code) ]
8592pub fn get_worktree_icon ( worktree : & WorktreeInfo ) -> & ' static str {
8693 if worktree. is_current {
87- "🏠"
94+ EMOJI_HOME
8895 } else if worktree. is_locked {
89- "🔒"
90- } else if worktree. branch == "detached" {
91- "🔗"
96+ EMOJI_LOCKED
97+ } else if worktree. branch == DEFAULT_BRANCH_DETACHED {
98+ EMOJI_DETACHED
9299 } else {
93- "📁"
100+ EMOJI_FOLDER
94101 }
95102}
96103
@@ -202,7 +209,7 @@ pub fn list_worktrees_with_git(git_ops: &dyn GitReadOperations) -> Result<()> {
202209
203210 // Print header
204211 println ! ( ) ;
205- let header = section_header ( "Worktrees" ) ;
212+ let header = section_header ( HEADER_WORKTREES ) ;
206213 println ! ( "{header}" ) ;
207214
208215 let start_idx = current_page * items_per_page;
@@ -354,15 +361,15 @@ fn search_worktrees_internal(manager: &GitWorktreeManager) -> Result<bool> {
354361
355362 if worktrees. is_empty ( ) {
356363 println ! ( ) ;
357- let msg = "• No worktrees to search." . yellow ( ) ;
364+ let msg = MSG_NO_WORKTREES_TO_SEARCH . yellow ( ) ;
358365 println ! ( "{msg}" ) ;
359366 println ! ( ) ;
360367 press_any_key_to_continue ( ) ?;
361368 return Ok ( false ) ;
362369 }
363370
364371 println ! ( ) ;
365- let header = section_header ( "Search Worktrees" ) ;
372+ let header = section_header ( HEADER_SEARCH_WORKTREES ) ;
366373 println ! ( "{header}" ) ;
367374 println ! ( ) ;
368375
@@ -372,16 +379,16 @@ fn search_worktrees_internal(manager: &GitWorktreeManager) -> Result<bool> {
372379 . map ( |wt| {
373380 let mut item = format ! ( "{} ({})" , wt. name, wt. branch) ;
374381 if wt. is_current {
375- item. push_str ( " (current)" ) ;
382+ item. push_str ( SEARCH_CURRENT_INDICATOR ) ;
376383 }
377384 item
378385 } )
379386 . collect ( ) ;
380387
381388 // Use FuzzySelect for interactive search
382- println ! ( "Type to search worktrees (fuzzy search enabled): " ) ;
389+ println ! ( "{MSG_SEARCH_FUZZY_ENABLED} " ) ;
383390 let selection = match FuzzySelect :: with_theme ( & get_theme ( ) )
384- . with_prompt ( "Select a worktree to switch to" )
391+ . with_prompt ( PROMPT_SELECT_WORKTREE_SWITCH )
385392 . items ( & items)
386393 . interact_opt ( ) ?
387394 {
@@ -393,7 +400,7 @@ fn search_worktrees_internal(manager: &GitWorktreeManager) -> Result<bool> {
393400
394401 if selected_worktree. is_current {
395402 println ! ( ) ;
396- let msg = "• Already in this worktree." . yellow ( ) ;
403+ let msg = MSG_ALREADY_IN_WORKTREE . yellow ( ) ;
397404 println ! ( "{msg}" ) ;
398405 println ! ( ) ;
399406 press_any_key_to_continue ( ) ?;
@@ -529,7 +536,7 @@ pub fn create_worktree_with_ui(
529536 ui : & dyn UserInterface ,
530537) -> Result < bool > {
531538 println ! ( ) ;
532- let header = section_header ( "Create New Worktree" ) ;
539+ let header = section_header ( HEADER_CREATE_WORKTREE ) ;
533540 println ! ( "{header}" ) ;
534541 println ! ( ) ;
535542
@@ -538,13 +545,13 @@ pub fn create_worktree_with_ui(
538545 let has_worktrees = !existing_worktrees. is_empty ( ) ;
539546
540547 // Get worktree name
541- let name = match ui. input ( "Enter worktree name" ) {
548+ let name = match ui. input ( PROMPT_WORKTREE_NAME ) {
542549 Ok ( name) => name. trim ( ) . to_string ( ) ,
543550 Err ( _) => return Ok ( false ) ,
544551 } ;
545552
546553 if name. is_empty ( ) {
547- utils:: print_error ( "Worktree name cannot be empty" ) ;
554+ utils:: print_error ( ERROR_WORKTREE_NAME_EMPTY ) ;
548555 return Ok ( false ) ;
549556 }
550557
@@ -577,7 +584,11 @@ pub fn create_worktree_with_ui(
577584 "Custom path (specify relative to project root)" . to_string( ) ,
578585 ] ;
579586
580- let selection = match ui. select ( "Select worktree location pattern" , & options) {
587+ let selection = match ui. select_with_default (
588+ PROMPT_SELECT_WORKTREE_LOCATION ,
589+ & options,
590+ DEFAULT_MENU_SELECTION ,
591+ ) {
581592 Ok ( selection) => selection,
582593 Err ( _) => return Ok ( false ) ,
583594 } ;
@@ -594,13 +605,13 @@ pub fn create_worktree_with_ui(
594605 "Examples: ../custom-dir/worktree-name, temp/worktrees/name" . dimmed ( ) ;
595606 println ! ( "{examples}" ) ;
596607
597- let custom_path = match ui. input ( "Custom path" ) {
608+ let custom_path = match ui. input ( PROMPT_CUSTOM_PATH ) {
598609 Ok ( path) => path. trim ( ) . to_string ( ) ,
599610 Err ( _) => return Ok ( false ) ,
600611 } ;
601612
602613 if custom_path. is_empty ( ) {
603- utils:: print_error ( "Custom path cannot be empty" ) ;
614+ utils:: print_error ( ERROR_CUSTOM_PATH_EMPTY ) ;
604615 return Ok ( false ) ;
605616 }
606617
@@ -626,7 +637,11 @@ pub fn create_worktree_with_ui(
626637 "Select tag" . to_string( ) ,
627638 ] ;
628639
629- let branch_choice = match ui. select ( "Select branch option" , & branch_options) {
640+ let branch_choice = match ui. select_with_default (
641+ PROMPT_SELECT_BRANCH_OPTION ,
642+ & branch_options,
643+ DEFAULT_MENU_SELECTION ,
644+ ) {
630645 Ok ( choice) => choice,
631646 Err ( _) => return Ok ( false ) ,
632647 } ;
@@ -677,9 +692,13 @@ pub fn create_worktree_with_ui(
677692 // Use FuzzySelect for better search experience when there are many branches
678693 let selection_result = if branch_items. len ( ) > FUZZY_SEARCH_THRESHOLD {
679694 println ! ( "Type to search branches (fuzzy search enabled):" ) ;
680- ui. fuzzy_select ( "Select a branch" , & branch_items)
695+ ui. fuzzy_select ( PROMPT_SELECT_BRANCH , & branch_items)
681696 } else {
682- ui. select ( "Select a branch" , & branch_items)
697+ ui. select_with_default (
698+ PROMPT_SELECT_BRANCH ,
699+ & branch_items,
700+ DEFAULT_MENU_SELECTION ,
701+ )
683702 } ;
684703 let selection_result = selection_result. ok ( ) ;
685704
@@ -709,7 +728,11 @@ pub fn create_worktree_with_ui(
709728 "Cancel" . to_string( ) ,
710729 ] ;
711730
712- match ui. select ( "What would you like to do?" , & action_options) {
731+ match ui. select_with_default (
732+ PROMPT_CONFLICT_ACTION ,
733+ & action_options,
734+ DEFAULT_MENU_SELECTION ,
735+ ) {
713736 Ok ( ACTION_USE_WORKTREE_NAME ) => {
714737 // Use worktree name as new branch name
715738 ( Some ( selected_branch. clone ( ) ) , Some ( name. clone ( ) ) )
@@ -779,7 +802,11 @@ pub fn create_worktree_with_ui(
779802 "Cancel" . to_string( ) ,
780803 ] ;
781804
782- match ui. select ( "What would you like to do?" , & action_options) {
805+ match ui. select_with_default (
806+ PROMPT_CONFLICT_ACTION ,
807+ & action_options,
808+ DEFAULT_MENU_SELECTION ,
809+ ) {
783810 Ok ( ACTION_CREATE_NEW_BRANCH ) => {
784811 // Create new branch with worktree name
785812 (
@@ -846,9 +873,9 @@ pub fn create_worktree_with_ui(
846873 // Use FuzzySelect for better search experience when there are many tags
847874 let selection_result = if tag_items. len ( ) > FUZZY_SEARCH_THRESHOLD {
848875 println ! ( "Type to search tags (fuzzy search enabled):" ) ;
849- ui. fuzzy_select ( "Select a tag" , & tag_items)
876+ ui. fuzzy_select ( PROMPT_SELECT_TAG , & tag_items)
850877 } else {
851- ui. select ( "Select a tag" , & tag_items)
878+ ui. select_with_default ( PROMPT_SELECT_TAG , & tag_items, DEFAULT_MENU_SELECTION )
852879 } ;
853880 let selection_result = selection_result. ok ( ) ;
854881
@@ -1091,7 +1118,11 @@ pub fn delete_worktree_with_ui(manager: &GitWorktreeManager, ui: &dyn UserInterf
10911118 . map ( |w| format ! ( "{} ({})" , w. name, w. branch) )
10921119 . collect ( ) ;
10931120
1094- let selection = match ui. select ( "Select a worktree to delete (ESC to cancel)" , & items) {
1121+ let selection = match ui. select_with_default (
1122+ "Select a worktree to delete (ESC to cancel)" ,
1123+ & items,
1124+ DEFAULT_MENU_SELECTION ,
1125+ ) {
10951126 Ok ( selection) => selection,
10961127 Err ( _) => return Ok ( ( ) ) ,
10971128 } ;
@@ -1261,13 +1292,20 @@ pub fn switch_worktree_with_ui(
12611292 } )
12621293 . collect ( ) ;
12631294
1264- let selection = ui. select ( "Select a worktree to switch to (ESC to cancel)" , & items) ?;
1295+ let selection = match ui. select_with_default (
1296+ "Select a worktree to switch to (ESC to cancel)" ,
1297+ & items,
1298+ DEFAULT_MENU_SELECTION ,
1299+ ) {
1300+ Ok ( selection) => selection,
1301+ Err ( _) => return Ok ( false ) ,
1302+ } ;
12651303
12661304 let selected_worktree = & sorted_worktrees[ selection] ;
12671305
12681306 if selected_worktree. is_current {
12691307 println ! ( ) ;
1270- let msg = "• Already in this worktree." . yellow ( ) ;
1308+ let msg = MSG_ALREADY_IN_WORKTREE . yellow ( ) ;
12711309 println ! ( "{msg}" ) ;
12721310 println ! ( ) ;
12731311 press_any_key_to_continue ( ) ?;
@@ -1741,16 +1779,23 @@ pub fn rename_worktree_with_ui(manager: &GitWorktreeManager, ui: &dyn UserInterf
17411779 . map ( |w| format ! ( "{} ({})" , w. name, w. branch) )
17421780 . collect ( ) ;
17431781
1744- let selection = ui. select ( "Select a worktree to rename (ESC to cancel)" , & items) ?;
1782+ let selection = match ui. select_with_default (
1783+ "Select a worktree to rename (ESC to cancel)" ,
1784+ & items,
1785+ DEFAULT_MENU_SELECTION ,
1786+ ) {
1787+ Ok ( selection) => selection,
1788+ Err ( _) => return Ok ( ( ) ) ,
1789+ } ;
17451790
17461791 let worktree = renameable_worktrees[ selection] ;
17471792
17481793 // Get new name
17491794 println ! ( ) ;
1750- let new_name = ui
1751- . input ( & format ! ( "New name for '{}' (ESC to cancel)" , worktree . name ) ) ?
1752- . trim ( )
1753- . to_string ( ) ;
1795+ let new_name = match ui . input ( & format ! ( "New name for '{}' (ESC to cancel)" , worktree . name ) ) {
1796+ Ok ( name) => name . trim ( ) . to_string ( ) ,
1797+ Err ( _ ) => return Ok ( ( ) ) ,
1798+ } ;
17541799
17551800 if new_name. is_empty ( ) {
17561801 utils:: print_error ( "Name cannot be empty" ) ;
@@ -1774,13 +1819,16 @@ pub fn rename_worktree_with_ui(manager: &GitWorktreeManager, ui: &dyn UserInterf
17741819 }
17751820
17761821 // Check if the worktree has a branch that could be renamed
1777- let rename_branch = if worktree. branch != "detached"
1778- && worktree. branch != "unknown"
1822+ let rename_branch = if worktree. branch != DEFAULT_BRANCH_DETACHED
1823+ && worktree. branch != DEFAULT_BRANCH_UNKNOWN
17791824 && ( worktree. branch == worktree. name
17801825 || worktree. branch == format ! ( "feature/{}" , worktree. name) )
17811826 {
17821827 println ! ( ) ;
1783- ui. confirm_with_default ( "Also rename the associated branch?" , true ) ?
1828+ match ui. confirm_with_default ( "Also rename the associated branch?" , true ) {
1829+ Ok ( confirm) => confirm,
1830+ Err ( _) => return Ok ( ( ) ) ,
1831+ }
17841832 } else {
17851833 false
17861834 } ;
@@ -1813,7 +1861,10 @@ pub fn rename_worktree_with_ui(manager: &GitWorktreeManager, ui: &dyn UserInterf
18131861 }
18141862
18151863 println ! ( ) ;
1816- let confirm = ui. confirm_with_default ( "Proceed with rename?" , false ) ?;
1864+ let confirm = match ui. confirm_with_default ( "Proceed with rename?" , false ) {
1865+ Ok ( confirm) => confirm,
1866+ Err ( _) => return Ok ( ( ) ) ,
1867+ } ;
18171868
18181869 if !confirm {
18191870 return Ok ( ( ) ) ;
@@ -2505,13 +2556,13 @@ copy = [
25052556 }
25062557
25072558 // Get the user's preferred editor
2508- let editor = std:: env:: var ( "EDITOR" )
2509- . or_else ( |_| std:: env:: var ( "VISUAL" ) )
2559+ let editor = std:: env:: var ( ENV_EDITOR )
2560+ . or_else ( |_| std:: env:: var ( ENV_VISUAL ) )
25102561 . unwrap_or_else ( |_| {
25112562 if cfg ! ( target_os = "windows" ) {
2512- "notepad" . to_string ( )
2563+ DEFAULT_EDITOR_WINDOWS . to_string ( )
25132564 } else {
2514- "vi" . to_string ( )
2565+ DEFAULT_EDITOR_UNIX . to_string ( )
25152566 }
25162567 } ) ;
25172568
0 commit comments