Better symlink support

Closes: https://github.com/sayanarijit/xplr/issues/37
pull/60/head v0.4.3
Arijit Basu 3 years ago committed by Arijit Basu
parent 0d4cd29a08
commit af1cda5762

@ -78,17 +78,62 @@ impl Pipe {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct SymlinkNode {
pub absolute_path: String,
pub extension: String,
pub is_dir: bool,
pub is_file: bool,
pub is_readonly: bool,
pub mime_essence: String,
}
impl SymlinkNode {
pub fn from(path: PathBuf) -> Self {
let extension = path
.extension()
.map(|e| e.to_string_lossy().to_string())
.unwrap_or_default();
let maybe_metadata = path.metadata().ok();
let is_dir = maybe_metadata.clone().map(|m| m.is_dir()).unwrap_or(false);
let is_file = maybe_metadata.clone().map(|m| m.is_file()).unwrap_or(false);
let is_readonly = maybe_metadata
.map(|m| m.permissions().readonly())
.unwrap_or(false);
let mime_essence = mime_guess::from_path(&path)
.first()
.map(|m| m.essence_str().to_string())
.unwrap_or_default();
Self {
absolute_path: path.to_string_lossy().to_string(),
extension,
is_dir,
is_file,
is_readonly,
mime_essence,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Node {
pub parent: String,
pub relative_path: String,
pub absolute_path: String,
pub extension: String,
pub is_symlink: bool,
pub is_dir: bool,
pub is_file: bool,
pub is_symlink: bool,
pub is_broken: bool,
pub is_readonly: bool,
pub mime_essence: String,
pub symlink: Option<SymlinkNode>,
}
impl Node {
@ -112,6 +157,14 @@ impl Node {
.map(|m| m.file_type().is_symlink())
.unwrap_or(false);
let (is_broken, maybe_symlink_meta) = if is_symlink {
path.canonicalize()
.map(|p| (false, Some(SymlinkNode::from(p))))
.unwrap_or_else(|_| (true, None))
} else {
(false, None)
};
let is_dir = maybe_metadata.clone().map(|m| m.is_dir()).unwrap_or(false);
let is_file = maybe_metadata.clone().map(|m| m.is_file()).unwrap_or(false);
@ -130,11 +183,13 @@ impl Node {
relative_path,
absolute_path,
extension,
is_symlink,
is_dir,
is_file,
is_symlink,
is_broken,
is_readonly,
mime_essence,
symlink: maybe_symlink_meta,
}
}
}

@ -42,7 +42,11 @@ general:
height: 1
row:
cols:
- format: '{{{tree}}}{{{prefix}}}{{{meta.icon}}} {{{relativePath}}}{{#if isDir}}/{{/if}}{{{suffix}}}'
- format: >
{{{tree}}}{{{prefix}}}{{{meta.icon}}}
{{{relativePath}}}{{#if isDir}}/{{/if}}{{{suffix}}}
{{#if isSymlink}}-> {{#if isBroken}}×{{else}}{{{symlink.absolutePath}}}{{/if}}{{#if symlink.isDir}}/{{/if}}{{/if}}
style:
fg: null
bg: null
@ -50,7 +54,7 @@ general:
bits: 0
sub_modifier:
bits: 0
- format: '{{{mimeEssence}}}'
- format: '{{#if isSymlink}}{{{symlink.mimeEssence}}}{{else}}{{{mimeEssence}}}{{/if}}'
style:
fg: null
bg: null

@ -1,6 +1,6 @@
use crate::app;
use crate::app::HelpMenuLine;
use crate::app::Node;
use crate::app::{Node, SymlinkNode};
use handlebars::Handlebars;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
@ -13,6 +13,30 @@ use tui::text::{Span, Spans};
use tui::widgets::{Block, Borders, Cell, List, ListItem, Paragraph, Row, Table};
use tui::Frame;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SymlinkNodeUiMetadata {
pub absolute_path: String,
pub extension: String,
pub is_dir: bool,
pub is_file: bool,
pub is_readonly: bool,
pub mime_essence: String,
}
impl From<SymlinkNode> for SymlinkNodeUiMetadata {
fn from(node: SymlinkNode) -> Self {
Self {
absolute_path: node.absolute_path.clone(),
extension: node.extension.clone(),
is_dir: node.is_dir,
is_file: node.is_file,
is_readonly: node.is_readonly,
mime_essence: node.mime_essence,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct NodeUiMetadata {
@ -22,10 +46,12 @@ struct NodeUiMetadata {
pub absolute_path: String,
pub extension: String,
pub is_symlink: bool,
pub is_broken: bool,
pub is_dir: bool,
pub is_file: bool,
pub is_readonly: bool,
pub mime_essence: String,
pub symlink: Option<SymlinkNodeUiMetadata>,
// Extra
pub index: usize,
@ -62,10 +88,12 @@ impl NodeUiMetadata {
absolute_path: node.absolute_path.clone(),
extension: node.extension.clone(),
is_symlink: node.is_symlink,
is_broken: node.is_broken,
is_dir: node.is_dir,
is_file: node.is_file,
is_readonly: node.is_readonly,
mime_essence: node.mime_essence.clone(),
symlink: node.symlink.to_owned().map(|s| s.into()),
index,
relative_index,
is_before_focus,

Loading…
Cancel
Save