-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
ls -lF symlink target indicators
#11554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,7 +93,7 @@ pub(crate) struct DisplayItemName { | |
| pub(crate) dired_name_len: usize, | ||
| } | ||
|
|
||
| #[derive(PartialEq, Eq)] | ||
| #[derive(Clone, Copy, PartialEq, Eq)] | ||
| pub(crate) enum IndicatorStyle { | ||
| None, | ||
| Slash, | ||
|
|
@@ -704,29 +704,12 @@ fn display_item_name( | |
| } | ||
| } | ||
|
|
||
| if config.indicator_style != IndicatorStyle::None { | ||
| let sym = classify_file(path); | ||
|
|
||
| let char_opt = match config.indicator_style { | ||
| IndicatorStyle::Classify => sym, | ||
| IndicatorStyle::FileType => { | ||
| // Don't append an asterisk. | ||
| match sym { | ||
| Some('*') => None, | ||
| _ => sym, | ||
| } | ||
| } | ||
| IndicatorStyle::Slash => { | ||
| // Append only a slash. | ||
| match sym { | ||
| Some('/') => Some('/'), | ||
| _ => None, | ||
| } | ||
| } | ||
| IndicatorStyle::None => None, | ||
| }; | ||
| let is_long_symlink = config.format == Format::Long | ||
| && path.file_type().is_some_and(FileType::is_symlink) | ||
| && !path.must_dereference; | ||
|
|
||
| if let Some(c) = char_opt { | ||
| if !is_long_symlink { | ||
| if let Some(c) = indicator_char(path, config.indicator_style) { | ||
| let _ = name.write_char(c); | ||
| } | ||
| } | ||
|
|
@@ -744,66 +727,68 @@ fn display_item_name( | |
| // We might as well color the symlink output after the arrow. | ||
| // This makes extra system calls, but provides important information that | ||
| // people run `ls -l --color` are very interested in. | ||
| if let Some(style_manager) = &mut style_manager { | ||
| let escaped_target = escape_name_with_locale(target_path.as_os_str(), config); | ||
| // We get the absolute path to be able to construct PathData with valid Metadata. | ||
| // This is because relative symlinks will fail to get_metadata. | ||
| let absolute_target = if target_path.is_relative() { | ||
| match path.path().parent() { | ||
| Some(p) => &p.join(&target_path), | ||
| None => &target_path, | ||
| } | ||
| } else { | ||
| &target_path | ||
| }; | ||
|
|
||
| match fs::canonicalize(absolute_target) { | ||
| Ok(resolved_target) => { | ||
| let target_data = PathData::new( | ||
| resolved_target.as_path().into(), | ||
| None, | ||
| target_path.file_name().map(Cow::Borrowed), | ||
| config, | ||
| false, | ||
| ); | ||
|
|
||
| // Check if the target actually needs coloring | ||
| let escaped_target = escape_name_with_locale(target_path.as_os_str(), config); | ||
|
|
||
| // We get the absolute path to be able to construct PathData with valid Metadata. | ||
| // This is because relative symlinks will fail to get_metadata. | ||
| let absolute_target = if target_path.is_relative() { | ||
| match path.path().parent() { | ||
| Some(p) => p.join(&target_path), | ||
| None => target_path.clone(), | ||
| } | ||
| } else { | ||
| target_path.clone() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not clone here; it is not necessary. Use references, like the previous code that you have replaced. This was fixed in edfe26c. |
||
| }; | ||
|
|
||
| match fs::canonicalize(&absolute_target) { | ||
| Ok(resolved_target) => { | ||
| let target_data = PathData::new( | ||
| resolved_target.as_path().into(), | ||
| None, | ||
| target_path.file_name().map(Cow::Borrowed), | ||
| config, | ||
| false, | ||
| ); | ||
|
|
||
| let mut target_display = escaped_target.clone(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not clone here. You should refactor the immediate assignment inside the if to be the expression of the let definition, like |
||
| if let Some(style_manager) = &mut style_manager { | ||
| let md_option: Option<Metadata> = target_data | ||
| .metadata() | ||
| .cloned() | ||
| .or_else(|| target_data.p_buf.symlink_metadata().ok()); | ||
| let style = style_manager.colors.style_for_path_with_metadata( | ||
| &target_data.p_buf, | ||
| md_option.as_ref(), | ||
| ); | ||
|
|
||
| if style.is_some() { | ||
| // Only apply coloring if there's actually a style | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep this comment if you can. |
||
| name.push(color_name( | ||
| escaped_target, | ||
| if style_manager | ||
| .colors | ||
| .style_for_path_with_metadata(&target_data.p_buf, md_option.as_ref()) | ||
| .is_some() | ||
| { | ||
| target_display = color_name( | ||
| escaped_target.clone(), | ||
| &target_data, | ||
| style_manager, | ||
| None, | ||
| is_wrap(name.len()), | ||
| )); | ||
| } else { | ||
| // For regular files with no coloring, just use plain text | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once/if you apply the other requested changes, consider keeping this comment. |
||
| name.push(escaped_target); | ||
| ); | ||
| } | ||
| } | ||
| Err(_) => { | ||
|
|
||
| name.push(target_display); | ||
| if let Some(c) = indicator_char(&target_data, config.indicator_style) { | ||
| let _ = name.write_char(c); | ||
| } | ||
| } | ||
| Err(_) => { | ||
| if let Some(style_manager) = &mut style_manager { | ||
| name.push( | ||
| style_manager.apply_missing_target_style( | ||
| escaped_target, | ||
| is_wrap(name.len()), | ||
| ), | ||
| ); | ||
| } else { | ||
| name.push(escaped_target); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please keep comments. Previously in L804-805. |
||
| } | ||
| } | ||
| } else { | ||
| // If no coloring is required, we just use target as is. | ||
| // Apply the right quoting | ||
| name.push(escape_name_with_locale(target_path.as_os_str(), config)); | ||
| } | ||
| } | ||
| Err(err) => { | ||
|
|
@@ -1118,6 +1103,23 @@ fn display_item_long( | |
| Ok(()) | ||
| } | ||
|
|
||
| fn indicator_char(path: &PathData, style: IndicatorStyle) -> Option<char> { | ||
| let sym = classify_file(path); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PD: please keep the old comments on the code you refactored to this new function. Did you vibecode this? Don't take it the wrong way; this is just a usual telltale. |
||
|
|
||
| match style { | ||
| IndicatorStyle::Classify => sym, | ||
| IndicatorStyle::FileType => match sym { | ||
| Some('*') => None, | ||
| _ => sym, | ||
| }, | ||
| IndicatorStyle::Slash => match sym { | ||
| Some('/') => Some('/'), | ||
| _ => None, | ||
| }, | ||
| IndicatorStyle::None => None, | ||
| } | ||
| } | ||
|
|
||
| fn classify_file(path: &PathData) -> Option<char> { | ||
| let file_type = path.file_type()?; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep this comment if you can.