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

feat: line mode #291

Merged
merged 4 commits into from
Oct 20, 2023
Merged
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
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