Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/nicohman/raven
Browse files Browse the repository at this point in the history
  • Loading branch information
nicohman committed Nov 11, 2018
2 parents a73651d + f6de759 commit 8defdcd
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 67 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ The following packages are required for their relevant options:

+ [Sublime Text 3](https://www.sublimetext.com/) : `st_tmtheme`, `st_scs` and `st_subltheme`

+ [VSCode](https://github.com/Microsoft/vscode) : `vscode`

* New option suggestions are very welcome!

You can also download a prebuilt binary from [here](https://github.com/nicohman/raven/releases)
Expand Down Expand Up @@ -119,6 +121,7 @@ To configure a theme, start off by creating it with `raven new [theme]`. You'll
+ [st_tmtheme](#sublime-text-3)
+ [st_scs](#sublime-text-3)
+ [st_subltheme](#sublime-text-3)
+ vscode (Plain text containing the name of an already installed VSCode theme.)

base_ files allow splitting the config from the cosmetics on the options with [base_]
For example if you place an i3 config named base\_i3 in ~/.config/raven, the contents of i3 for a theme will be appended to it instead of being run on their own. This allows you to have a central config for keyboard shortcuts, and have cosmetics only be stored in the theme.
Expand All @@ -135,4 +138,6 @@ With the cycle command you can control a daemon that will automatically cycle th

### Sublime Text 3

Plain text containing the absolute (allowing `$HOME` and `~`) or relative path (To the sublime config directory. Usually `~/.config/sublime-text-3/`) of a .tmTheme, .sublime-color-scheme or .sublime-theme file.
Plain text containing `sublt/<filename>.<extension>` (which you must create on your theme folder) or the name of an already installed theme (e.g `DA.sublime-theme`)

Extensions: st_tmtheme (`.tmTheme`), st_scs (`.sublime-color-scheme`) and st_subltheme (`.sublime-theme`)
5 changes: 5 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub enum Raven {
Add { option: String, name: String },
#[structopt(name = "rm", about = "Remove an option from edited theme")]
Rm { name: String },
#[structopt(name = "key", about = "Add a key-value option")]
Key {
key: String,
value: String
},
#[structopt(name = "edit", about = "Edit theme")]
Edit { name: String },
#[structopt(name = "menu", about = "Show theme menu")]
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fn interpet_args() {
Modify { name, editor } => modify_file(conf.editing, name, editor),
Delete { name } => del_theme(name),
Edit { name } => edit(name),
Key {key, value} => key_value(key, value, conf.editing),
ManageO { .. } => {
match r {
ManageO(Export { name }) => {
Expand Down
3 changes: 3 additions & 0 deletions src/ravenlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod config {
use crate::themes::*;
use dirs::home_dir;
use std::{fs, fs::OpenOptions, io::Read, io::Write};
use serde_json::value::Map;
/// Returns home directory as string
pub fn get_home() -> String {
return String::from(home_dir().unwrap().to_str().unwrap());
Expand Down Expand Up @@ -142,6 +143,7 @@ pub mod config {
options: options,
screenshot: default_screen(),
description: default_desc(),
kv: Map::new()
};
OpenOptions::new()
.create(true)
Expand Down Expand Up @@ -185,6 +187,7 @@ pub mod config {
monitor: conf.monitors,
enabled: theme_info.enabled,
order: conf.polybar,
kv: theme_info.kv
};
Ok(new_theme)
} else {
Expand Down
215 changes: 149 additions & 66 deletions src/themes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::config::*;
use proc_path;
use serde_json::value::{Map, Value};
use std::{
env, fs, fs::DirEntry, fs::OpenOptions, io, io::Read, io::Write, os::unix::fs::OpenOptionsExt,
process::Command,
Expand All @@ -14,6 +15,8 @@ pub struct ThemeStore {
pub screenshot: String,
#[serde(default = "default_desc")]
pub description: String,
#[serde(default)]
pub kv: Map<String, Value>,
}
/// Structure that holds all methods and data for individual themes.
pub struct Theme {
Expand All @@ -22,10 +25,50 @@ pub struct Theme {
pub monitor: i32,
pub enabled: Vec<String>,
pub order: Vec<String>,
pub kv: Map<String, Value>,
}

/// Methods for a loaded theme
impl Theme {
/// Loads options held within theme.json key-value storage
pub fn load_kv(&self) {
for (k, v) in &self.kv {
self.load_k(k.as_str(), v.as_str().unwrap());
}
}
/// Loads a single key option
pub fn load_k<N>(&self, k: N, v: N)
where
N: Into<String>,
{
let (k, v) = (k.into(), v.into());
match k.as_str() {
"st_tmtheme" => self.load_sublt("st_tmtheme", v.as_str()),
"st_scs" => self.load_sublt("st_scs", v.as_str()),
"st_subltheme" => self.load_sublt("st_subltheme", v.as_str()),
"vscode" => self.load_vscode(v.as_str()),
_ => println!("Unrecognized key {}", k),
}
println!("Loaded key option {}", k);
}
/// Converts old single-string file options into key-value storage
pub fn convert_single<N>(&self, name: N)
where
N: Into<String>,
{
let key = name.into();
let mut value = String::new();
fs::File::open(get_home() + "/.config/raven/themes/" + &self.name + "/" + &key)
.expect("Couldn't open file")
.read_to_string(&mut value)
.unwrap();
let mut store = load_store(self.name.clone());
store.kv.insert(key.clone(),serde_json::Value::String(value.clone().trim().to_string()));
store.options = store.options.iter().filter(|x| x.as_str() != key.as_str()).map(|x|x.to_owned()).collect();
up_theme(store);
println!("Converted option {} to new key-value system", key);
self.load_k(key, value);
}
/// Iterates through options and loads them with submethods
pub fn load_all(&self) {
let opt = &self.options;
Expand All @@ -50,9 +93,10 @@ impl Theme {
"lemonbar" => self.load_lemon(),
"openbox" => self.load_openbox(),
"dunst" => self.load_dunst(),
"st_tmtheme" => self.load_sublt("st_tmtheme"),
"st_scs" => self.load_sublt("st_scs"),
"st_subltheme" => self.load_sublt("st_subltheme"),
"st_tmtheme" => self.convert_single("st_tmtheme"),
"st_scs" => self.convert_single("st_scs"),
"st_subltheme" => self.convert_single("st_subltheme"),
"vscode" => self.convert_single("vscode"),
"|" => {}
_ => println!("Unknown option"),
};
Expand All @@ -61,8 +105,61 @@ impl Theme {
}
i += 1;
}
self.load_kv();
println!("Loaded all options for theme {}", self.name);
}
/// Edits the value of a key in hjson files
fn edit_hjson<N, S, T>(&self, file: N, pat: S, value: T)
where
N: Into<String>,
S: Into<String>,
T: Into<String>,
{
let file = &file.into();
let pat = &pat.into();
let value = &value.into();
let mut finals = String::new();
if fs::metadata(file).is_ok() {
let mut pre = String::new();
fs::File::open(file)
.expect("Couldn't open hjson file")
.read_to_string(&mut pre)
.unwrap();
let mut patfound = false;
for line in pre.lines() {
if line.contains(pat) {
patfound = true;
if line.ends_with(",") {
finals = finals + "\n" + " " + pat + "\"" + &value + "\","
} else {
finals = finals + "\n" + " " + pat + "\"" + &value + "\""
}
} else if line.ends_with("}") && !patfound {
finals =
finals + "," + "\n" + " " + pat + "\"" + &value + "\"" + "\n" + line;
} else {
finals = finals + "\n" + line;
}
}
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(file)
.expect("Couldn't open hjson file")
.write_all(finals.trim().as_bytes())
.unwrap();
} else {
finals = finals + "{\n " + pat + "\"" + &value + "\"\n}";
OpenOptions::new()
.create(true)
.write(true)
.open(file)
.expect("Couldn't open hjson file")
.write_all(finals.as_bytes())
.unwrap();
}
}
pub fn load_rofi(&self) {
if fs::metadata(get_home() + "/.config/rofi").is_err() {
fs::create_dir(get_home() + "/.config/rofi").unwrap();
Expand Down Expand Up @@ -149,83 +246,60 @@ impl Theme {
.unwrap();
Command::new("dunst").spawn().expect("Failed to run dunst");
}

pub fn load_sublt<N>(&self, stype: N)
pub fn load_vscode<N>(&self, value: N)
where
N: Into<String>,
{
let path1 = get_home() + "/.config/Code/User";
let path2 = get_home() + "/.config/Code - OSS/User";
if fs::metadata(&path1).is_err() && fs::metadata(&path2).is_err() {
println!(
"Couldn't find neither .config/Code nor .config/Code - OSS. Do you have VSCode installed? \
Skipping."
);
return;
}
let pattern = "\"workbench.colorTheme\": ";
let value = value.into();
if fs::metadata(&path1).is_ok() {
self.edit_hjson(path1 + "/settings.json", pattern, value.as_str())
}
if fs::metadata(&path2).is_ok() {
self.edit_hjson(path2 + "/settings.json", pattern, value)
}
}
pub fn load_sublt<N>(&self, stype: N, value: N)
where
N: Into<String>,
{
let stype = &stype.into();
let sublpath = "/.config/sublime-text-3/Packages/User";
if fs::metadata(get_home() + &sublpath).is_err() {
let path = get_home() + "/.config/sublime-text-3/Packages/User";
if fs::metadata(&path).is_err() {
println!(
"Couldn't find {}. Do you have sublime text 3 installed? \
Skipping.",
get_home() + &sublpath
&path
);
return;
}

let mut value = String::new();
fs::File::open(get_home() + "/.config/raven/themes/" + &self.name + "/" + &stype)
.unwrap()
.read_to_string(&mut value)
.unwrap();
let mut pat = "";
let mut value = value.into();
if value.starts_with("sublt/") {
value = value.trim_start_matches("sublt/").to_string();
fs::copy(
get_home() + "/.config/raven/themes/" + &self.name + "/sublt/" + &value,
path.clone() + "/" + &value
)
.expect("Couldn't overwrite sublt theme");
}

let mut pattern = "";
if stype == "st_tmtheme" || stype == "st_scs" {
pat = "\"color_scheme\": ";
pattern = "\"color_scheme\": ";
} else if stype == "st_subltheme" {
pat = "\"theme\": ";
}
if fs::metadata(get_home() + sublpath + "/Preferences.sublime-settings").is_ok() {
let mut pre = String::new();
fs::File::open(get_home() + sublpath + "/Preferences.sublime-settings")
.expect("Couldn't open sublime settings")
.read_to_string(&mut pre)
.unwrap();
let mut finals = String::new();
let mut patfound = false;
for line in pre.lines() {
if line.contains(pat) {
patfound = true;
if line.ends_with(",") {
finals = finals + "\n" + " " + pat + "\"" + &value + "\","
} else {
finals = finals + "\n" + " " + pat + "\"" + &value + "\""
}
} else if line.ends_with("}") && !patfound {
finals =
finals + "," + "\n" + " " + pat + "\"" + &value + "\"" + "\n" + line;
} else {
finals = finals + "\n" + line;
}
}
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(get_home() + sublpath + "/Preferences.sublime-settings")
.expect("Couldn't open sublime settings")
.write_all(finals.trim().as_bytes())
.unwrap();
} else {
let mut finals = String::new();
finals = finals
+ "// Settings in here override those in \
\"Default/Preferences.sublime-settings\",\n\
// and are overridden in turn by syntax-specific settings.\n\
{\n "
+ pat
+ "\""
+ &value
+ "\"\n}";
OpenOptions::new()
.create(true)
.write(true)
.open(get_home() + sublpath + "/Preferences.sublime-settings")
.expect("Couldn't open sublime settings")
.write_all(finals.as_bytes())
.unwrap();
pattern = "\"theme\": ";
}
self.edit_hjson(path + "/Preferences.sublime-settings", pattern, value)
}

pub fn load_ncm(&self) {
Expand Down Expand Up @@ -433,6 +507,7 @@ where
enabled: vec![],
screenshot: default_screen(),
description: default_desc(),
kv: Map::new(),
};
let st = serde_json::to_string(&stdef).unwrap();
file.write_all(st.as_bytes()).unwrap();
Expand All @@ -455,6 +530,7 @@ where
enabled: cur_theme.enabled,
screenshot: cur_st.screenshot,
description: cur_st.description,
kv: Map::new(),
};
let mut already_used = false;
for opt in &new_themes.options {
Expand Down Expand Up @@ -488,6 +564,7 @@ where
enabled: cur_theme.enabled,
screenshot: cur_st.screenshot,
description: cur_st.description,
kv: Map::new(),
};
let mut found = false;
let mut i = 0;
Expand Down Expand Up @@ -522,3 +599,9 @@ pub fn get_themes() -> Vec<String> {
.map(|x| proc_path(x.unwrap()))
.collect::<Vec<String>>()
}
/// Changes a key-value option
pub fn key_value<N, S, T>(key: N, value: S, theme: T) where N : Into<String>, S: Into<String>, T: Into<String> {
let mut store = load_store(theme.into());
store.kv.insert(key.into(), serde_json::Value::String(value.into()));
up_theme(store);
}

0 comments on commit 8defdcd

Please sign in to comment.