multi-line copy/paste, more copy/paste
fix C and D in nimbus romono
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ming-wm"
|
||||
version = "1.0.3"
|
||||
version = "1.1.0"
|
||||
repository = "https://github.com/stjet/ming-wm"
|
||||
license = "GPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 534 B |
Binary file not shown.
|
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 534 B |
@@ -15,6 +15,8 @@ Since the windows and the window manager are separate binaries, they need some w
|
||||
|
||||
The serialization format is in `ming-wm-lib/src/serialize.rs`. Make sure any newlines (`\n`) in strings are removed before/after serializations. When doing IPC, the window manager assumes the response to a query is one line, so if a newline is present, it will fail to parse the response.
|
||||
|
||||
> In the case of `WindowMessage::Request(WindowManagerRequest::ClipboardCopy(<copy_string>))`, windows should convert any `\n` into `𐘂` when copying to clipboard and vice versa when pasting, in order to allow for multi-line clipboard contents.
|
||||
|
||||
## Hello, World!
|
||||
|
||||
A minimal example using `ming-wm-lib`.
|
||||
|
||||
@@ -14,6 +14,8 @@ Type to write commands, backspace to delete last character, and enter to run com
|
||||
|
||||
Tab completion is supported for the `<dir>` and `<dir / playlist file>` arguments.
|
||||
|
||||
The copy shortcut will copy the currently playing song's file name, if there is a currently playing song.
|
||||
|
||||
## Playlists
|
||||
|
||||
Example playlist file:
|
||||
|
||||
@@ -25,7 +25,7 @@ To get sudo to read from stdin, the `-S` option will need to be used (eg, `sudo
|
||||
|
||||
## Copy / Paste
|
||||
|
||||
This window-like supports the paste [shortcut](../system/shortcuts.md) (`Alt+P`) if in INPUT or STDIN mode.
|
||||
This window-like supports the paste [shortcut](../system/shortcuts.md) (`Alt+P`) if in INPUT or STDIN mode. The copy shortcut will copy the output of the last ran command.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ming-wm-lib"
|
||||
version = "0.1.7"
|
||||
version = "0.2.0"
|
||||
repository = "https://github.com/stjet/ming-wm"
|
||||
description = "library for building windows for ming-wm in rust"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -58,9 +58,11 @@ pub fn listen(mut window_like: impl WindowLike) {
|
||||
let arg = &parts.collect::<Vec<&str>>().join(" ");
|
||||
let output = match method {
|
||||
"handle_message" => {
|
||||
//newlines allowed for ClipboardCopy, but represented by the Linear A char
|
||||
window_like.handle_message(WindowMessage::deserialize(arg).unwrap()).serialize().to_string()
|
||||
},
|
||||
"draw" => {
|
||||
//newlines never allowed
|
||||
window_like.draw(&ThemeInfo::deserialize(arg).unwrap()).serialize().replace("\n", "").to_string()
|
||||
},
|
||||
"title" => {
|
||||
|
||||
@@ -146,7 +146,7 @@ impl Serializable for WindowMessageResponse {
|
||||
WindowMessageResponse::Request(req) => {
|
||||
let req = match req {
|
||||
WindowManagerRequest::OpenWindow(name) => format!("OpenWindow/{}", name),
|
||||
WindowManagerRequest::ClipboardCopy(name) => format!("ClipboardCopy/{}", name),
|
||||
WindowManagerRequest::ClipboardCopy(copy_string) => format!("ClipboardCopy/{}", copy_string.replace("\n", "𐘂")), //serialised output must be 1 line
|
||||
WindowManagerRequest::CloseStartMenu => "CloseStartMenu".to_string(),
|
||||
WindowManagerRequest::Unlock => "Unlock".to_string(),
|
||||
WindowManagerRequest::Lock => "Lock".to_string(),
|
||||
@@ -646,7 +646,7 @@ impl Serializable for WindowMessage {
|
||||
"FullscreenWindow" => Some(ShortcutType::FullscreenWindow),
|
||||
"HalfWidthWindow" => Some(ShortcutType::HalfWidthWindow),
|
||||
"ClipboardCopy" => Some(ShortcutType::ClipboardCopy),
|
||||
"ClipboardPaste" => Some(ShortcutType::ClipboardPaste(get_rest_of_split(&mut parts, Some("/")))),
|
||||
"ClipboardPaste" => Some(ShortcutType::ClipboardPaste(get_rest_of_split(&mut parts, Some("/")).replace("𐘂", "\n"))),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(shortcut) = shortcut {
|
||||
|
||||
@@ -14,7 +14,7 @@ use mp4ameta;
|
||||
use metaflac;
|
||||
|
||||
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType };
|
||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||
use ming_wm_lib::themes::ThemeInfo;
|
||||
use ming_wm_lib::utils::{ concat_paths, get_all_files, path_autocomplete, format_seconds, Substring };
|
||||
@@ -79,7 +79,6 @@ pub struct AudioPlayer {
|
||||
|
||||
impl WindowLike for AudioPlayer {
|
||||
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse {
|
||||
//
|
||||
match message {
|
||||
WindowMessage::Init(dimensions) => {
|
||||
self.dimensions = dimensions;
|
||||
@@ -116,6 +115,27 @@ impl WindowLike for AudioPlayer {
|
||||
}
|
||||
WindowMessageResponse::JustRedraw
|
||||
},
|
||||
WindowMessage::Shortcut(shortcut) => {
|
||||
match shortcut {
|
||||
ShortcutType::ClipboardPaste(paste_string) => {
|
||||
self.command += &paste_string.replace("\n", "");
|
||||
WindowMessageResponse::JustRedraw
|
||||
},
|
||||
ShortcutType::ClipboardCopy => {
|
||||
let internal_locked = self.internal.lock().unwrap();
|
||||
let sink_len = internal_locked.sink.len();
|
||||
if sink_len > 0 {
|
||||
let queue = &internal_locked.queue;
|
||||
let current = &queue[queue.len() - sink_len];
|
||||
let current_name = current.0.file_name().unwrap().to_string_lossy().into_owned();
|
||||
WindowMessageResponse::Request(WindowManagerRequest::ClipboardCopy(current_name))
|
||||
} else {
|
||||
WindowMessageResponse::DoNothing
|
||||
}
|
||||
},
|
||||
_ => WindowMessageResponse::DoNothing,
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
WindowMessageResponse::DoNothing
|
||||
},
|
||||
|
||||
@@ -457,11 +457,21 @@ impl WindowLike for Malvim {
|
||||
ShortcutType::ClipboardPaste(copy_string) => {
|
||||
if self.mode == Mode::Insert {
|
||||
let current_file = &mut self.files[self.current_file_index];
|
||||
let line = ¤t_file.content[current_file.line_pos];
|
||||
current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + ©_string + line.substring(current_file.cursor_pos, line.chars().count());
|
||||
current_file.cursor_pos += copy_string.len();
|
||||
for (i, cs) in copy_string.split("\n").enumerate() {
|
||||
if i == 0 {
|
||||
//modify current line
|
||||
let line = ¤t_file.content[current_file.line_pos];
|
||||
current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &cs + line.substring(current_file.cursor_pos, line.chars().count());
|
||||
current_file.cursor_pos += copy_string.len();
|
||||
} else {
|
||||
//insert a new line
|
||||
current_file.content.insert(current_file.line_pos + 1, cs.to_string());
|
||||
current_file.line_pos += 1;
|
||||
current_file.cursor_pos = cs.chars().count();
|
||||
}
|
||||
}
|
||||
self.calc_top_line_pos();
|
||||
self.calc_current(); //too over zealous but whatever
|
||||
self.calc_current();
|
||||
self.files[self.current_file_index].changed = true;
|
||||
WindowMessageResponse::JustRedraw
|
||||
} else {
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::fmt;
|
||||
use pty_process::blocking;
|
||||
|
||||
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, ShortcutType };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType };
|
||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||
use ming_wm_lib::themes::ThemeInfo;
|
||||
use ming_wm_lib::utils::{ concat_paths, path_autocomplete, Substring };
|
||||
@@ -46,6 +46,11 @@ fn strip_ansi_escape_codes(line: String) -> String {
|
||||
new_line
|
||||
}
|
||||
|
||||
fn bytes_to_string(bytes: Vec<u8>) -> String {
|
||||
let bytes_len = bytes.len();
|
||||
String::from_utf8(bytes).unwrap_or("?".repeat(bytes_len))
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
enum Mode {
|
||||
#[default]
|
||||
@@ -78,6 +83,7 @@ pub struct Terminal {
|
||||
current_path: String,
|
||||
running_process: Option<Child>,
|
||||
process_current_line: Vec<u8>, //bytes of line
|
||||
output: String, //current or previous running output of command
|
||||
pty_outerr_rx: Option<Receiver<u8>>,
|
||||
pty_in_tx: Option<Sender<String>>,
|
||||
history: Vec<String>,
|
||||
@@ -116,6 +122,7 @@ impl WindowLike for Terminal {
|
||||
self.history_index = None;
|
||||
self.mode = self.process_command();
|
||||
self.current_input = String::new();
|
||||
self.output = String::new();
|
||||
} else if key_press.key == '\t' { //tab
|
||||
//autocomplete assuming it's a file system path
|
||||
//...mostly working
|
||||
@@ -144,8 +151,10 @@ impl WindowLike for Terminal {
|
||||
loop {
|
||||
if let Ok(ci) = self.pty_outerr_rx.as_mut().unwrap().recv_timeout(Duration::from_millis(5)) {
|
||||
if char::from(ci) == '\n' {
|
||||
let pcl_len = self.process_current_line.len();
|
||||
self.lines.push(strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))));
|
||||
let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone()));
|
||||
self.output += &append_line;
|
||||
self.output += "\n";
|
||||
self.lines.push(append_line);
|
||||
self.process_current_line = Vec::new();
|
||||
} else if char::from(ci) == '\r' {
|
||||
//for now, ignore
|
||||
@@ -166,7 +175,14 @@ impl WindowLike for Terminal {
|
||||
//process exited
|
||||
self.pty_outerr_rx = None;
|
||||
self.mode = Mode::Input;
|
||||
self.process_current_line = Vec::new();
|
||||
if self.process_current_line.len() > 0 {
|
||||
//add to lines
|
||||
let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone()));
|
||||
self.output += &append_line;
|
||||
self.lines.push(append_line);
|
||||
//only need to reset if not empty
|
||||
self.process_current_line = Vec::new();
|
||||
}
|
||||
changed = true;
|
||||
} else {
|
||||
if key_press.key == 'i' {
|
||||
@@ -187,8 +203,9 @@ impl WindowLike for Terminal {
|
||||
} else if key_press.is_enter() {
|
||||
let _ = self.pty_in_tx.as_mut().unwrap().send(self.current_stdin_input.clone());
|
||||
self.mode = Mode::Running;
|
||||
let pcl_len = self.process_current_line.len();
|
||||
self.lines.push(strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))) + &self.current_stdin_input);
|
||||
let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone()) + &self.current_stdin_input);
|
||||
self.output += &append_line;
|
||||
self.lines.push(append_line);
|
||||
self.current_stdin_input = String::new();
|
||||
self.process_current_line = Vec::new();
|
||||
} else if key_press.is_backspace() {
|
||||
@@ -210,6 +227,12 @@ impl WindowLike for Terminal {
|
||||
//kills and running_process is now None
|
||||
let _ = self.running_process.take().unwrap().kill();
|
||||
self.mode = Mode::Input;
|
||||
if self.process_current_line.len() > 0 {
|
||||
let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone()));
|
||||
self.output += &append_line;
|
||||
self.lines.push(append_line);
|
||||
self.process_current_line = Vec::new();
|
||||
}
|
||||
WindowMessageResponse::JustRedraw
|
||||
} else if self.mode == Mode::Input && (key_press.key == 'p' || key_press.key == 'n') {
|
||||
//only the last command is saved unlike other terminals. good enough for me
|
||||
@@ -231,6 +254,7 @@ impl WindowLike for Terminal {
|
||||
},
|
||||
WindowMessage::Shortcut(shortcut) => {
|
||||
match shortcut {
|
||||
ShortcutType::ClipboardCopy => WindowMessageResponse::Request(WindowManagerRequest::ClipboardCopy(self.output.clone())),
|
||||
ShortcutType::ClipboardPaste(copy_string) => {
|
||||
if self.mode == Mode::Input || self.mode == Mode::Stdin {
|
||||
if self.mode == Mode::Input {
|
||||
@@ -381,8 +405,7 @@ impl Terminal {
|
||||
//must_add_current_line will be false
|
||||
"$ ".to_string() + &self.current_input + "█"
|
||||
} else {
|
||||
let pcl_len = self.process_current_line.len();
|
||||
strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))) + &self.current_stdin_input.clone() + "█"
|
||||
strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone()) + &self.current_stdin_input.clone() + "█")
|
||||
}
|
||||
} else {
|
||||
self.lines[line_num].clone()
|
||||
|
||||
Reference in New Issue
Block a user