mirror of
https://github.com/sayanarijit/xplr
synced 2024-11-10 07:10:45 +00:00
Add support for NO_COLOR
Also, add `general.logs` to the config. Ref: https://no-color.org/
This commit is contained in:
parent
af1cda5762
commit
d0342260fe
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1362,7 +1362,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xplr"
|
name = "xplr"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "xplr"
|
name = "xplr"
|
||||||
version = "0.4.3" # Update config.yml, config.rs and default.nix
|
version = "0.4.4" # Update config.yml, config.rs and default.nix
|
||||||
authors = ["Arijit Basu <sayanarijit@gmail.com>"]
|
authors = ["Arijit Basu <sayanarijit@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "A hackable, minimal, fast TUI file explorer, stealing ideas from nnn and fzf"
|
description = "A hackable, minimal, fast TUI file explorer, stealing ideas from nnn and fzf"
|
||||||
|
@ -1,54 +1,12 @@
|
|||||||
use crate::app::ExternalMsg;
|
use crate::app::ExternalMsg;
|
||||||
use crate::app::HelpMenuLine;
|
use crate::app::HelpMenuLine;
|
||||||
use crate::default_config;
|
use crate::default_config;
|
||||||
|
use crate::ui::Style;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tui::layout::Constraint as TuiConstraint;
|
use tui::layout::Constraint as TuiConstraint;
|
||||||
use tui::style::Style as TuiStyle;
|
|
||||||
use tui::style::{Color, Modifier};
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct Style {
|
|
||||||
fg: Option<Color>,
|
|
||||||
bg: Option<Color>,
|
|
||||||
add_modifier: Option<Modifier>,
|
|
||||||
sub_modifier: Option<Modifier>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Style {
|
|
||||||
pub fn extend(mut self, other: Self) -> Self {
|
|
||||||
self.fg = other.fg.or(self.fg);
|
|
||||||
self.bg = other.bg.or(self.bg);
|
|
||||||
self.add_modifier = other.add_modifier.or(self.add_modifier);
|
|
||||||
self.sub_modifier = other.sub_modifier.or(self.sub_modifier);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<TuiStyle> for Style {
|
|
||||||
fn from(s: TuiStyle) -> Self {
|
|
||||||
Self {
|
|
||||||
fg: s.fg,
|
|
||||||
bg: s.bg,
|
|
||||||
add_modifier: Some(s.add_modifier),
|
|
||||||
sub_modifier: Some(s.sub_modifier),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<TuiStyle> for Style {
|
|
||||||
fn into(self) -> TuiStyle {
|
|
||||||
TuiStyle {
|
|
||||||
fg: self.fg,
|
|
||||||
bg: self.bg,
|
|
||||||
add_modifier: self.add_modifier.unwrap_or_else(Modifier::empty),
|
|
||||||
sub_modifier: self.sub_modifier.unwrap_or_else(Modifier::empty),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
@ -252,6 +210,28 @@ impl TableConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct LogsConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub info: UiElement,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub success: UiElement,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub error: UiElement,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogsConfig {
|
||||||
|
pub fn extend(mut self, other: Self) -> Self {
|
||||||
|
self.info = other.info.extend(self.info);
|
||||||
|
self.success = other.success.extend(self.success);
|
||||||
|
self.error = other.error.extend(self.error);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct GeneralConfig {
|
pub struct GeneralConfig {
|
||||||
@ -264,6 +244,9 @@ pub struct GeneralConfig {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub prompt: UiElement,
|
pub prompt: UiElement,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub logs: LogsConfig,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub table: TableConfig,
|
pub table: TableConfig,
|
||||||
|
|
||||||
@ -282,6 +265,7 @@ impl GeneralConfig {
|
|||||||
self.show_hidden = other.show_hidden.or(self.show_hidden);
|
self.show_hidden = other.show_hidden.or(self.show_hidden);
|
||||||
self.cursor = other.cursor.extend(self.cursor);
|
self.cursor = other.cursor.extend(self.cursor);
|
||||||
self.prompt = other.prompt.extend(self.prompt);
|
self.prompt = other.prompt.extend(self.prompt);
|
||||||
|
self.logs = other.logs.extend(self.logs);
|
||||||
self.table = other.table.extend(self.table);
|
self.table = other.table.extend(self.table);
|
||||||
self.default_ui = other.default_ui.extend(self.default_ui);
|
self.default_ui = other.default_ui.extend(self.default_ui);
|
||||||
self.focus_ui = other.focus_ui.extend(self.focus_ui);
|
self.focus_ui = other.focus_ui.extend(self.focus_ui);
|
||||||
@ -559,6 +543,7 @@ impl Config {
|
|||||||
|
|
||||||
pub fn is_compatible(&self) -> Result<bool> {
|
pub fn is_compatible(&self) -> Result<bool> {
|
||||||
let result = match self.parsed_version()? {
|
let result = match self.parsed_version()? {
|
||||||
|
(0, 4, 4) => true,
|
||||||
(0, 4, 3) => true,
|
(0, 4, 3) => true,
|
||||||
(0, 4, 2) => true,
|
(0, 4, 2) => true,
|
||||||
(0, 4, 1) => true,
|
(0, 4, 1) => true,
|
||||||
@ -571,7 +556,7 @@ impl Config {
|
|||||||
|
|
||||||
pub fn upgrade_notification(&self) -> Result<Option<&str>> {
|
pub fn upgrade_notification(&self) -> Result<Option<&str>> {
|
||||||
let result = match self.parsed_version()? {
|
let result = match self.parsed_version()? {
|
||||||
(0, 4, 3) => None,
|
(0, 4, 4) => None,
|
||||||
(_, _, _) => Some("App version updated"),
|
(_, _, _) => Some("App version updated"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
version: v0.4.3
|
version: v0.4.4
|
||||||
general:
|
general:
|
||||||
show_hidden: false
|
show_hidden: false
|
||||||
prompt:
|
prompt:
|
||||||
format: "> "
|
format: "> "
|
||||||
cursor:
|
cursor:
|
||||||
format: █
|
format: █
|
||||||
|
logs:
|
||||||
|
info:
|
||||||
|
format: "INFO"
|
||||||
|
style:
|
||||||
|
fg: LightBlue
|
||||||
|
success:
|
||||||
|
format: "SUCCESS"
|
||||||
|
style:
|
||||||
|
fg: Green
|
||||||
|
error:
|
||||||
|
format: "ERROR"
|
||||||
|
style:
|
||||||
|
fg: Red
|
||||||
table:
|
table:
|
||||||
header:
|
header:
|
||||||
cols:
|
cols:
|
||||||
|
88
src/ui.rs
88
src/ui.rs
@ -2,17 +2,69 @@ use crate::app;
|
|||||||
use crate::app::HelpMenuLine;
|
use crate::app::HelpMenuLine;
|
||||||
use crate::app::{Node, SymlinkNode};
|
use crate::app::{Node, SymlinkNode};
|
||||||
use handlebars::Handlebars;
|
use handlebars::Handlebars;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
use tui::backend::Backend;
|
use tui::backend::Backend;
|
||||||
use tui::layout::Rect;
|
use tui::layout::Rect;
|
||||||
use tui::layout::{Constraint as TuiConstraint, Direction, Layout};
|
use tui::layout::{Constraint as TuiConstraint, Direction, Layout};
|
||||||
use tui::style::{Color, Style};
|
use tui::style::{Color, Modifier, Style as TuiStyle};
|
||||||
use tui::text::{Span, Spans};
|
use tui::text::{Span, Spans};
|
||||||
use tui::widgets::{Block, Borders, Cell, List, ListItem, Paragraph, Row, Table};
|
use tui::widgets::{Block, Borders, Cell, List, ListItem, Paragraph, Row, Table};
|
||||||
use tui::Frame;
|
use tui::Frame;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref NO_COLOR: bool = env::var("NO_COLOR").ok().map(|_| true).unwrap_or(false);
|
||||||
|
pub static ref DEFAULT_STYLE: TuiStyle = TuiStyle::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct Style {
|
||||||
|
pub fg: Option<Color>,
|
||||||
|
pub bg: Option<Color>,
|
||||||
|
pub add_modifier: Option<Modifier>,
|
||||||
|
pub sub_modifier: Option<Modifier>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Style {
|
||||||
|
pub fn extend(mut self, other: Self) -> Self {
|
||||||
|
self.fg = other.fg.or(self.fg);
|
||||||
|
self.bg = other.bg.or(self.bg);
|
||||||
|
self.add_modifier = other.add_modifier.or(self.add_modifier);
|
||||||
|
self.sub_modifier = other.sub_modifier.or(self.sub_modifier);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TuiStyle> for Style {
|
||||||
|
fn from(s: TuiStyle) -> Self {
|
||||||
|
Self {
|
||||||
|
fg: s.fg,
|
||||||
|
bg: s.bg,
|
||||||
|
add_modifier: Some(s.add_modifier),
|
||||||
|
sub_modifier: Some(s.sub_modifier),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<TuiStyle> for Style {
|
||||||
|
fn into(self) -> TuiStyle {
|
||||||
|
if *NO_COLOR {
|
||||||
|
*DEFAULT_STYLE
|
||||||
|
} else {
|
||||||
|
TuiStyle {
|
||||||
|
fg: self.fg,
|
||||||
|
bg: self.bg,
|
||||||
|
add_modifier: self.add_modifier.unwrap_or_else(Modifier::empty),
|
||||||
|
sub_modifier: self.sub_modifier.unwrap_or_else(Modifier::empty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SymlinkNodeUiMetadata {
|
pub struct SymlinkNodeUiMetadata {
|
||||||
@ -356,6 +408,7 @@ fn draw_input_buffer<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw_logs<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handlebars) {
|
fn draw_logs<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handlebars) {
|
||||||
|
let config = app.config().general.logs.clone();
|
||||||
let logs = app
|
let logs = app
|
||||||
.logs()
|
.logs()
|
||||||
.iter()
|
.iter()
|
||||||
@ -364,18 +417,37 @@ fn draw_logs<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handl
|
|||||||
.rev()
|
.rev()
|
||||||
.map(|l| {
|
.map(|l| {
|
||||||
let time = l.created_at.format("%r");
|
let time = l.created_at.format("%r");
|
||||||
let log = format!("{} | {}", &time, l.message);
|
|
||||||
match &l.level {
|
match &l.level {
|
||||||
app::LogLevel::Info => ListItem::new(log).style(Style::default().fg(Color::Gray)),
|
app::LogLevel::Info => ListItem::new(format!(
|
||||||
app::LogLevel::Success => {
|
"{} | {} | {}",
|
||||||
ListItem::new(log).style(Style::default().fg(Color::Green))
|
&time,
|
||||||
}
|
&config.info.format.to_owned().unwrap_or_default(),
|
||||||
app::LogLevel::Error => ListItem::new(log).style(Style::default().fg(Color::Red)),
|
&l.message
|
||||||
|
))
|
||||||
|
.style(config.info.style.into()),
|
||||||
|
app::LogLevel::Success => ListItem::new(format!(
|
||||||
|
"{} | {} | {}",
|
||||||
|
&time,
|
||||||
|
&config.success.format.to_owned().unwrap_or_default(),
|
||||||
|
&l.message
|
||||||
|
))
|
||||||
|
.style(config.success.style.into()),
|
||||||
|
app::LogLevel::Error => ListItem::new(format!(
|
||||||
|
"{} | {} | {}",
|
||||||
|
&time,
|
||||||
|
&config.error.format.to_owned().unwrap_or_default(),
|
||||||
|
&l.message
|
||||||
|
))
|
||||||
|
.style(config.error.style.into()),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<ListItem>>();
|
.collect::<Vec<ListItem>>();
|
||||||
|
|
||||||
let logs_list = List::new(logs).block(Block::default().borders(Borders::ALL).title(" Logs "));
|
let logs_list = List::new(logs).block(
|
||||||
|
Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.title(format!(" Logs ({}) ", app.logs().len())),
|
||||||
|
);
|
||||||
|
|
||||||
f.render_widget(logs_list, rect);
|
f.render_widget(logs_list, rect);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user