Merge pull request #73 from christopher-l/feature/drag-and-drop
Open files with drag and drop, escape filenames
This commit is contained in:
commit
15a285b032
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-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)",
|
||||
"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)",
|
||||
"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-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-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_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_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)",
|
||||
@ -419,6 +422,11 @@ dependencies = [
|
||||
"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]]
|
||||
name = "phf"
|
||||
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 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 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_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"
|
||||
|
@ -31,6 +31,9 @@ phf = "0.7"
|
||||
log = "0.4"
|
||||
env_logger = "0.5"
|
||||
htmlescape = "0.3"
|
||||
percent-encoding = "1.0"
|
||||
regex = "0.2"
|
||||
lazy_static = "1.0"
|
||||
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
@ -15,6 +15,7 @@ use gtk::prelude::*;
|
||||
|
||||
use neovim_lib::{NeovimApi, NeovimApiAsync};
|
||||
|
||||
use misc::escape_filename;
|
||||
use nvim::{ErrorReport, NeovimClient, NeovimRef};
|
||||
use shell;
|
||||
|
||||
@ -267,6 +268,7 @@ impl FileBrowserWidget {
|
||||
} else {
|
||||
&file_path
|
||||
};
|
||||
let file_path = escape_filename(file_path);
|
||||
nvim_ref.nvim().unwrap().command_async(&format!(":e {}", file_path))
|
||||
.cb(|r| r.report_err())
|
||||
.call();
|
||||
|
10
src/main.rs
10
src/main.rs
@ -11,13 +11,17 @@ extern crate gtk;
|
||||
extern crate gtk_sys;
|
||||
extern crate htmlescape;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate neovim_lib;
|
||||
extern crate pango;
|
||||
extern crate pango_cairo_sys;
|
||||
extern crate pango_sys;
|
||||
extern crate pangocairo;
|
||||
extern crate percent_encoding;
|
||||
extern crate phf;
|
||||
extern crate regex;
|
||||
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
@ -50,6 +54,7 @@ mod tabline;
|
||||
mod error;
|
||||
mod file_browser;
|
||||
mod subscriptions;
|
||||
mod misc;
|
||||
|
||||
use std::env;
|
||||
use std::time::Duration;
|
||||
@ -58,6 +63,7 @@ use gio::prelude::*;
|
||||
|
||||
use ui::Ui;
|
||||
|
||||
use misc::escape_filename;
|
||||
use shell::ShellOptions;
|
||||
|
||||
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 {
|
||||
let mut ui = Ui::new(ShellOptions::new(
|
||||
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()),
|
||||
));
|
||||
|
||||
|
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_api::Tabpage;
|
||||
|
||||
use misc::{decode_uri, escape_filename};
|
||||
use settings::{FontSource, Settings};
|
||||
use ui_model::{Attrs, ModelRect, UiModel};
|
||||
use color::{Color, ColorModel, COLOR_BLACK, COLOR_RED, COLOR_WHITE};
|
||||
@ -567,6 +568,28 @@ impl Shell {
|
||||
state.drawing_area.connect_size_allocate(move |_, _| {
|
||||
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)]
|
||||
|
Loading…
Reference in New Issue
Block a user