Skip to content
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ echo "# Hello\n\n\`\`\`rust\nfn main() {}\n\`\`\`" | mq-view
mq-view --theme dark README.md # force the dark palette
mq-view --theme light README.md # force the light palette
mq-view --theme auto README.md # default: guess from the COLORFGBG env var, fall back to dark
mq-view --accent blue README.md # accent color: cyan (default), blue, green, magenta, orange
mq-view --no-color README.md # disable all ANSI color output (also respects $NO_COLOR)
```

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use pager::run_pager;
pub use renderer::{
RenderConfig, render_markdown, render_markdown_to_string, render_markdown_with_config,
};
pub use theme::{Theme, ThemeMode};
pub use theme::{AccentColor, Theme, ThemeMode};

/// Runs an mq query against `content` and re-serializes the resulting nodes
/// back to Markdown source, so the result can be fed into the same parse
Expand Down
10 changes: 8 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use clap::Parser;
use miette::{IntoDiagnostic, Result};
use mq_markdown::Markdown;
use mq_view::{RenderConfig, Theme, ThemeMode, render_markdown_with_config, run_pager};
use mq_view::{
AccentColor, RenderConfig, Theme, ThemeMode, render_markdown_with_config, run_pager,
};
use std::fs;
use std::io::{self, BufWriter, Write};
use std::io::{IsTerminal, Read};
Expand Down Expand Up @@ -30,6 +32,10 @@ pub struct Args {
#[arg(long = "theme", value_enum, default_value_t = ThemeMode::Auto)]
theme: ThemeMode,

/// Accent color for the title bar, scrollbar and popups.
#[arg(long = "accent", value_enum, default_value_t = AccentColor::Cyan)]
accent: AccentColor,

/// Disable all ANSI color output
#[arg(long = "no-color")]
no_color: bool,
Expand Down Expand Up @@ -65,7 +71,7 @@ fn main() -> Result<()> {

let config = RenderConfig {
header_full_width_highlight: !args.no_header_highlight,
theme: Theme::resolve(args.theme),
theme: Theme::resolve_with_accent(args.theme, args.accent),
no_color,
line_numbers: args.line_numbers,
..RenderConfig::default()
Expand Down
6 changes: 6 additions & 0 deletions src/pager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,13 @@ fn draw_scrollbar(
theme: &Theme,
) {
let mut state = ScrollbarState::new(total).position(position);
let (track, thumb) = match orientation {
ScrollbarOrientation::VerticalRight | ScrollbarOrientation::VerticalLeft => ("│", "┃"),
_ => ("─", "━"),
};
let scrollbar = Scrollbar::new(orientation)
.track_symbol(Some(track))
.thumb_symbol(thumb)
.begin_symbol(None)
.end_symbol(None)
.track_style(Style::default().fg(to_ratatui(theme.ui_muted)))
Expand Down
61 changes: 44 additions & 17 deletions src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@ pub enum ThemeMode {
Light,
}

/// Accent color for the title bar, scrollbar and popups. Each variant has a
/// dark-background and a light-background shade.
#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum, Default)]
pub enum AccentColor {
#[default]
Cyan,
Blue,
Green,
Magenta,
Orange,
}

impl AccentColor {
fn color(self, light: bool) -> Color {
let (r, g, b) = match (self, light) {
(Self::Cyan, false) => (0, 139, 153),
(Self::Cyan, true) => (0, 115, 130),
(Self::Blue, false) => (0, 0, 238),
(Self::Blue, true) => (0, 90, 200),
(Self::Green, false) => (30, 140, 70),
(Self::Green, true) => (20, 110, 50),
(Self::Magenta, false) => (170, 50, 170),
(Self::Magenta, true) => (140, 30, 140),
(Self::Orange, false) => (200, 100, 0),
(Self::Orange, true) => (170, 80, 0),
};
Color::TrueColor { r, g, b }
}
}

/// Indexed the same way as `SyntaxHighlighter`'s tree-sitter highlight
/// capture list (attribute, constant, function.builtin, ...).
pub type SyntaxPalette = [(u8, u8, u8); 26];
Expand Down Expand Up @@ -222,7 +252,7 @@ impl Theme {
g: 140,
b: 0,
},
ui_accent: Color::TrueColor { r: 0, g: 0, b: 238 },
ui_accent: AccentColor::Cyan.color(false),
ui_muted: Color::TrueColor {
r: 128,
g: 128,
Expand Down Expand Up @@ -350,11 +380,7 @@ impl Theme {
g: 90,
b: 0,
},
ui_accent: Color::TrueColor {
r: 0,
g: 90,
b: 200,
},
ui_accent: AccentColor::Cyan.color(true),
ui_muted: Color::TrueColor {
r: 110,
g: 110,
Expand All @@ -367,17 +393,18 @@ impl Theme {
/// Terminals that don't set `COLORFGBG` (iTerm2, Kitty, Alacritty, ...)
/// fall back to `Dark` under `Auto`.
pub fn resolve(mode: ThemeMode) -> Self {
match mode {
ThemeMode::Dark => Self::dark(),
ThemeMode::Light => Self::light(),
ThemeMode::Auto => {
if is_light_background() {
Self::light()
} else {
Self::dark()
}
}
}
Self::resolve_with_accent(mode, AccentColor::default())
}

pub fn resolve_with_accent(mode: ThemeMode, accent: AccentColor) -> Self {
let light = match mode {
ThemeMode::Dark => false,
ThemeMode::Light => true,
ThemeMode::Auto => is_light_background(),
};
let mut theme = if light { Self::light() } else { Self::dark() };
theme.ui_accent = accent.color(light);
theme
}
}

Expand Down
Loading