mirror of https://github.com/Aloxaf/silicon
parent
1e3089447c
commit
2c35f82758
|
@ -1285,6 +1285,12 @@ dependencies = [
|
|||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
|
||||
|
||||
[[package]]
|
||||
name = "silicon"
|
||||
version = "0.4.0"
|
||||
|
@ -1298,9 +1304,11 @@ dependencies = [
|
|||
"font-kit",
|
||||
"image",
|
||||
"imageproc",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"pasteboard",
|
||||
"pathfinder_geometry",
|
||||
"shell-words",
|
||||
"structopt 0.3.20",
|
||||
"syntect",
|
||||
"tempfile",
|
||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -9,14 +9,6 @@ repository = "https://github.com/Aloxaf/silicon"
|
|||
license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "silicon"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "silicon"
|
||||
path = "src/bin.rs"
|
||||
|
||||
[dependencies]
|
||||
dirs = "3.0"
|
||||
imageproc = "0.22.0"
|
||||
|
@ -26,6 +18,8 @@ tempfile = "3.1.0"
|
|||
conv = "0.3.3"
|
||||
pathfinder_geometry = "0.5.1"
|
||||
log = "0.4.11"
|
||||
lazy_static = "1.4.0"
|
||||
shell-words = { version = "1.0.0", optional = true }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
pasteboard = "0.1.1"
|
||||
|
@ -61,5 +55,7 @@ features = ["termcolor", "atty", "humantime"]
|
|||
optional = true
|
||||
|
||||
[features]
|
||||
# fearures required for silicon as a application
|
||||
# disable it when using as a library
|
||||
default = ["bin"]
|
||||
bin = ["structopt", "env_logger", "anyhow"]
|
||||
bin = ["structopt", "env_logger", "anyhow", "shell-words"]
|
||||
|
|
13
README.md
13
README.md
|
@ -124,6 +124,19 @@ Silicon reads syntax-definition and theme cache from bat's cache directory.
|
|||
|
||||
You can find the steps to add new syntaxes / themes for bat here: [sharkdp/bat#adding-new-syntaxes--language-definitions](https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions).
|
||||
|
||||
## Configuration file
|
||||
|
||||
You can write some common args to `silicon --config-file`.
|
||||
|
||||
Example:
|
||||
```shell
|
||||
# enable shadow
|
||||
--shadow-color '#555'
|
||||
--background '#fff'
|
||||
--shadow-blur-radius 30
|
||||
--no-window-controls
|
||||
```
|
||||
|
||||
# Related projects
|
||||
|
||||
- [vim-silicon](https://github.com/segeljakt/vim-silicon)
|
||||
|
|
|
@ -1,16 +1,43 @@
|
|||
use crate::formatter::{ImageFormatter, ImageFormatterBuilder};
|
||||
use crate::utils::{Background, ShadowAdder, ToRgba};
|
||||
use anyhow::{Context, Error};
|
||||
use clipboard::{ClipboardContext, ClipboardProvider};
|
||||
use image::Rgba;
|
||||
use silicon::directories::PROJECT_DIRS;
|
||||
use silicon::formatter::{ImageFormatter, ImageFormatterBuilder};
|
||||
use silicon::utils::{Background, ShadowAdder, ToRgba};
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, Read};
|
||||
use std::num::ParseIntError;
|
||||
use std::path::PathBuf;
|
||||
use structopt::clap::AppSettings::ColoredHelp;
|
||||
use structopt::StructOpt;
|
||||
use syntect::highlighting::{Theme, ThemeSet};
|
||||
use syntect::parsing::{SyntaxReference, SyntaxSet};
|
||||
|
||||
pub fn config_file() -> PathBuf {
|
||||
std::env::var("SILICON_CONFIG_PATH")
|
||||
.ok()
|
||||
.map(PathBuf::from)
|
||||
.filter(|config_path| config_path.is_file())
|
||||
.unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
|
||||
}
|
||||
|
||||
pub fn get_args_from_config_file() -> Vec<OsString> {
|
||||
let args = std::fs::read_to_string(config_file())
|
||||
.ok()
|
||||
.and_then(|content| {
|
||||
content
|
||||
.split('\n')
|
||||
.map(|line| line.trim())
|
||||
.filter(|line| !line.starts_with('#') && !line.is_empty())
|
||||
.map(|line| shell_words::split(line))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.ok()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
args.iter().flatten().map(OsString::from).collect()
|
||||
}
|
||||
|
||||
fn parse_str_color(s: &str) -> Result<Rgba<u8>, Error> {
|
||||
Ok(s.to_rgba()
|
||||
.map_err(|_| format_err!("Invalid color: `{}`", s))?)
|
||||
|
@ -54,6 +81,7 @@ type Lines = Vec<u32>;
|
|||
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(name = "silicon")]
|
||||
#[structopt(global_setting(ColoredHelp))]
|
||||
pub struct Config {
|
||||
/// Background image
|
||||
#[structopt(long, value_name = "IMAGE", conflicts_with = "background")]
|
||||
|
@ -69,6 +97,10 @@ pub struct Config {
|
|||
)]
|
||||
pub background: Rgba<u8>,
|
||||
|
||||
/// Show the path of silicon config file
|
||||
#[structopt(long)]
|
||||
pub config_file: bool,
|
||||
|
||||
/// Read input from clipboard.
|
||||
#[structopt(long)]
|
||||
pub from_clipboard: bool,
|
||||
|
@ -110,7 +142,7 @@ pub struct Config {
|
|||
short,
|
||||
long,
|
||||
value_name = "PATH",
|
||||
required_unless_one = &["list-fonts", "list-themes", "to-clipboard"]
|
||||
required_unless_one = &["config-file", "list-fonts", "list-themes", "to-clipboard"]
|
||||
)]
|
||||
pub output: Option<PathBuf>,
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::utils::*;
|
||||
use anyhow::Error;
|
||||
use image::DynamicImage;
|
||||
use structopt::StructOpt;
|
||||
|
@ -20,12 +16,10 @@ use {image::ImageOutputFormat, pasteboard::Pasteboard};
|
|||
#[cfg(target_os = "linux")]
|
||||
use {image::ImageOutputFormat, std::process::Command};
|
||||
|
||||
pub mod blur;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod font;
|
||||
pub mod formatter;
|
||||
pub mod utils;
|
||||
mod config;
|
||||
use config::Config;
|
||||
use silicon::utils::init_syntect;
|
||||
use crate::config::{get_args_from_config_file, config_file};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn dump_image_to_clipboard(image: &DynamicImage) -> Result<(), Error> {
|
||||
|
@ -81,7 +75,11 @@ pub fn dump_image_to_clipboard(_image: &DynamicImage) -> Result<(), Error> {
|
|||
}
|
||||
|
||||
fn run() -> Result<(), Error> {
|
||||
let config: Config = Config::from_args();
|
||||
let mut args = get_args_from_config_file();
|
||||
let mut args_cli = std::env::args_os();
|
||||
args.insert(0, args_cli.next().unwrap());
|
||||
args.extend(args_cli);
|
||||
let config: Config = Config::from_iter(args);
|
||||
|
||||
let (ps, ts) = init_syntect();
|
||||
|
||||
|
@ -96,6 +94,9 @@ fn run() -> Result<(), Error> {
|
|||
println!("{}", font);
|
||||
}
|
||||
return Ok(());
|
||||
} else if config.config_file {
|
||||
println!("{}", config_file().to_string_lossy());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (syntax, code) = config.get_source_code(&ps)?;
|
|
@ -0,0 +1,63 @@
|
|||
use lazy_static::lazy_static;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct SiliconProjectDirs {
|
||||
cache_dir: PathBuf,
|
||||
config_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl SiliconProjectDirs {
|
||||
fn new() -> Option<Self> {
|
||||
let cache_dir = Self::get_cache_dir()?;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let config_dir_op = env::var_os("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs::home_dir().map(|d| d.join(".config")));
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let config_dir_op = dirs::config_dir();
|
||||
|
||||
let config_dir = config_dir_op.map(|d| d.join("silicon"))?;
|
||||
|
||||
Some(Self {
|
||||
cache_dir,
|
||||
config_dir,
|
||||
})
|
||||
}
|
||||
|
||||
// silicon use bat's cache directory
|
||||
fn get_cache_dir() -> Option<PathBuf> {
|
||||
// on all OS prefer BAT_CACHE_PATH if set
|
||||
let cache_dir_op = env::var_os("BAT_CACHE_PATH").map(PathBuf::from);
|
||||
if cache_dir_op.is_some() {
|
||||
return cache_dir_op;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let cache_dir_op = env::var_os("XDG_CACHE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs::home_dir().map(|d| d.join(".cache")));
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let cache_dir_op = dirs::cache_dir();
|
||||
|
||||
cache_dir_op.map(|d| d.join("bat"))
|
||||
}
|
||||
|
||||
pub fn cache_dir(&self) -> &Path {
|
||||
&self.cache_dir
|
||||
}
|
||||
|
||||
pub fn config_dir(&self) -> &Path {
|
||||
&self.config_dir
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PROJECT_DIRS: SiliconProjectDirs =
|
||||
SiliconProjectDirs::new().expect("Could not get home directory");
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
extern crate log;
|
||||
|
||||
pub mod blur;
|
||||
pub mod directories;
|
||||
pub mod error;
|
||||
pub mod font;
|
||||
pub mod formatter;
|
||||
|
|
46
src/utils.rs
46
src/utils.rs
|
@ -1,49 +1,27 @@
|
|||
use crate::directories::PROJECT_DIRS;
|
||||
use crate::error::ParseColorError;
|
||||
use image::imageops::{crop, resize, FilterType};
|
||||
use image::Pixel;
|
||||
use image::{DynamicImage, GenericImage, GenericImageView, Rgba, RgbaImage};
|
||||
use imageproc::drawing::{draw_filled_rect_mut, draw_line_segment_mut};
|
||||
use imageproc::rect::Rect;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use syntect::dumps;
|
||||
use syntect::highlighting::ThemeSet;
|
||||
use syntect::parsing::SyntaxSet;
|
||||
|
||||
// Copied from https://github.com/sharkdp/bat/blob/12a1fe3ad417f7694c4490b94b793387c7a7b536/src/bin/bat/directories.rs#L35
|
||||
fn get_cache_dir() -> Option<PathBuf> {
|
||||
// on all OS prefer BAT_CACHE_PATH if set
|
||||
let cache_dir_op = env::var_os("BAT_CACHE_PATH").map(PathBuf::from);
|
||||
if cache_dir_op.is_some() {
|
||||
return cache_dir_op;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let cache_dir_op = env::var_os("XDG_CACHE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs::home_dir().map(|d| d.join(".cache")));
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let cache_dir_op = dirs::cache_dir();
|
||||
|
||||
cache_dir_op.map(|d| d.join("bat"))
|
||||
}
|
||||
|
||||
pub fn read_from_bat_cache() -> Option<(SyntaxSet, ThemeSet)> {
|
||||
get_cache_dir().and_then(|cache_dir| {
|
||||
let syntax_cache = cache_dir.join("syntaxes.bin");
|
||||
let theme_cache = cache_dir.join("themes.bin");
|
||||
if syntax_cache.exists() && theme_cache.exists() {
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
dumps::from_dump_file(syntax_cache),
|
||||
dumps::from_dump_file(theme_cache),
|
||||
) {
|
||||
return Some((a, b));
|
||||
}
|
||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
||||
let syntax_cache = cache_dir.join("syntaxes.bin");
|
||||
let theme_cache = cache_dir.join("themes.bin");
|
||||
if syntax_cache.exists() && theme_cache.exists() {
|
||||
if let (Ok(a), Ok(b)) = (
|
||||
dumps::from_dump_file(syntax_cache),
|
||||
dumps::from_dump_file(theme_cache),
|
||||
) {
|
||||
return Some((a, b));
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Load the default SyntaxSet and ThemeSet.
|
||||
|
|
Loading…
Reference in New Issue