Port killring

This commit is contained in:
Clemens Wasser 2023-05-30 23:22:09 +02:00 committed by Peter Ammon
parent cfdcaf880f
commit c2f58cd312
7 changed files with 112 additions and 66 deletions

View file

@ -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",

View file

@ -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.

View file

@ -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
View 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()
}

View file

@ -42,6 +42,7 @@ mod global_safety;
mod highlight;
mod io;
mod job_group;
mod kill;
mod locale;
mod nix;
mod null_terminated_array;

View file

@ -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(); }

View file

@ -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