Open files with drag and drop, escape filenames
This commit is contained in:
parent
fdaff9748a
commit
0c398c893a
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -350,14 +350,17 @@ dependencies = [
|
|||||||
"gtk 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gtk 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"neovim-lib 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"neovim-lib 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pango 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pango-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pangocairo 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pangocairo 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pangocairo-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pangocairo-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -419,6 +422,11 @@ dependencies = [
|
|||||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.7.21"
|
version = "0.7.21"
|
||||||
@ -750,6 +758,7 @@ dependencies = [
|
|||||||
"checksum pango-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94039b3921a4af4058a3e4335e5d15099101f298a92f5afc40bab3a3027594a1"
|
"checksum pango-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94039b3921a4af4058a3e4335e5d15099101f298a92f5afc40bab3a3027594a1"
|
||||||
"checksum pangocairo 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db4130d0e0567b177178c9568466277ff167cb43a245b2881e203509ea5fbd84"
|
"checksum pangocairo 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db4130d0e0567b177178c9568466277ff167cb43a245b2881e203509ea5fbd84"
|
||||||
"checksum pangocairo-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "decc9523cd5bbba49a67ed8d2ef7dfca957f4760bf420a1ea4a82634da26381c"
|
"checksum pangocairo-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "decc9523cd5bbba49a67ed8d2ef7dfca957f4760bf420a1ea4a82634da26381c"
|
||||||
|
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||||
"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
|
"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
|
||||||
"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
|
"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
|
||||||
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
|
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
|
||||||
|
@ -31,6 +31,9 @@ phf = "0.7"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
htmlescape = "0.3"
|
htmlescape = "0.3"
|
||||||
|
percent-encoding = "1.0"
|
||||||
|
regex = "0.2"
|
||||||
|
lazy_static = "1.0"
|
||||||
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -15,6 +15,7 @@ use gtk::prelude::*;
|
|||||||
|
|
||||||
use neovim_lib::{NeovimApi, NeovimApiAsync};
|
use neovim_lib::{NeovimApi, NeovimApiAsync};
|
||||||
|
|
||||||
|
use misc::escape_filename;
|
||||||
use nvim::{ErrorReport, NeovimClient, NeovimRef};
|
use nvim::{ErrorReport, NeovimClient, NeovimRef};
|
||||||
use shell;
|
use shell;
|
||||||
|
|
||||||
@ -267,6 +268,7 @@ impl FileBrowserWidget {
|
|||||||
} else {
|
} else {
|
||||||
&file_path
|
&file_path
|
||||||
};
|
};
|
||||||
|
let file_path = escape_filename(file_path);
|
||||||
nvim_ref.nvim().unwrap().command_async(&format!(":e {}", file_path))
|
nvim_ref.nvim().unwrap().command_async(&format!(":e {}", file_path))
|
||||||
.cb(|r| r.report_err())
|
.cb(|r| r.report_err())
|
||||||
.call();
|
.call();
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -11,13 +11,17 @@ extern crate gtk;
|
|||||||
extern crate gtk_sys;
|
extern crate gtk_sys;
|
||||||
extern crate htmlescape;
|
extern crate htmlescape;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate neovim_lib;
|
extern crate neovim_lib;
|
||||||
extern crate pango;
|
extern crate pango;
|
||||||
extern crate pango_cairo_sys;
|
extern crate pango_cairo_sys;
|
||||||
extern crate pango_sys;
|
extern crate pango_sys;
|
||||||
extern crate pangocairo;
|
extern crate pangocairo;
|
||||||
|
extern crate percent_encoding;
|
||||||
extern crate phf;
|
extern crate phf;
|
||||||
|
extern crate regex;
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -50,6 +54,7 @@ mod tabline;
|
|||||||
mod error;
|
mod error;
|
||||||
mod file_browser;
|
mod file_browser;
|
||||||
mod subscriptions;
|
mod subscriptions;
|
||||||
|
mod misc;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -58,6 +63,7 @@ use gio::prelude::*;
|
|||||||
|
|
||||||
use ui::Ui;
|
use ui::Ui;
|
||||||
|
|
||||||
|
use misc::escape_filename;
|
||||||
use shell::ShellOptions;
|
use shell::ShellOptions;
|
||||||
|
|
||||||
const BIN_PATH_ARG: &str = "--nvim-bin-path";
|
const BIN_PATH_ARG: &str = "--nvim-bin-path";
|
||||||
@ -101,7 +107,9 @@ fn open(app: >k::Application, files: &[gio::File], _: &str) {
|
|||||||
for f in files {
|
for f in files {
|
||||||
let mut ui = Ui::new(ShellOptions::new(
|
let mut ui = Ui::new(ShellOptions::new(
|
||||||
nvim_bin_path(std::env::args()),
|
nvim_bin_path(std::env::args()),
|
||||||
f.get_path().and_then(|p| p.to_str().map(str::to_owned)),
|
f.get_path().and_then(|p| {
|
||||||
|
p.to_str().map(|path| escape_filename(path).to_string())
|
||||||
|
}),
|
||||||
nvim_timeout(std::env::args()),
|
nvim_timeout(std::env::args()),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
38
src/misc.rs
Normal file
38
src/misc.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
use percent_encoding::percent_decode;
|
||||||
|
|
||||||
|
/// Escape special ASCII characters with a backslash.
|
||||||
|
pub fn escape_filename<'t>(filename: &'t str) -> Cow<'t, str> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref SPECIAL_CHARS: Regex = if cfg!(target_os = "windows") {
|
||||||
|
// On Windows, don't escape `:` and `\`, as these are valid components of the path.
|
||||||
|
Regex::new(r"[[:ascii:]&&[^0-9a-zA-Z._:\\-]]").unwrap()
|
||||||
|
} else {
|
||||||
|
// Similarly, don't escape `/` on other platforms.
|
||||||
|
Regex::new(r"[[:ascii:]&&[^0-9a-zA-Z._/-]]").unwrap()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
SPECIAL_CHARS.replace_all(&*filename, r"\$0")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode a file URI.
|
||||||
|
///
|
||||||
|
/// - On UNIX: `file:///path/to/a%20file.ext` -> `/path/to/a file.ext`
|
||||||
|
/// - On Windows: `file:///C:/path/to/a%20file.ext` -> `C:\path\to\a file.ext`
|
||||||
|
pub fn decode_uri(uri: &str) -> Option<String> {
|
||||||
|
let path = match uri.split_at(8) {
|
||||||
|
("file:///", path) => path,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
let path = percent_decode(path.as_bytes()).decode_utf8().ok()?;
|
||||||
|
if cfg!(target_os = "windows") {
|
||||||
|
lazy_static! {
|
||||||
|
static ref SLASH: Regex = Regex::new(r"/").unwrap();
|
||||||
|
}
|
||||||
|
Some(String::from(SLASH.replace_all(&*path, r"\")))
|
||||||
|
} else {
|
||||||
|
Some("/".to_owned() + &path)
|
||||||
|
}
|
||||||
|
}
|
23
src/shell.rs
23
src/shell.rs
@ -18,6 +18,7 @@ use pangocairo;
|
|||||||
use neovim_lib::{Neovim, NeovimApi, NeovimApiAsync, Value};
|
use neovim_lib::{Neovim, NeovimApi, NeovimApiAsync, Value};
|
||||||
use neovim_lib::neovim_api::Tabpage;
|
use neovim_lib::neovim_api::Tabpage;
|
||||||
|
|
||||||
|
use misc::{decode_uri, escape_filename};
|
||||||
use settings::{FontSource, Settings};
|
use settings::{FontSource, Settings};
|
||||||
use ui_model::{Attrs, ModelRect, UiModel};
|
use ui_model::{Attrs, ModelRect, UiModel};
|
||||||
use color::{Color, ColorModel, COLOR_BLACK, COLOR_RED, COLOR_WHITE};
|
use color::{Color, ColorModel, COLOR_BLACK, COLOR_RED, COLOR_WHITE};
|
||||||
@ -567,6 +568,28 @@ impl Shell {
|
|||||||
state.drawing_area.connect_size_allocate(move |_, _| {
|
state.drawing_area.connect_size_allocate(move |_, _| {
|
||||||
init_nvim(&ref_state);
|
init_nvim(&ref_state);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let ref_state = self.state.clone();
|
||||||
|
let targets = vec![
|
||||||
|
gtk::TargetEntry::new("text/uri-list", gtk::TargetFlags::OTHER_APP, 0),
|
||||||
|
];
|
||||||
|
state
|
||||||
|
.drawing_area
|
||||||
|
.drag_dest_set(gtk::DestDefaults::ALL, &targets, gdk::DragAction::COPY);
|
||||||
|
state
|
||||||
|
.drawing_area
|
||||||
|
.connect_drag_data_received(move |_, _, _, _, s, _, _| {
|
||||||
|
let uris = s.get_uris();
|
||||||
|
let command = uris.iter()
|
||||||
|
.filter_map(|uri| decode_uri(uri))
|
||||||
|
.fold(":ar".to_owned(), |command, filename| {
|
||||||
|
let filename = escape_filename(&filename);
|
||||||
|
command + " " + &filename
|
||||||
|
});
|
||||||
|
let state = ref_state.borrow_mut();
|
||||||
|
let mut nvim = state.nvim().unwrap();
|
||||||
|
nvim.command_async(&command).cb(|r| r.report_err()).call()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
Loading…
Reference in New Issue
Block a user