Skip to content
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

Print the root path relative to the initial root #758

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions man/page
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Show folders and files alike
\fB\-\-show\-root\-fs\fR
Show filesystem info on top
.TP
\fB\-\-root\-relative\-path\fR
Show the root path relative to the launch directory
.TP
\fB\-g\fR, \fB\-\-show\-git\-info\fR
Show git statuses on files and stats on repo
.TP
Expand Down
4 changes: 4 additions & 0 deletions src/app/app_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub struct AppContext {
/// Initial tree options
pub initial_tree_options: TreeOptions,

/// Initial working directory. This is where `broot` is launched, not the root path!
pub initial_working_dir: PathBuf,

/// where's the config file we're using
/// This vec can't be empty
pub config_paths: Vec<PathBuf>,
Expand Down Expand Up @@ -159,6 +162,7 @@ impl AppContext {
initial_root,
initial_file,
initial_tree_options,
initial_working_dir: std::env::current_dir()?,
config_paths,
launch_args,
verb_store,
Expand Down
15 changes: 15 additions & 0 deletions src/app/panel_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,21 @@ pub trait PanelState {
con,
)
}
Internal::toggle_root_relative => {
self.with_new_options(
screen,
&|o| {
o.relative_root ^= true;
if o.relative_root {
"*displaying root relative to launch dir*"
} else {
"*displaying root as absolute path*"
}
},
bang,
con,
)
}
Internal::toggle_git_ignore => {
self.with_new_options(
screen,
Expand Down
2 changes: 1 addition & 1 deletion src/browser/browser_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ impl PanelState for BrowserState {
disc: &DisplayContext,
) -> Result<(), ProgramError> {
let dp = DisplayableTree {
app_state: Some(disc.app_state),
display_context: Some(disc),
tree: self.displayed_tree(),
skin: &disc.panel_skin.styles,
ext_colors: &disc.con.ext_colors,
Expand Down
4 changes: 4 additions & 0 deletions src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ pub struct Args {
#[arg(long)]
pub show_root_fs: bool,

/// Show the root path relative to the launch directory.
#[arg(long)]
pub root_relative_path: bool,

/// Show git statuses on files and stats on repo
#[arg(short='g', long)]
pub show_git_info: bool,
Expand Down
4 changes: 4 additions & 0 deletions src/conf/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ pub struct Conf {

#[serde(alias="content-search-max-file-size", deserialize_with="file_size::deserialize", default)]
pub content_search_max_file_size: Option<u64>,

#[serde(alias="root-relative-path")]
pub root_relative_path: Option<bool>,
}

impl Conf {
Expand Down Expand Up @@ -187,6 +190,7 @@ impl Conf {
overwrite!(self, max_staged_count, conf);
overwrite!(self, show_matching_characters_on_path_searches, conf);
overwrite!(self, content_search_max_file_size, conf);
overwrite!(self, root_relative_path, conf);
self.verbs.append(&mut conf.verbs);
// the following maps are "additive": we can add entries from several
// config files and they still make sense
Expand Down
25 changes: 17 additions & 8 deletions src/display/displayable_tree.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::app::DisplayContext;
use crate::path::relativize_path;

use {
super::{
cond_bg,
Expand All @@ -9,7 +12,6 @@ use {
SPACE_FILLING, BRANCH_FILLING,
},
crate::{
app::AppState,
content_search::ContentMatch,
errors::ProgramError,
file_sum::FileSum,
Expand Down Expand Up @@ -37,7 +39,7 @@ use {
/// - a scrollbar may be drawn
/// - the empty lines will be erased
pub struct DisplayableTree<'a, 's, 't> {
pub app_state: Option<&'a AppState>,
pub display_context: Option<&'a DisplayContext<'a>>,
pub tree: &'t Tree,
pub skin: &'s StyleMap,
pub area: termimad::Area,
Expand All @@ -55,7 +57,7 @@ impl<'a, 's, 't> DisplayableTree<'a, 's, 't> {
height: u16,
) -> DisplayableTree<'a, 's, 't> {
DisplayableTree {
app_state: None,
display_context: None,
tree,
skin,
ext_colors,
Expand Down Expand Up @@ -413,8 +415,15 @@ impl<'a, 's, 't> DisplayableTree<'a, 's, 't> {
)?;
}
}
let title = line.path.to_string_lossy();
cw.queue_str(style, &title)?;
match self.display_context {
Some(context) if self.tree.options.relative_root => {
cw.queue_str(style, &relativize_path(&line.path, context.con)?)?;
},
_ => {
cw.queue_str(style, &line.path.to_string_lossy())?;
},
}

if self.in_app && !cw.is_full() {
if let ComputationResult::Done(git_status) = &self.tree.git_status {
let git_status_display = GitStatusDisplay::from(
Expand Down Expand Up @@ -486,7 +495,7 @@ impl<'a, 's, 't> DisplayableTree<'a, 's, 't> {
.options
.cols_order
.iter()
.filter(|col| col.is_visible(tree, self.app_state))
.filter(|col| col.is_visible(tree, self.display_context.map(|con| con.app_state)))
.cloned()
.collect();

Expand Down Expand Up @@ -536,8 +545,8 @@ impl<'a, 's, 't> DisplayableTree<'a, 's, 't> {
if visible_cols[0].needs_left_margin() {
cw.queue_char(space_style, ' ')?;
}
let staged = self.app_state
.map_or(false, |a| a.stage.contains(&line.path));
let staged = self.display_context
.map_or(false, |a| a.app_state.stage.contains(&line.path));
for col in &visible_cols {
let void_len = match col {

Expand Down
2 changes: 2 additions & 0 deletions src/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod closest;
mod from;
mod normalize;
mod special_path;
mod relative;

pub use {
anchor::*,
Expand All @@ -12,4 +13,5 @@ pub use {
from::*,
normalize::*,
special_path::*,
relative::*,
};
23 changes: 23 additions & 0 deletions src/path/relative.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::io;
use std::path::Path;

use crate::app::AppContext;

pub fn relativize_path(path: &Path, con: &AppContext) -> io::Result<String> {
let relative_path = match pathdiff::diff_paths(path, &con.initial_working_dir) {
None => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("Cannot relativize {path:?}"), // does this happen ? how ?
));
}
Some(p) => p,
};
Ok(
if relative_path.components().next().is_some() {
relative_path.to_string_lossy().to_string()
} else {
".".to_string()
}
)
}
2 changes: 1 addition & 1 deletion src/preview/dir_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl DirView {
self.page_height = Some(page_height);
}
let dp = DisplayableTree {
app_state: None,
display_context: None,
tree: &self.tree,
skin: &disc.panel_skin.styles,
ext_colors: &disc.con.ext_colors,
Expand Down
27 changes: 3 additions & 24 deletions src/print.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! functions printing a tree or a path
use crate::path::relativize_path;

use {
crate::{
app::*,
Expand All @@ -10,11 +12,7 @@ use {
tree::Tree,
},
crokey::crossterm::tty::IsTty,
pathdiff,
std::{
io::{self, stdout},
path::Path,
},
std::io::{self, stdout},
};

fn print_string(string: String, _con: &AppContext) -> io::Result<CmdResult> {
Expand Down Expand Up @@ -42,25 +40,6 @@ pub fn print_paths(sel_info: SelInfo, con: &AppContext) -> io::Result<CmdResult>
print_string(string, con)
}

fn relativize_path(path: &Path, con: &AppContext) -> io::Result<String> {
let relative_path = match pathdiff::diff_paths(path, &con.initial_root) {
None => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("Cannot relativize {path:?}"), // does this happen ? how ?
));
}
Some(p) => p,
};
Ok(
if relative_path.components().next().is_some() {
relative_path.to_string_lossy().to_string()
} else {
".".to_string()
}
)
}

pub fn print_relative_paths(sel_info: SelInfo, con: &AppContext) -> io::Result<CmdResult> {
let string = match sel_info {
SelInfo::None => "".to_string(),
Expand Down
12 changes: 11 additions & 1 deletion src/tree/tree_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub struct TreeOptions {
pub show_device_id: bool,
pub show_root_fs: bool, // show information relative to the fs of the root
pub trim_root: bool, // whether to cut out direct children of root
/// Show root directory relative to the program's current working directory.
pub relative_root: bool,
pub show_permissions: bool, // show classic rwx unix permissions (only on unix)
pub respect_git_ignore: bool, // hide files as requested by .gitignore ?
pub filter_by_git_status: bool, // only show files whose git status is not nul
Expand Down Expand Up @@ -51,6 +53,7 @@ impl TreeOptions {
show_device_id: self.show_device_id,
show_root_fs: self.show_root_fs,
trim_root: self.trim_root,
relative_root: self.relative_root,
pattern: InputPattern::none(),
date_time_format: self.date_time_format,
sort: self.sort,
Expand Down Expand Up @@ -85,7 +88,7 @@ impl TreeOptions {
let conf_matches = Args::try_parse_from(vec!["broot", &flags_args])
.map_err(|_| ConfError::InvalidDefaultFlags {
flags: default_flags.to_string()
})?;
})?;
self.apply_launch_args(&conf_matches);
}
if let Some(b) = config.show_selection_mark {
Expand All @@ -97,6 +100,9 @@ impl TreeOptions {
if let Some(b) = config.show_matching_characters_on_path_searches {
self.show_matching_characters_on_path_searches = b;
}
if let Some(b) = config.root_relative_path {
self.relative_root = b;
}
self.cols_order = config
.cols_order
.as_ref()
Expand Down Expand Up @@ -183,6 +189,9 @@ impl TreeOptions {
} else if cli_args.no_trim_root {
self.trim_root = false;
}
if cli_args.root_relative_path {
self.relative_root = true;
}
}
}

Expand All @@ -199,6 +208,7 @@ impl Default for TreeOptions {
show_device_id: false,
show_root_fs: false,
trim_root: false,
relative_root: false,
show_permissions: false,
respect_git_ignore: true,
filter_by_git_status: false,
Expand Down
1 change: 1 addition & 0 deletions src/verb/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ Internals! {
toggle_git_file_info: "toggle display of git file information" false,
toggle_git_status: "toggle showing only files relevant for git status" false,
toggle_root_fs: "toggle showing filesystem info on top" false,
toggle_root_relative: "toggle displaying root path relative to launch dir" false,
toggle_hidden: "toggle showing hidden files" false,
toggle_perm: "toggle showing file permissions" false,
toggle_sizes: "toggle showing sizes" false,
Expand Down
1 change: 1 addition & 0 deletions src/verb/verb_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ impl VerbStore {
self.add_internal(toggle_git_file_info).with_shortcut("gf");
self.add_internal(toggle_git_status).with_shortcut("gs");
self.add_internal(toggle_root_fs).with_shortcut("rfs");
self.add_internal(toggle_root_relative);
self.add_internal(toggle_hidden)
.with_key(key!(alt-h))
.with_shortcut("h");
Expand Down
13 changes: 13 additions & 0 deletions website/docs/conf_file.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,16 @@ show_matching_characters_on_path_searches = false
which gives this:

![not shown](img/subpath-match-not-shown.png)

## Show the root path relative to the launch directory

If you'd prefer the root path (the top line in the tree display) to be
displayed relative to the directory `broot` is launched in (not the root
directory passed on the command line), you can use this option:

```Hjson
root-relative-path: true
```
```TOML
root_relative_path = true
```
1 change: 1 addition & 0 deletions website/docs/conf_verbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ invocation | default key | default shortcut | behavior / details
:toggle_stage | <kbd>ctrl</kbd><kbd>g</kbd> | - | add or remove selection to staging area
:toggle_staging_area | - | tsa | open/close the staging area panel
:toggle_trim_root | - | - | toggle trimming of top level files in tree display
:toggle_root_relative | - | - | toggle display of root path relative to launch dir or absolute
:unstage | <kbd>-</kbd> | - | remove selection from staging area
:up_tree | - | - | focus the parent of the current root

Expand Down