Skip to content

Commit

Permalink
feat: line mode (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi authored Oct 20, 2023
1 parent 51ab86b commit ddb5490
Show file tree
Hide file tree
Showing 19 changed files with 174 additions and 108 deletions.
1 change: 1 addition & 0 deletions app/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ impl Executor {
exec.named.contains_key("confirm"),
),
"hidden" => cx.manager.active_mut().hidden(exec),
"linemode" => cx.manager.active_mut().linemode(exec),
"search" => match exec.args.get(0).map(|s| s.as_str()).unwrap_or("") {
"rg" => cx.manager.active_mut().search(true),
"fd" => cx.manager.active_mut().search(false),
Expand Down
6 changes: 6 additions & 0 deletions config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ keymap = [
{ on = [ "z" ], exec = "jump zoxide", desc = "Jump to a directory using zoxide" },
{ on = [ "Z" ], exec = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },

# Linemode
{ on = [ "m", "s" ], exec = "linemode size", desc = "Set linemode to size" },
{ on = [ "m", "p" ], exec = "linemode permissions", desc = "Set linemode to permissions" },
{ on = [ "m", "m" ], exec = "linemode mtime", desc = "Set linemode to mtime" },
{ on = [ "m", "n" ], exec = "linemode none", desc = "Set linemode to none" },

# Copy
{ on = [ "c", "c" ], exec = "copy path", desc = "Copy the absolute path" },
{ on = [ "c", "d" ], exec = "copy dirname", desc = "Copy the path of the parent directory" },
Expand Down
26 changes: 0 additions & 26 deletions config/src/manager/linemode.rs

This file was deleted.

15 changes: 10 additions & 5 deletions config/src/manager/manager.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use serde::{Deserialize, Serialize};
use validator::Validate;

use super::{Linemode, ManagerLayout, SortBy};
use crate::MERGED_YAZI;
use super::{ManagerLayout, SortBy};
use crate::{validation::check_validation, MERGED_YAZI};

#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct Manager {
pub layout: ManagerLayout,

Expand All @@ -14,7 +15,8 @@ pub struct Manager {
pub sort_dir_first: bool,

// Display
pub linemode: Linemode,
#[validate(length(min = 1, max = 20, message = "must be between 1 and 20 characters"))]
pub linemode: String,
pub show_hidden: bool,
pub show_symlink: bool,
}
Expand All @@ -26,6 +28,9 @@ impl Default for Manager {
manager: Manager,
}

toml::from_str::<Outer>(&MERGED_YAZI).unwrap().manager
let manager = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().manager;

check_validation(manager.validate());
manager
}
}
2 changes: 0 additions & 2 deletions config/src/manager/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
mod layout;
mod linemode;
mod manager;
mod sorting;

pub use layout::*;
pub use linemode::*;
pub use manager::*;
pub use sorting::*;
14 changes: 14 additions & 0 deletions config/src/manager/sorting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,17 @@ impl TryFrom<String> for SortBy {

fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
}

impl ToString for SortBy {
fn to_string(&self) -> String {
match self {
Self::None => "none",
Self::Alphabetical => "alphabetical",
Self::Created => "created",
Self::Modified => "modified",
Self::Natural => "natural",
Self::Size => "size",
}
.to_string()
}
}
4 changes: 1 addition & 3 deletions core/src/files/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use tokio::fs;
pub struct File {
pub url: Url,
pub meta: Metadata,
pub length: u64,
pub(super) link_to: Option<Url>,
pub is_link: bool,
pub is_hidden: bool,
Expand All @@ -30,9 +29,8 @@ impl File {
link_to = fs::read_link(&url).await.map(Url::from).ok();
}

let length = meta.len();
let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false);
Self { url, meta, length, link_to, is_link, is_hidden }
Self { url, meta, link_to, is_link, is_hidden }
}

#[inline]
Expand Down
8 changes: 2 additions & 6 deletions core/src/files/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ pub struct Files {
ticket: u64,
pub(crate) version: u64,

sizes: BTreeMap<Url, u64>,
selected: BTreeSet<Url>,
pub sizes: BTreeMap<Url, u64>,
selected: BTreeSet<Url>,

sorter: FilesSorter,
show_hidden: bool,
Expand Down Expand Up @@ -268,10 +268,6 @@ impl Files {
#[inline]
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| &f.url == url) }

// --- Sizes
#[inline]
pub fn size(&self, url: &Url) -> Option<u64> { self.sizes.get(url).copied() }

