mirror of
https://github.com/TECHNOFAB11/tmux-copyrat.git
synced 2025-12-12 16:10:07 +01:00
refactor: follow clippy suggestions
This commit is contained in:
parent
7e28931f6c
commit
ffd8e9b12d
7 changed files with 38 additions and 69 deletions
|
|
@ -6,7 +6,7 @@ use crate::error;
|
||||||
///
|
///
|
||||||
/// Keep in mind letters 'n' and 'y' are systematically removed at runtime to
|
/// Keep in mind letters 'n' and 'y' are systematically removed at runtime to
|
||||||
/// prevent conflict with navigation and yank/copy keys.
|
/// prevent conflict with navigation and yank/copy keys.
|
||||||
const ALPHABETS: [(&'static str, &'static str); 21] = [
|
const ALPHABETS: [(&str, &str); 21] = [
|
||||||
// ("abcd", "abcd"),
|
// ("abcd", "abcd"),
|
||||||
("qwerty", "asdfqwerzxcvjklmiuopghtybn"),
|
("qwerty", "asdfqwerzxcvjklmiuopghtybn"),
|
||||||
("qwerty-homerow", "asdfjklgh"),
|
("qwerty-homerow", "asdfjklgh"),
|
||||||
|
|
@ -47,7 +47,7 @@ pub fn parse_alphabet(src: &str) -> Result<Alphabet, error::ParseError> {
|
||||||
match alphabet_pair {
|
match alphabet_pair {
|
||||||
Some((_name, letters)) => {
|
Some((_name, letters)) => {
|
||||||
let letters = letters.replace(&['n', 'N', 'y', 'Y'][..], "");
|
let letters = letters.replace(&['n', 'N', 'y', 'Y'][..], "");
|
||||||
Ok(Alphabet(letters.to_string()))
|
Ok(Alphabet(letters))
|
||||||
}
|
}
|
||||||
None => Err(error::ParseError::UnknownAlphabet),
|
None => Err(error::ParseError::UnknownAlphabet),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,8 @@ impl BridgeOpt {
|
||||||
options: &HashMap<String, String>,
|
options: &HashMap<String, String>,
|
||||||
) -> Result<(), error::ParseError> {
|
) -> Result<(), error::ParseError> {
|
||||||
for (name, value) in options {
|
for (name, value) in options {
|
||||||
match name.as_ref() {
|
if let "@copyrat-capture" = name.as_ref() {
|
||||||
"@copyrat-capture" => {
|
self.capture_region = tmux::CaptureRegion::from_str(&value)?;
|
||||||
self.capture_region = tmux::CaptureRegion::from_str(&value)?;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,41 +91,17 @@ fn main() -> Result<(), error::ParseError> {
|
||||||
// buffer if it was uppercased.
|
// buffer if it was uppercased.
|
||||||
// TODO: consider getting rid of multi-selection mode.
|
// TODO: consider getting rid of multi-selection mode.
|
||||||
|
|
||||||
// Execute a command on each group of selections (normal and uppercased).
|
match selections {
|
||||||
let (normal_selections, uppercased_selections): (Vec<(String, bool)>, Vec<(String, bool)>) =
|
None => return Ok(()),
|
||||||
selections
|
Some((text, uppercased)) => {
|
||||||
.into_iter()
|
let args = vec!["set-buffer", &text];
|
||||||
.partition(|(_text, uppercased)| !*uppercased);
|
process::execute("tmux", &args)?;
|
||||||
|
|
||||||
let buffer_selections: String = normal_selections
|
if uppercased {
|
||||||
.into_iter()
|
let args = vec!["paste-buffer", "-t", active_pane.id.as_str()];
|
||||||
.map(|(text, _)| text)
|
process::execute("tmux", &args)?;
|
||||||
.collect::<Vec<_>>()
|
}
|
||||||
.join("\n");
|
}
|
||||||
|
|
||||||
if buffer_selections.len() > 0 {
|
|
||||||
let args = vec!["set-buffer", &buffer_selections];
|
|
||||||
// Simply execute the command as is, and let the program crash on
|
|
||||||
// potential errors because it is not our responsibility.
|
|
||||||
process::execute("tmux", &args).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let buffer_selections: String = uppercased_selections
|
|
||||||
.into_iter()
|
|
||||||
.map(|(text, _)| text)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
if buffer_selections.len() > 0 {
|
|
||||||
let args = vec!["set-buffer", &buffer_selections];
|
|
||||||
// Simply execute the command as is, and let the program crash on
|
|
||||||
// potential errors because it is not our responsibility.
|
|
||||||
process::execute("tmux", &args).unwrap();
|
|
||||||
|
|
||||||
let args = vec!["paste-buffer", "-t", active_pane.id.as_str()];
|
|
||||||
// Simply execute the command as is, and let the program crash on
|
|
||||||
// potential errors because it is not our responsibility.
|
|
||||||
process::execute("tmux", &args).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ fn main() {
|
||||||
handle.read_to_string(&mut buffer).unwrap();
|
handle.read_to_string(&mut buffer).unwrap();
|
||||||
|
|
||||||
// Execute copyrat over the buffer (will take control over stdout).
|
// Execute copyrat over the buffer (will take control over stdout).
|
||||||
// This returns the selected matches.
|
// This returns the selected matche.
|
||||||
let selection: Option<(String, bool)> = run(buffer, &opt);
|
let selection: Option<(String, bool)> = run(buffer, &opt);
|
||||||
|
|
||||||
// Early exit, signaling no selections were found.
|
// Early exit, signaling no selections were found.
|
||||||
|
|
@ -37,7 +37,7 @@ fn main() {
|
||||||
.open(target)
|
.open(target)
|
||||||
.expect("Unable to open the target file");
|
.expect("Unable to open the target file");
|
||||||
|
|
||||||
file.write(text.as_bytes()).unwrap();
|
file.write_all(text.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/model.rs
20
src/model.rs
|
|
@ -12,8 +12,8 @@ pub struct Model<'a> {
|
||||||
pub lines: Vec<&'a str>,
|
pub lines: Vec<&'a str>,
|
||||||
alphabet: &'a Alphabet,
|
alphabet: &'a Alphabet,
|
||||||
use_all_patterns: bool,
|
use_all_patterns: bool,
|
||||||
named_patterns: &'a Vec<NamedPattern>,
|
named_patterns: &'a [NamedPattern],
|
||||||
custom_patterns: &'a Vec<String>,
|
custom_patterns: &'a [String],
|
||||||
pub reverse: bool,
|
pub reverse: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,8 +22,8 @@ impl<'a> Model<'a> {
|
||||||
buffer: &'a str,
|
buffer: &'a str,
|
||||||
alphabet: &'a Alphabet,
|
alphabet: &'a Alphabet,
|
||||||
use_all_patterns: bool,
|
use_all_patterns: bool,
|
||||||
named_patterns: &'a Vec<NamedPattern>,
|
named_patterns: &'a [NamedPattern],
|
||||||
custom_patterns: &'a Vec<String>,
|
custom_patterns: &'a [String],
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
) -> Model<'a> {
|
) -> Model<'a> {
|
||||||
let lines = buffer.split('\n').collect();
|
let lines = buffer.split('\n').collect();
|
||||||
|
|
@ -112,7 +112,7 @@ impl<'a> Model<'a> {
|
||||||
loop {
|
loop {
|
||||||
let chunk_matches = all_regexes
|
let chunk_matches = all_regexes
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(&ref name, regex)| match regex.find_iter(chunk).nth(0) {
|
.filter_map(|(&ref name, regex)| match regex.find_iter(chunk).next() {
|
||||||
Some(m) => Some((name, regex, m)),
|
Some(m) => Some((name, regex, m)),
|
||||||
None => None,
|
None => None,
|
||||||
})
|
})
|
||||||
|
|
@ -164,7 +164,7 @@ impl<'a> Model<'a> {
|
||||||
/// If `unique` is `true`, all duplicate matches will have the same hint.
|
/// If `unique` is `true`, all duplicate matches will have the same hint.
|
||||||
/// For copying matched text, this seems easier and more natural.
|
/// For copying matched text, this seems easier and more natural.
|
||||||
/// If `unique` is `false`, duplicate matches will have their own hint.
|
/// If `unique` is `false`, duplicate matches will have their own hint.
|
||||||
fn associate_hints(&self, raw_matches: &Vec<RawMatch<'a>>, unique: bool) -> Vec<Match<'a>> {
|
fn associate_hints(&self, raw_matches: &[RawMatch<'a>], unique: bool) -> Vec<Match<'a>> {
|
||||||
let hints = self.alphabet.make_hints(raw_matches.len());
|
let hints = self.alphabet.make_hints(raw_matches.len());
|
||||||
let mut hints_iter = hints.iter();
|
let mut hints_iter = hints.iter();
|
||||||
|
|
||||||
|
|
@ -175,11 +175,11 @@ impl<'a> Model<'a> {
|
||||||
let mut known: collections::HashMap<&str, &str> = collections::HashMap::new();
|
let mut known: collections::HashMap<&str, &str> = collections::HashMap::new();
|
||||||
|
|
||||||
for raw_mat in raw_matches {
|
for raw_mat in raw_matches {
|
||||||
let hint: &str = known.entry(raw_mat.text).or_insert(
|
let hint: &str = known.entry(raw_mat.text).or_insert_with(|| {
|
||||||
hints_iter
|
hints_iter
|
||||||
.next()
|
.next()
|
||||||
.expect("We should have as many hints as necessary, even invisible ones."),
|
.expect("We should have as many hints as necessary, even invisible ones.")
|
||||||
);
|
});
|
||||||
|
|
||||||
result.push(Match {
|
result.push(Match {
|
||||||
x: raw_mat.x,
|
x: raw_mat.x,
|
||||||
|
|
@ -211,7 +211,7 @@ impl<'a> Model<'a> {
|
||||||
/// Builds a `SequenceTrie` that helps determine if a sequence of keys
|
/// Builds a `SequenceTrie` that helps determine if a sequence of keys
|
||||||
/// entered by the user corresponds to a match. This kind of lookup
|
/// entered by the user corresponds to a match. This kind of lookup
|
||||||
/// directly returns a reference to the corresponding `Match` if any.
|
/// directly returns a reference to the corresponding `Match` if any.
|
||||||
pub fn build_lookup_trie(matches: &'a Vec<Match<'a>>) -> SequenceTrie<char, usize> {
|
pub fn build_lookup_trie(matches: &'a [Match<'a>]) -> SequenceTrie<char, usize> {
|
||||||
let mut trie = SequenceTrie::new();
|
let mut trie = SequenceTrie::new();
|
||||||
|
|
||||||
for (index, mat) in matches.iter().enumerate() {
|
for (index, mat) in matches.iter().enumerate() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::error::ParseError;
|
||||||
|
|
||||||
/// Execute an arbitrary Unix command and return the stdout as a `String` if
|
/// Execute an arbitrary Unix command and return the stdout as a `String` if
|
||||||
/// successful.
|
/// successful.
|
||||||
pub fn execute(command: &str, args: &Vec<&str>) -> Result<String, ParseError> {
|
pub fn execute(command: &str, args: &[&str]) -> Result<String, ParseError> {
|
||||||
let output = Command::new(command).args(args).output()?;
|
let output = Command::new(command).args(args).output()?;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
pub const EXCLUDE_PATTERNS: [(&'static str, &'static str); 1] =
|
pub const EXCLUDE_PATTERNS: [(&str, &str); 1] =
|
||||||
[("ansi_colors", r"[[:cntrl:]]\[([0-9]{1,2};)?([0-9]{1,2})?m")];
|
[("ansi_colors", r"[[:cntrl:]]\[([0-9]{1,2};)?([0-9]{1,2})?m")];
|
||||||
|
|
||||||
/// Holds all the regex patterns that are currently supported.
|
/// Holds all the regex patterns that are currently supported.
|
||||||
///
|
///
|
||||||
/// The email address was obtained at https://www.regular-expressions.info/email.html.
|
/// The email address was obtained at https://www.regular-expressions.info/email.html.
|
||||||
/// Others were obtained from Ferran Basora.
|
/// Others were obtained from Ferran Basora.
|
||||||
pub const PATTERNS: [(&'static str, &'static str); 15] = [
|
pub const PATTERNS: [(&str, &str); 15] = [
|
||||||
("markdown-url", r"\[[^]]*\]\(([^)]+)\)"),
|
("markdown-url", r"\[[^]]*\]\(([^)]+)\)"),
|
||||||
(
|
(
|
||||||
"url",
|
"url",
|
||||||
|
|
|
||||||
22
src/ui.rs
22
src/ui.rs
|
|
@ -82,10 +82,8 @@ impl<'a> Ui<'a> {
|
||||||
} else {
|
} else {
|
||||||
self.focus_index -= 1;
|
self.focus_index -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else if self.focus_index > 0 {
|
||||||
if self.focus_index > 0 {
|
self.focus_index -= 1;
|
||||||
self.focus_index -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let new_index = self.focus_index;
|
let new_index = self.focus_index;
|
||||||
(old_index, new_index)
|
(old_index, new_index)
|
||||||
|
|
@ -101,10 +99,8 @@ impl<'a> Ui<'a> {
|
||||||
} else {
|
} else {
|
||||||
self.focus_index += 1;
|
self.focus_index += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else if self.focus_index < self.matches.len() - 1 {
|
||||||
if self.focus_index < self.matches.len() - 1 {
|
self.focus_index += 1;
|
||||||
self.focus_index += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let new_index = self.focus_index;
|
let new_index = self.focus_index;
|
||||||
(old_index, new_index)
|
(old_index, new_index)
|
||||||
|
|
@ -137,10 +133,10 @@ impl<'a> Ui<'a> {
|
||||||
/// - This writes directly on the writer, avoiding extra allocation.
|
/// - This writes directly on the writer, avoiding extra allocation.
|
||||||
fn render_base_text(
|
fn render_base_text(
|
||||||
stdout: &mut dyn io::Write,
|
stdout: &mut dyn io::Write,
|
||||||
lines: &Vec<&str>,
|
lines: &[&str],
|
||||||
line_offsets: &Vec<usize>,
|
line_offsets: &[usize],
|
||||||
colors: &UiColors,
|
colors: &UiColors,
|
||||||
) -> () {
|
) {
|
||||||
write!(
|
write!(
|
||||||
stdout,
|
stdout,
|
||||||
"{bg_color}{fg_color}",
|
"{bg_color}{fg_color}",
|
||||||
|
|
@ -361,7 +357,7 @@ impl<'a> Ui<'a> {
|
||||||
/// # Note
|
/// # Note
|
||||||
/// Multibyte characters are taken into account, so that the Match's `text`
|
/// Multibyte characters are taken into account, so that the Match's `text`
|
||||||
/// and `hint` are rendered in their proper position.
|
/// and `hint` are rendered in their proper position.
|
||||||
fn full_render(&self, stdout: &mut dyn io::Write) -> () {
|
fn full_render(&self, stdout: &mut dyn io::Write) {
|
||||||
// 1. Trim all lines and render non-empty ones.
|
// 1. Trim all lines and render non-empty ones.
|
||||||
Ui::render_base_text(
|
Ui::render_base_text(
|
||||||
stdout,
|
stdout,
|
||||||
|
|
@ -557,7 +553,7 @@ impl<'a> Ui<'a> {
|
||||||
|
|
||||||
/// Compute each line's actual y offset if displayed in a terminal of width
|
/// Compute each line's actual y offset if displayed in a terminal of width
|
||||||
/// `term_width`.
|
/// `term_width`.
|
||||||
fn get_line_offsets(lines: &Vec<&str>, term_width: u16) -> Vec<usize> {
|
fn get_line_offsets(lines: &[&str], term_width: u16) -> Vec<usize> {
|
||||||
lines
|
lines
|
||||||
.iter()
|
.iter()
|
||||||
.scan(0, |offset, &line| {
|
.scan(0, |offset, &line| {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue