Compare commits
13 commits
c99ef1a7b0
...
5b20a34c7d
Author | SHA1 | Date | |
---|---|---|---|
5b20a34c7d | |||
adf2bc762d | |||
17a05cf2c5 | |||
a270d08c47 | |||
|
c533630ff8 | ||
be34b2bc1e | |||
43397e0640 | |||
|
206dc672ec | ||
e1bbcf3c3f | |||
9456983536 | |||
357fac445f | |||
cb5fb6b1ac | |||
85b463b9b8 |
4 changed files with 87 additions and 22 deletions
|
@ -1,10 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "0.3.0"
|
version = "0.6.0"
|
||||||
authors = ["Valerie Wolfe <sleeplessval@gmail.com>"]
|
authors = ["Valerie Wolfe <sleeplessval@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
configparser = "2.0.1"
|
configparser = "3.0.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = "debuginfo"
|
||||||
|
|
||||||
|
|
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# open
|
||||||
|
|
||||||
|
A Rust reimplementation of `xdg-open` command. It's written to be quickly and easily customizable, features separate local and global configs, and a zero-operand command allowing the user to specify how files should be opened differently, and for opening a project, etc.
|
||||||
|
|
||||||
|
For example, for
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[open]
|
||||||
|
# zero-operand command
|
||||||
|
command = atom .
|
||||||
|
# use $EDITOR to edit files without specified commands?
|
||||||
|
use_editor = true
|
||||||
|
|
||||||
|
[.md]
|
||||||
|
command = typora
|
||||||
|
|
||||||
|
[.rs]
|
||||||
|
command = atom
|
||||||
|
|
||||||
|
[filename:.gitignore]
|
||||||
|
command = vim
|
||||||
|
shell = true
|
||||||
|
```
|
||||||
|
|
||||||
|
I can use `open` to open the directory in Atom, or I could use `open src/main.rs` to open `main.rs` in Atom, and I can specify these on a per-project basis.
|
||||||
|
|
||||||
|
For directories with a local config, any missing values will be filled in by the global config (`~/.config/open.conf`), which means local configs can be shorter.
|
|
@ -9,8 +9,8 @@ use configparser::ini::Ini;
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub local: Option<Ini>,
|
pub local: Option<Ini>,
|
||||||
pub global: Option<Ini>,
|
pub global: Option<Ini>,
|
||||||
local_path: Option<String>,
|
pub local_path: Option<String>,
|
||||||
global_path: Option<String>
|
pub global_path: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -86,13 +86,15 @@ impl Config {
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
pub fn getbool(&self, section: &str, key: &str) -> Result<Option<bool>, String> {
|
pub fn getbool(&self, section: &str, key: &str) -> Option<bool> {
|
||||||
let mut output = Ok(None);
|
let mut output = None;
|
||||||
if self.local.is_some() {
|
if self.local.is_some() {
|
||||||
output = self.local.as_ref().unwrap().getbool(section, key);
|
let i_out = self.local.as_ref().unwrap().getbool(section, key);
|
||||||
|
output = i_out.unwrap_or(None);
|
||||||
}
|
}
|
||||||
if output.clone().ok().is_none() && self.global.is_some() {
|
if output.is_none() && self.global.is_some() {
|
||||||
output = self.global.as_ref().unwrap().getbool(section, key);
|
let i_out = self.global.as_ref().unwrap().getbool(section, key);
|
||||||
|
output = i_out.unwrap_or(None);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +107,7 @@ impl Config {
|
||||||
ini = self.global.clone().unwrap();
|
ini = self.global.clone().unwrap();
|
||||||
}
|
}
|
||||||
ini.set(section, key, Some(value));
|
ini.set(section, key, Some(value));
|
||||||
if local{
|
if local {
|
||||||
self.local = Some(ini);
|
self.local = Some(ini);
|
||||||
} else {
|
} else {
|
||||||
self.global = Some(ini);
|
self.global = Some(ini);
|
||||||
|
|
56
src/main.rs
56
src/main.rs
|
@ -1,5 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
env::{args, current_dir},
|
env::{args, current_dir, var},
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{Command, exit, Stdio}
|
process::{Command, exit, Stdio}
|
||||||
};
|
};
|
||||||
|
@ -22,16 +22,18 @@ fn main() {
|
||||||
match arg.as_str() {
|
match arg.as_str() {
|
||||||
"-h" |
|
"-h" |
|
||||||
"--help" => {
|
"--help" => {
|
||||||
println!("open
|
println!("open v0.6.0
|
||||||
Valerie Wolfe <sleeplessval@gmail.com>
|
Valerie Wolfe <sleeplessval@gmail.com>
|
||||||
A Linux implementation of the \"open\" command on Mac OS written in Rust and easily configurable.
|
A Rust reimplementation of \"xdg-open\" configurable with an ini file.
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
open [FLAGS] [OPERAND]
|
open [FLAGS] [OPERAND]
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-h, --help Prints this help text
|
-h, --help Prints this help text
|
||||||
-a, --add Add a handler for a operand type
|
-a, --add Add a handler for a operand type
|
||||||
|
-p, --path Prints the config path used
|
||||||
|
-v, --version Prints the version number
|
||||||
");
|
");
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
@ -52,7 +54,17 @@ FLAGS:
|
||||||
}
|
}
|
||||||
config.write().ok();
|
config.write().ok();
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
|
"-p" |
|
||||||
|
"--path" => {
|
||||||
|
let local = config.local_path;
|
||||||
|
if local.is_some() {
|
||||||
|
println!("{}", local.unwrap());
|
||||||
|
} else {
|
||||||
|
println!("{}", config.global_path.unwrap());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
if file_operand {
|
if file_operand {
|
||||||
error = Some("open: too many file operands.".to_string());
|
error = Some("open: too many file operands.".to_string());
|
||||||
|
@ -93,12 +105,32 @@ FLAGS:
|
||||||
}
|
}
|
||||||
let i_exe = config.get(ext, "command");
|
let i_exe = config.get(ext, "command");
|
||||||
if i_exe.is_none() {
|
if i_exe.is_none() {
|
||||||
match ext {
|
let use_editor = config.getbool("open", "use_editor");
|
||||||
"open" => println!("open: no zero-operand command specified."),
|
if use_editor.unwrap_or(false) {
|
||||||
"dir" => println!("open: no command specified for directories."),
|
let i_editor = var("EDITOR");
|
||||||
_ => println!("open: no command specified for \"{}\" files.", ext)
|
if i_editor.is_err() {
|
||||||
|
println!("open: encountered an error trying to access $EDITOR");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let editor = i_editor.ok().unwrap();
|
||||||
|
if editor.is_empty() {
|
||||||
|
println!("open: $EDITOR is not defined.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut command = Command::new(editor);
|
||||||
|
command.args(vec![i_target]);
|
||||||
|
command.stdout(Stdio::inherit())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.stdin(Stdio::inherit());
|
||||||
|
command.output().ok();
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
match ext {
|
||||||
|
"dir" => println!("open: no command specified for directories."),
|
||||||
|
_ => println!("open: no command specified for \"{}\" files.", ext)
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
let exe = i_exe.unwrap();
|
let exe = i_exe.unwrap();
|
||||||
let mut parts = exe.split(" ");
|
let mut parts = exe.split(" ");
|
||||||
|
@ -111,7 +143,7 @@ FLAGS:
|
||||||
command.args(param)
|
command.args(param)
|
||||||
.current_dir(dir);
|
.current_dir(dir);
|
||||||
|
|
||||||
let is_sh = config.getbool(ext, "shell").ok().unwrap_or(Some(false)).unwrap_or(false);
|
let is_sh = config.getbool(ext, "shell").unwrap_or(false);
|
||||||
if is_sh {
|
if is_sh {
|
||||||
command.stdout(Stdio::inherit())
|
command.stdout(Stdio::inherit())
|
||||||
.stderr(Stdio::inherit())
|
.stderr(Stdio::inherit())
|
||||||
|
|
Loading…
Reference in a new issue