// --- Selected
pub fn selected(&self, pending: &BTreeSet<usize>, unset: bool) -> Vec<&File> {
if self.selected.is_empty() && (unset || pending.is_empty()) {
Expand Down
3 changes: 1 addition & 2 deletions core/src/files/sorter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl FilesSorter {
SortBy::Size => items.sort_unstable_by(|a, b| {
let aa = if a.is_dir() { sizes.get(&a.url).copied() } else { None };
let bb = if b.is_dir() { sizes.get(&b.url).copied() } else { None };
self.cmp(aa.unwrap_or(a.length), bb.unwrap_or(b.length), self.promote(a, b))
self.cmp(aa.unwrap_or(a.meta.len()), bb.unwrap_or(b.meta.len()), self.promote(a, b))
}),
}
true
Expand All @@ -75,7 +75,6 @@ impl FilesSorter {
let dummy = File {
url: Default::default(),
meta: items[0].meta.clone(),
length: 0,
link_to: None,
is_link: false,
is_hidden: false,
Expand Down
2 changes: 1 addition & 1 deletion core/src/manager/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Tabs {
}

let mut tab = Tab::from(url);
tab.conf = self.active().conf;
tab.conf = self.active().conf.clone();
tab.apply_files_attrs(false);

self.items.insert(self.idx + 1, tab);
Expand Down
16 changes: 16 additions & 0 deletions core/src/tab/commands/linemode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use config::keymap::Exec;

use crate::tab::Tab;

impl Tab {
pub fn linemode(&mut self, e: &Exec) -> bool {
self.conf.patch(|c| {
let Some(mode) = e.args.get(0) else {
return;
};
if !mode.is_empty() && mode.len() <= 20 {
c.linemode = mode.to_owned();
}
})
}
}
1 change: 1 addition & 0 deletions core/src/tab/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod find;
mod hidden;
mod jump;
mod leave;
mod linemode;
mod search;
mod select;
mod shell;
Expand Down
10 changes: 5 additions & 5 deletions core/src/tab/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use config::{manager::{Linemode, SortBy}, MANAGER};
use config::{manager::SortBy, MANAGER};

use crate::files::FilesSorter;

#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, PartialEq)]
pub struct Config {
// Sorting
pub sort_by: SortBy,
Expand All @@ -11,7 +11,7 @@ pub struct Config {
pub sort_dir_first: bool,

// Display
pub linemode: Linemode,
pub linemode: String,
pub show_hidden: bool,
}

Expand All @@ -25,15 +25,15 @@ impl Default for Config {
sort_dir_first: MANAGER.sort_dir_first,

// Display
linemode: MANAGER.linemode,
linemode: MANAGER.linemode.to_owned(),
show_hidden: MANAGER.show_hidden,
}
}
}

impl Config {
pub(super) fn patch<F: FnOnce(&mut Self)>(&mut self, f: F) -> bool {
let old = *self;
let old = self.clone();
f(self);
*self != old
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/tasks/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl Tasks {

let targets: Vec<_> = targets
.iter()
.filter(|f| f.is_dir() && targets.size(&f.url).is_none())
.filter(|f| f.is_dir() && !targets.sizes.contains_key(&f.url))
.map(|f| &f.url)
.collect();

Expand Down
81 changes: 51 additions & 30 deletions plugin/preset/components/folder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,56 @@ function Folder:by_kind(kind)
end
end

function Folder:highlighted_name(file)
-- Complete prefix when searching across directories
local prefix = file:prefix() or ""
if prefix ~= "" then
prefix = prefix .. "/"
end

-- Range highlighting for filenames
local highlights = file:highlights()
local spans = ui.highlight_ranges(prefix .. file.name, highlights)

-- Show symlink target
if MANAGER.show_symlink and file.link_to ~= nil then
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
end

if highlights == nil or not file:is_hovered() then
return spans
end

local found = file:found()
if found ~= nil then
spans[#spans + 1] = ui.Span(" ")
spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position)
end
return spans
end

function Folder:linemode(area)
local mode = cx.active.conf.linemode
if mode == "none" then
return {}
end

local lines = {}
for _, f in ipairs(self:by_kind(self.CURRENT).window) do
local spans = { ui.Span(" ") }
if mode == "size" then
local size = f:size()
spans[#spans + 1] = ui.Span(size and utils.readable_size(size) or "")
elseif mode == "mtime" then
spans[#spans + 1] = ui.Span(os.date("%y-%m-%d %H:%M", f.modified))
elseif mode == "permissions" then
spans[#spans + 1] = ui.Span(f:permissions() or "")
end
lines[#lines + 1] = ui.Line(spans)
end
return ui.Paragraph(area:padding(ui.Padding.right(1)), lines):align(ui.Alignment.RIGHT)
end

function Folder:markers(area, markers)
if #markers == 0 then
return {}
Expand Down Expand Up @@ -55,34 +105,6 @@ function Folder:markers(area, markers)
return elements
end

function Folder:highlighted_name(file)
-- Complete prefix when searching across directories
local prefix = file:prefix() or ""
if prefix ~= "" then
prefix = prefix .. "/"
end

-- Range highlighting for filenames
local highlights = file:highlights()
local spans = ui.highlight_ranges(prefix .. file.name, highlights)

-- Show symlink target
if MANAGER.show_symlink and file.link_to ~= nil then
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
end

if highlights == nil or not file:is_hovered() then
return spans
end

local found = file:found()
if found ~= nil then
spans[#spans + 1] = ui.Span(" ")
spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position)
end
return spans
end

function Folder:parent(area)
local folder = self:by_kind(self.PARENT)
if folder == nil then
Expand Down Expand Up @@ -127,8 +149,7 @@ function Folder:current(area)
markers[#markers + 1] = { i, 3 }
end
end

return { ui.List(area, items), table.unpack(self:markers(area, markers)) }
return utils.flat { ui.List(area, items), self:linemode(area), table.unpack(self:markers(area, markers)) }
end

function Folder:preview(area)
Expand Down
Loading

0 comments on commit ddb5490

Please sign in to comment.