mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 15:14:44 +00:00
Port killring
This commit is contained in:
parent
cfdcaf880f
commit
c2f58cd312
7 changed files with 112 additions and 66 deletions
|
@ -54,6 +54,7 @@ fn main() {
|
|||
"src/future_feature_flags.rs",
|
||||
"src/highlight.rs",
|
||||
"src/job_group.rs",
|
||||
"src/kill.rs",
|
||||
"src/null_terminated_array.rs",
|
||||
"src/parse_constants.rs",
|
||||
"src/parse_tree.rs",
|
||||
|
|
2
fish-rust/src/env/environment_impl.rs
vendored
2
fish-rust/src/env/environment_impl.rs
vendored
|
@ -44,7 +44,7 @@ pub static UVAR_SCOPE_IS_GLOBAL: RelaxedAtomicBool = RelaxedAtomicBool::new(fals
|
|||
|
||||
/// Helper to get the kill ring.
|
||||
fn get_kill_ring_entries() -> Vec<WString> {
|
||||
ffi::kill_entries_ffi().from_ffi()
|
||||
crate::kill::kill_entries()
|
||||
}
|
||||
|
||||
/// Helper to get the history for a session ID.
|
||||
|
|
|
@ -33,7 +33,6 @@ include_cpp! {
|
|||
#include "history.h"
|
||||
#include "io.h"
|
||||
#include "input_common.h"
|
||||
#include "kill.h"
|
||||
#include "parse_constants.h"
|
||||
#include "parser.h"
|
||||
#include "parse_util.h"
|
||||
|
@ -133,7 +132,6 @@ include_cpp! {
|
|||
|
||||
generate!("colorize_shell")
|
||||
generate!("reader_status_count")
|
||||
generate!("kill_entries_ffi")
|
||||
|
||||
generate!("get_history_variable_text_ffi")
|
||||
|
||||
|
|
99
fish-rust/src/kill.rs
Normal file
99
fish-rust/src/kill.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
//! The killring.
|
||||
//!
|
||||
//! Works like the killring in emacs and readline. The killring is cut and paste with a memory of
|
||||
//! previous cuts.
|
||||
|
||||
use cxx::CxxWString;
|
||||
use std::collections::VecDeque;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::ffi::wcstring_list_ffi_t;
|
||||
use crate::wchar::WString;
|
||||
use crate::wchar_ffi::WCharFromFFI;
|
||||
|
||||
#[cxx::bridge]
|
||||
mod kill_ffi {
|
||||
extern "C++" {
|
||||
include!("wutil.h");
|
||||
type wcstring_list_ffi_t = super::wcstring_list_ffi_t;
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
#[cxx_name = "kill_add"]
|
||||
fn kill_add_ffi(new_entry: &CxxWString);
|
||||
#[cxx_name = "kill_replace"]
|
||||
fn kill_replace_ffi(old_entry: &CxxWString, new_entry: &CxxWString);
|
||||
#[cxx_name = "kill_yank_rotate"]
|
||||
fn kill_yank_rotate_ffi(mut out_front: Pin<&mut CxxWString>);
|
||||
#[cxx_name = "kill_yank"]
|
||||
fn kill_yank_ffi(mut out_front: Pin<&mut CxxWString>);
|
||||
#[cxx_name = "kill_entries"]
|
||||
fn kill_entries_ffi(mut out: Pin<&mut wcstring_list_ffi_t>);
|
||||
}
|
||||
}
|
||||
|
||||
static KILL_LIST: once_cell::sync::Lazy<Mutex<VecDeque<WString>>> =
|
||||
once_cell::sync::Lazy::new(|| Mutex::new(VecDeque::new()));
|
||||
|
||||
fn kill_add_ffi(new_entry: &CxxWString) {
|
||||
kill_add(new_entry.from_ffi());
|
||||
}
|
||||
|
||||
/// Add a string to the top of the killring.
|
||||
pub fn kill_add(new_entry: WString) {
|
||||
if !new_entry.is_empty() {
|
||||
KILL_LIST.lock().unwrap().push_front(new_entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn kill_replace_ffi(old_entry: &CxxWString, new_entry: &CxxWString) {
|
||||
kill_replace(old_entry.from_ffi(), new_entry.from_ffi())
|
||||
}
|
||||
|
||||
/// Replace the specified string in the killring.
|
||||
pub fn kill_replace(old_entry: WString, new_entry: WString) {
|
||||
let mut kill_list = KILL_LIST.lock().unwrap();
|
||||
if let Some(old_entry_idx) = kill_list.iter().position(|entry| entry == &old_entry) {
|
||||
kill_list.remove(old_entry_idx);
|
||||
}
|
||||
if !new_entry.is_empty() {
|
||||
kill_list.push_front(new_entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn kill_yank_rotate_ffi(mut out_front: Pin<&mut CxxWString>) {
|
||||
out_front.as_mut().clear();
|
||||
out_front
|
||||
.as_mut()
|
||||
.push_chars(kill_yank_rotate().as_char_slice());
|
||||
}
|
||||
|
||||
/// Rotate the killring.
|
||||
pub fn kill_yank_rotate() -> WString {
|
||||
let mut kill_list = KILL_LIST.lock().unwrap();
|
||||
kill_list.rotate_left(1);
|
||||
kill_list.front().cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn kill_yank_ffi(mut out_front: Pin<&mut CxxWString>) {
|
||||
out_front.as_mut().clear();
|
||||
out_front.as_mut().push_chars(kill_yank().as_char_slice());
|
||||
}
|
||||
|
||||
/// Paste from the killring.
|
||||
pub fn kill_yank() -> WString {
|
||||
let kill_list = KILL_LIST.lock().unwrap();
|
||||
kill_list.front().cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn kill_entries_ffi(mut out_entries: Pin<&mut wcstring_list_ffi_t>) {
|
||||
out_entries.as_mut().clear();
|
||||
for kill_entry in KILL_LIST.lock().unwrap().iter() {
|
||||
out_entries.as_mut().push(kill_entry);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kill_entries() -> Vec<WString> {
|
||||
KILL_LIST.lock().unwrap().iter().cloned().collect()
|
||||
}
|
|
@ -42,6 +42,7 @@ mod global_safety;
|
|||
mod highlight;
|
||||
mod io;
|
||||
mod job_group;
|
||||
mod kill;
|
||||
mod locale;
|
||||
mod nix;
|
||||
mod null_terminated_array;
|
||||
|
|
58
src/kill.cpp
58
src/kill.cpp
|
@ -1,61 +1,21 @@
|
|||
// The killring.
|
||||
//
|
||||
// Works like the killring in emacs and readline. The killring is cut and paste with a memory of
|
||||
// previous cuts.
|
||||
#include "config.h" // IWYU pragma: keep
|
||||
|
||||
#include "kill.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "common.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
|
||||
/** Kill ring */
|
||||
static owning_lock<std::list<wcstring>> s_kill_list;
|
||||
|
||||
void kill_add(wcstring str) {
|
||||
if (!str.empty()) {
|
||||
s_kill_list.acquire()->push_front(std::move(str));
|
||||
}
|
||||
}
|
||||
|
||||
void kill_replace(const wcstring &old, const wcstring &newv) {
|
||||
auto kill_list = s_kill_list.acquire();
|
||||
// Remove old.
|
||||
auto iter = std::find(kill_list->begin(), kill_list->end(), old);
|
||||
if (iter != kill_list->end()) kill_list->erase(iter);
|
||||
|
||||
// Add new.
|
||||
if (!newv.empty()) {
|
||||
kill_list->push_front(newv);
|
||||
}
|
||||
}
|
||||
|
||||
wcstring kill_yank_rotate() {
|
||||
auto kill_list = s_kill_list.acquire();
|
||||
// Move the first element to the end.
|
||||
if (kill_list->empty()) {
|
||||
return {};
|
||||
}
|
||||
kill_list->splice(kill_list->end(), *kill_list, kill_list->begin());
|
||||
return kill_list->front();
|
||||
wcstring front;
|
||||
kill_yank_rotate(front);
|
||||
return front;
|
||||
}
|
||||
|
||||
wcstring kill_yank() {
|
||||
auto kill_list = s_kill_list.acquire();
|
||||
if (kill_list->empty()) {
|
||||
return {};
|
||||
}
|
||||
return kill_list->front();
|
||||
wcstring front;
|
||||
kill_yank(front);
|
||||
return front;
|
||||
}
|
||||
|
||||
std::vector<wcstring> kill_entries() {
|
||||
auto kill_list = s_kill_list.acquire();
|
||||
return std::vector<wcstring>{kill_list->begin(), kill_list->end()};
|
||||
wcstring_list_ffi_t entries;
|
||||
kill_entries(entries);
|
||||
return std::move(entries.vals);
|
||||
}
|
||||
|
||||
wcstring_list_ffi_t kill_entries_ffi() { return kill_entries(); }
|
||||
|
|
15
src/kill.h
15
src/kill.h
|
@ -1,18 +1,8 @@
|
|||
// Prototypes for the killring.
|
||||
//
|
||||
// Works like the killring in emacs and readline. The killring is cut and paste with a memory of
|
||||
// previous cuts.
|
||||
#ifndef FISH_KILL_H
|
||||
#define FISH_KILL_H
|
||||
|
||||
#include "common.h"
|
||||
#include "wutil.h"
|
||||
|
||||
/// Replace the specified string in the killring.
|
||||
void kill_replace(const wcstring &old, const wcstring &newv);
|
||||
|
||||
/// Add a string to the top of the killring.
|
||||
void kill_add(wcstring str);
|
||||
#include "kill.rs.h"
|
||||
|
||||
/// Rotate the killring.
|
||||
wcstring kill_yank_rotate();
|
||||
|
@ -23,7 +13,4 @@ wcstring kill_yank();
|
|||
/// Get copy of kill ring as vector of strings
|
||||
std::vector<wcstring> kill_entries();
|
||||
|
||||
/// Rust-friendly kill entries.
|
||||
wcstring_list_ffi_t kill_entries_ffi();
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue