Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into conditional_binding2
Browse files Browse the repository at this point in the history
  • Loading branch information
gwenn committed Mar 6, 2021
2 parents 7a1e05d + 4eeb2e4 commit 15d9f43
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 116 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
run: cargo test --workspace --all-targets
- name: Run doctests
run: cargo test --workspace --doc
- name: Test features
if: matrix.os != 'windows-latest'
run: cargo test --workspace --all-targets --all-features

env:
RUST_BACKTRACE: 1
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ smallvec = "1.6.1"
radix_trie = "0.2"

[target.'cfg(unix)'.dependencies]
nix = "0.19"
nix = "0.20"
utf8parse = "0.2"
skim = { version = "0.7", optional = true }
skim = { version = "0.9", optional = true }

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["consoleapi", "handleapi", "minwindef", "processenv", "winbase", "wincon", "winuser"] }
Expand Down
6 changes: 3 additions & 3 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub fn execute<H: Helper>(
}
Cmd::CapitalizeWord => {
// capitalize word after point
s.edit_word(WordAction::CAPITALIZE)?
s.edit_word(WordAction::Capitalize)?
}
Cmd::Kill(ref mvt) => {
s.edit_kill(mvt)?;
Expand All @@ -193,15 +193,15 @@ pub fn execute<H: Helper>(
}
Cmd::DowncaseWord => {
// lowercase word after point
s.edit_word(WordAction::LOWERCASE)?
s.edit_word(WordAction::Lowercase)?
}
Cmd::TransposeWords(n) => {
// transpose words
s.edit_transpose_words(n)?
}
Cmd::UpcaseWord => {
// uppercase word after point
s.edit_word(WordAction::UPPERCASE)?
s.edit_word(WordAction::Uppercase)?
}
Cmd::YankPop => {
// yank-pop
Expand Down
30 changes: 14 additions & 16 deletions src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,22 +357,20 @@ fn filename_complete(
// if any of the below IO operations have errors, just ignore them
if let Ok(read_dir) = dir.read_dir() {
let file_name = normalize(file_name);
for entry in read_dir {
if let Ok(entry) = entry {
if let Some(s) = entry.file_name().to_str() {
let ns = normalize(s);
if ns.starts_with(file_name.as_ref()) {
if let Ok(metadata) = fs::metadata(entry.path()) {
let mut path = String::from(dir_name) + s;
if metadata.is_dir() {
path.push(sep);
}
entries.push(Pair {
display: String::from(s),
replacement: escape(path, esc_char, break_chars, quote),
});
} // else ignore PermissionDenied
}
for entry in read_dir.flatten() {
if let Some(s) = entry.file_name().to_str() {
let ns = normalize(s);
if ns.starts_with(file_name.as_ref()) {
if let Ok(metadata) = fs::metadata(entry.path()) {
let mut path = String::from(dir_name) + s;
if metadata.is_dir() {
path.push(sep);
}
entries.push(Pair {
display: String::from(s),
replacement: escape(path, esc_char, break_chars, quote),
});
} // else ignore PermissionDenied
}
}
}
Expand Down
19 changes: 7 additions & 12 deletions src/keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -938,19 +938,14 @@ impl InputState {
E(K::Char('E'), M::NONE) => Some(Movement::ForwardWord(n, At::AfterEnd, Word::Big)),
E(K::Char(c), M::NONE) if c == 'f' || c == 'F' || c == 't' || c == 'T' => {
let cs = self.vi_char_search(rdr, c)?;
match cs {
Some(cs) => Some(Movement::ViCharSearch(n, cs)),
None => None,
}
cs.map(|cs| Movement::ViCharSearch(n, cs))
}
E(K::Char(';'), M::NONE) => match self.last_char_search {
Some(cs) => Some(Movement::ViCharSearch(n, cs)),
None => None,
},
E(K::Char(','), M::NONE) => match self.last_char_search {
Some(ref cs) => Some(Movement::ViCharSearch(n, cs.opposite())),
None => None,
},
E(K::Char(';'), M::NONE) => self
.last_char_search
.map(|cs| Movement::ViCharSearch(n, cs)),
E(K::Char(','), M::NONE) => self
.last_char_search
.map(|cs| Movement::ViCharSearch(n, cs.opposite())),
E(K::Char('h'), M::NONE) | E(K::Char('H'), M::CTRL) | E::BACKSPACE => {
Some(Movement::BackwardChar(n))
}
Expand Down
44 changes: 33 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ fn complete_line<H: Helper>(
config: &Config,
) -> Result<Option<Cmd>> {
#[cfg(all(unix, feature = "with-fuzzy"))]
use skim::{Skim, SkimOptionsBuilder};
use skim::prelude::{
unbounded, Skim, SkimItem, SkimItemReceiver, SkimItemSender, SkimOptionsBuilder,
};

let completer = s.helper.unwrap();
// get a list of completions
Expand Down Expand Up @@ -192,13 +194,31 @@ fn complete_line<H: Helper>(
// corresponding completion_type
#[cfg(all(unix, feature = "with-fuzzy"))]
{
use std::borrow::Cow;
if CompletionType::Fuzzy == config.completion_type() {
// skim takes input of candidates separated by new line
let input = candidates
struct Candidate {
index: usize,
text: String,
}
impl SkimItem for Candidate {
fn text(&self) -> Cow<str> {
Cow::Borrowed(&self.text)
}
}

let (tx_item, rx_item): (SkimItemSender, SkimItemReceiver) = unbounded();

candidates
.iter()
.map(|c| c.display())
.collect::<Vec<_>>()
.join("\n");
.enumerate()
.map(|(i, c)| Candidate {
index: i,
text: c.display().to_owned(),
})
.for_each(|c| {
let _ = tx_item.send(Arc::new(c));
});
drop(tx_item); // so that skim could know when to stop waiting for more items.

// setup skim and run with input options
// will display UI for fuzzy search and return selected results
Expand All @@ -211,15 +231,17 @@ fn complete_line<H: Helper>(
.build()
.unwrap();

let selected_items =
Skim::run_with(&options, Some(Box::new(std::io::Cursor::new(input))))
.map(|out| out.selected_items)
.unwrap_or_else(Vec::new);
let selected_items = Skim::run_with(&options, Some(rx_item))
.map(|out| out.selected_items)
.unwrap_or_else(Vec::new);

// match the first (and only) returned option with the candidate and update the
// line otherwise only refresh line to clear the skim UI changes
if let Some(item) = selected_items.first() {
if let Some(candidate) = candidates.get(item.get_index()) {
let item: &Candidate = (*item).as_any() // cast to Any
.downcast_ref::<Candidate>() // downcast to concrete type
.expect("something wrong with downcast");
if let Some(candidate) = candidates.get(item.index) {
completer.update(&mut s.line, start, candidate.replacement());
}
}
Expand Down
113 changes: 44 additions & 69 deletions src/line_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ pub(crate) const INDENT: &str = " ";
#[derive(Clone, Copy)]
pub enum WordAction {
/// Capitalize word
CAPITALIZE,
Capitalize,
/// lowercase word
LOWERCASE,
Lowercase,
/// uppercase word
UPPERCASE,
Uppercase,
}

/// Delete (kill) direction
Expand Down Expand Up @@ -694,23 +694,19 @@ impl LineBuffer {
}
}
};
if let Some(pos) = search_result {
Some(match cs {
CharSearch::Backward(_) => pos,
CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
CharSearch::Forward(_) => shift + pos,
CharSearch::ForwardBefore(_) => {
shift + pos
- self.buf[..shift + pos]
.chars()
.next_back()
.unwrap()
.len_utf8()
}
})
} else {
None
}
search_result.map(|pos| match cs {
CharSearch::Backward(_) => pos,
CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
CharSearch::Forward(_) => shift + pos,
CharSearch::ForwardBefore(_) => {
shift + pos
- self.buf[..shift + pos]
.chars()
.next_back()
.unwrap()
.len_utf8()
}
})
}

/// Move cursor to the matching character position.
Expand Down Expand Up @@ -792,13 +788,13 @@ impl LineBuffer {
.drain(start..end, Direction::default())
.collect::<String>();
let result = match a {
WordAction::CAPITALIZE => {
WordAction::Capitalize => {
let ch = (&word).graphemes(true).next().unwrap();
let cap = ch.to_uppercase();
cap + &word[ch.len()..].to_lowercase()
}
WordAction::LOWERCASE => word.to_lowercase(),
WordAction::UPPERCASE => word.to_uppercase(),
WordAction::Lowercase => word.to_lowercase(),
WordAction::Uppercase => word.to_uppercase(),
};
self.insert_str(start, &result);
self.pos = start + result.len();
Expand Down Expand Up @@ -923,10 +919,9 @@ impl LineBuffer {
Movement::ViFirstPrint => {
if self.pos == 0 {
None
} else if let Some(pos) = self.next_word_pos(0, At::Start, Word::Big, 1) {
Some(self.buf[pos..self.pos].to_owned())
} else {
None
self.next_word_pos(0, At::Start, Word::Big, 1)
.map(|pos| self.buf[pos..self.pos].to_owned())
}
}
Movement::EndOfLine => {
Expand Down Expand Up @@ -958,51 +953,31 @@ impl LineBuffer {
Some(self.buf[..self.pos].to_owned())
}
}
Movement::BackwardWord(n, word_def) => {
if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
Some(self.buf[pos..self.pos].to_owned())
} else {
None
}
}
Movement::ForwardWord(n, at, word_def) => {
if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
Some(self.buf[self.pos..pos].to_owned())
} else {
None
}
}
Movement::BackwardWord(n, word_def) => self
.prev_word_pos(self.pos, word_def, n)
.map(|pos| self.buf[pos..self.pos].to_owned()),
Movement::ForwardWord(n, at, word_def) => self
.next_word_pos(self.pos, at, word_def, n)
.map(|pos| self.buf[self.pos..pos].to_owned()),
Movement::ViCharSearch(n, cs) => {
let search_result = match cs {
CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
_ => self.search_char_pos(cs, n),
};
if let Some(pos) = search_result {
Some(match cs {
CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
self.buf[pos..self.pos].to_owned()
}
CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
})
} else {
None
}
}
Movement::BackwardChar(n) => {
if let Some(pos) = self.prev_pos(n) {
Some(self.buf[pos..self.pos].to_owned())
} else {
None
}
}
Movement::ForwardChar(n) => {
if let Some(pos) = self.next_pos(n) {
Some(self.buf[self.pos..pos].to_owned())
} else {
None
}
search_result.map(|pos| match cs {
CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
self.buf[pos..self.pos].to_owned()
}
CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
})
}
Movement::BackwardChar(n) => self
.prev_pos(n)
.map(|pos| self.buf[pos..self.pos].to_owned()),
Movement::ForwardChar(n) => self
.next_pos(n)
.map(|pos| self.buf[self.pos..pos].to_owned()),
Movement::LineUp(n) => {
if let Some((start, end)) = self.n_lines_up(n) {
Some(self.buf[start..end].to_owned())
Expand Down Expand Up @@ -1798,22 +1773,22 @@ mod test {
#[test]
fn edit_word() {
let mut s = LineBuffer::init("a ßeta c", 1, None);
assert!(s.edit_word(WordAction::UPPERCASE));
assert!(s.edit_word(WordAction::Uppercase));
assert_eq!("a SSETA c", s.buf);
assert_eq!(7, s.pos);

let mut s = LineBuffer::init("a ßetA c", 1, None);
assert!(s.edit_word(WordAction::LOWERCASE));
assert!(s.edit_word(WordAction::Lowercase));
assert_eq!("a ßeta c", s.buf);
assert_eq!(7, s.pos);

let mut s = LineBuffer::init("a ßETA c", 1, None);
assert!(s.edit_word(WordAction::CAPITALIZE));
assert!(s.edit_word(WordAction::Capitalize));
assert_eq!("a SSeta c", s.buf);
assert_eq!(7, s.pos);

let mut s = LineBuffer::init("test", 1, None);
assert!(s.edit_word(WordAction::CAPITALIZE));
assert!(s.edit_word(WordAction::Capitalize));
assert_eq!("tEst", s.buf);
assert_eq!(4, s.pos);
}
Expand Down
6 changes: 3 additions & 3 deletions src/tty/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl RawReader for ConsoleRawReader {
loop {
// TODO GetNumberOfConsoleInputEvents
check(unsafe {
consoleapi::ReadConsoleInputW(self.handle, &mut rec, 1 as DWORD, &mut count)
consoleapi::ReadConsoleInputW(self.handle, &mut rec, 1, &mut count)
})?;

if rec.EventType == wincon::WINDOW_BUFFER_SIZE_EVENT {
Expand Down Expand Up @@ -188,7 +188,7 @@ impl RawReader for ConsoleRawReader {
} else if utf16 == 27 {
KeyEvent(K::Esc, mods)
} else {
if utf16 >= 0xD800 && utf16 < 0xDC00 {
if (0xD800..0xDC00).contains(&utf16) {
surrogate = utf16;
continue;
}
Expand Down Expand Up @@ -449,7 +449,7 @@ impl Renderer for ConsoleRenderer {
}

fn sigwinch(&self) -> bool {
SIGWINCH.compare_and_swap(true, false, Ordering::SeqCst)
SIGWINCH.compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst).unwrap_or(false)
}

/// Try to get the number of columns in the current terminal,
Expand Down

0 comments on commit 15d9f43

Please sign in to comment.