1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use app::App;
use errors::*;
use std::ascii::AsciiExt;
use std::fs::{File, create_dir_all};
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use xdg_basedir::dirs::get_data_home;
pub fn open<S: Into<String>>(uri: S) -> Result<()> {
let uri = uri.into();
let output = Command::new("xdg-open")
.arg(uri.clone())
.output()
.chain_err(|| "Could not execute xdg-open")?;
if output.status.success() {
Ok(())
} else {
Err(
format!(
"Executing `xdg-open {}` failed: {}",
uri,
String::from_utf8_lossy(&output.stdout)
).into(),
)
}
}
fn clean_string(input: &str) -> String {
input.replace(".", "").replace("/", "").to_ascii_lowercase()
}
pub fn install(app: &App, schemes: &[String]) -> Result<()> {
let home = get_data_home().chain_err(|| "Home directory not found")?;
let ascii_name = format!(
"{}-{}.desktop",
clean_string(&app.vendor).as_str(),
clean_string(&app.name).as_str()
);
let mut desktop_target = PathBuf::new();
desktop_target.push(home);
desktop_target.push("applications");
let apps_dir = desktop_target.clone();
create_dir_all(apps_dir.clone()).chain_err(
|| "Could not create app directory",
)?;
desktop_target.push(ascii_name.clone());
let mut f = File::create(desktop_target.as_path()).chain_err(
|| "Could not create app desktop file",
)?;
let schemes_list = schemes
.iter()
.map(|s| match s.matches(char::is_uppercase).next() {
Some(_) => {
println!("[WARN] system-uri: converting schema '{}' to lowercase", s);
format!("x-scheme-handler/{}", s.to_lowercase())
}
None => format!("x-scheme-handler/{}", s),
})
.collect::<Vec<String>>();
f.write_fmt(format_args!(
include_str!("./template.desktop"),
name = app.name,
exec = app.exec,
mime_types = schemes_list.join(";")
)).chain_err(|| " Could not write app desktop file")?;
let status = Command::new("update-desktop-database")
.arg(apps_dir)
.status()
.chain_err(|| "Could not run update-desktop-database")?;
for scheme in schemes_list {
let _ = Command::new("xdg-mime")
.arg("default")
.arg(ascii_name.clone())
.arg(scheme)
.status()
.chain_err(|| "Could not run xdg-mime")?;
}
if status.success() {
Ok(())
} else {
Err(
("Executing update-desktop-database failed. See terminal output for errors.").into(),
)
}
}