-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
359 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ examples/mimeout* | |
build | ||
.ccls-cache | ||
docs/playground/mime.* | ||
target | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
name = "mime-rs" | ||
description = "A text processing framework, inspired by Emacs lisp and keyboard macros." | ||
version = "0.3.0" | ||
edition = "2021" | ||
repository = "https://github.com/shsms/mime" | ||
license = "GPL-3.0" | ||
keywords = ["scripting", "text-processing"] | ||
categories = ["text-processing"] | ||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[lib] | ||
name = "mime" | ||
path = "mime-rs/lib.rs" | ||
|
||
[dependencies] | ||
cxx = "1.0" | ||
|
||
[build-dependencies] | ||
cxx-build = "1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
fn main() { | ||
println!("cargo:rerun-if-changed=src/ffi.rs"); | ||
|
||
cxx_build::bridge("mime-rs/ffi.rs") | ||
.includes(["c++/vendor/immer", "c++/include"]) | ||
.file("c++/src/lib/mime.cc") | ||
.warnings(false) | ||
.flag_if_supported("-std=c++17") | ||
.opt_level(3) | ||
.compile("mime"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#[cxx::bridge(namespace = "mime")] | ||
pub(crate) mod cpp { | ||
|
||
unsafe extern "C++" { | ||
include!("mime/mime.hh"); | ||
|
||
type text; | ||
type buffer; | ||
|
||
fn new_buffer() -> UniquePtr<buffer>; | ||
fn open_buffer(name: &CxxString) -> UniquePtr<buffer>; | ||
|
||
fn empty(self: &buffer) -> bool; | ||
fn size(self: &buffer) -> usize; | ||
fn narrowed(self: &buffer) -> bool; | ||
|
||
fn save_as(self: &buffer, name: &CxxString); | ||
|
||
fn set_mark(self: Pin<&mut buffer>); | ||
fn get_mark(self: &buffer) -> i64; | ||
|
||
fn get_contents_box(self: &buffer) -> UniquePtr<text>; | ||
|
||
fn find(self: Pin<&mut buffer>, t: &CxxString) -> i64; | ||
// fn find_text(self: Pin<&mut buffer>, t: &text) -> i64; | ||
|
||
fn rfind(self: Pin<&mut buffer>, t: &CxxString) -> i64; | ||
// fn rfind_text(self: Pin<&mut buffer>, t: &text) -> i64; | ||
|
||
fn replace(self: Pin<&mut buffer>, from: &CxxString, to: &CxxString, n: usize) -> i32; | ||
// fn replace_all(self: Pin<&mut buffer>, from: &CxxString, to: &CxxString) -> i32; | ||
|
||
fn copy_box(self: &buffer) -> UniquePtr<text>; | ||
fn cut_box(self: Pin<&mut buffer>) -> UniquePtr<text>; | ||
|
||
fn paste(self: Pin<&mut buffer>, t: &CxxString); | ||
fn paste_text(self: Pin<&mut buffer>, t: &text); | ||
|
||
fn erase_region(self: Pin<&mut buffer>); | ||
fn clear(self: Pin<&mut buffer>); | ||
|
||
fn del_backward(self: Pin<&mut buffer>, n: usize) -> usize; | ||
fn del_forward(self: Pin<&mut buffer>, n: usize) -> usize; | ||
|
||
fn new_cursor(self: Pin<&mut buffer>) -> usize; | ||
fn use_cursor(self: Pin<&mut buffer>, c: usize); | ||
fn get_pos(self: &buffer) -> usize; | ||
fn goto_pos(self: Pin<&mut buffer>, pos: i64) -> bool; | ||
|
||
fn forward(self: Pin<&mut buffer>, n: usize) -> usize; | ||
fn backward(self: Pin<&mut buffer>, n: usize) -> usize; | ||
fn next_line(self: Pin<&mut buffer>, n: usize) -> usize; | ||
fn prev_line(self: Pin<&mut buffer>, n: usize) -> usize; | ||
|
||
fn start_of_buffer(self: Pin<&mut buffer>); | ||
fn end_of_buffer(self: Pin<&mut buffer>); | ||
fn start_of_line(self: Pin<&mut buffer>); | ||
fn end_of_line(self: Pin<&mut buffer>); | ||
|
||
fn start_of_block(self: Pin<&mut buffer>) -> bool; | ||
fn end_of_block(self: Pin<&mut buffer>) -> bool; | ||
|
||
fn narrow_to_block(self: Pin<&mut buffer>) -> bool; | ||
fn narrow_to_region(self: Pin<&mut buffer>) -> bool; | ||
fn widen(self: Pin<&mut buffer>); | ||
|
||
fn text_to_string(t: &text) -> UniquePtr<CxxString>; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
mod ffi; | ||
|
||
use cxx::{let_cxx_string, UniquePtr}; | ||
use ffi::cpp; | ||
use std::{cell::RefCell, fmt::Display, rc::Rc}; | ||
|
||
pub enum Text { | ||
Text(UniquePtr<cpp::text>), | ||
Str(String), | ||
} | ||
|
||
impl Display for Text { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match self { | ||
Text::Text(t) => f.write_str(&cpp::text_to_string(t).to_string()), | ||
Text::Str(t) => f.write_str(&t), | ||
} | ||
} | ||
} | ||
|
||
impl From<String> for Text { | ||
fn from(value: String) -> Self { | ||
Self::Str(value) | ||
} | ||
} | ||
|
||
impl From<&str> for Text { | ||
fn from(value: &str) -> Self { | ||
Self::Str(value.to_string()) | ||
} | ||
} | ||
|
||
pub struct Window { | ||
buffer: Rc<RefCell<UniquePtr<cpp::buffer>>>, | ||
cursor: usize, | ||
} | ||
|
||
impl Clone for Window { | ||
/// Returns a new window for the same buffer, effectively adding a new | ||
/// cursor to the existing buffer. | ||
fn clone(&self) -> Self { | ||
let buffer = self.buffer.clone(); | ||
let cursor = buffer.borrow_mut().as_mut().unwrap().new_cursor(); | ||
Self { buffer, cursor } | ||
} | ||
} | ||
|
||
impl Window { | ||
pub fn new() -> Self { | ||
let buffer = Rc::new(RefCell::new(cpp::new_buffer())); | ||
let cursor = buffer.borrow_mut().as_mut().unwrap().new_cursor(); | ||
Self { buffer, cursor } | ||
} | ||
|
||
pub fn open(filename: &str) -> Self { | ||
let_cxx_string!(filename = filename); | ||
let buffer = Rc::new(RefCell::new(cpp::open_buffer(&filename))); | ||
let cursor = buffer.borrow_mut().as_mut().unwrap().new_cursor(); | ||
Self { buffer, cursor } | ||
} | ||
|
||
pub fn empty(&self) -> bool { | ||
self.buffer.borrow().empty() | ||
} | ||
|
||
pub fn size(&self) -> usize { | ||
self.buffer.borrow().size() | ||
} | ||
|
||
pub fn narrowed(&self) -> bool { | ||
self.update_cursor(); | ||
self.buffer.borrow().narrowed() | ||
} | ||
|
||
pub fn save_as(&self, filename: &str) { | ||
let_cxx_string!(filename = filename); | ||
self.buffer.borrow().save_as(&filename); | ||
} | ||
|
||
pub fn set_mark(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().set_mark(); | ||
} | ||
|
||
// TODO: add bookmark interface | ||
pub fn get_mark(&self) -> Option<i64> { | ||
self.update_cursor(); | ||
let pos = self.buffer.borrow().get_mark(); | ||
(pos >= 0).then(|| pos) | ||
} | ||
|
||
pub fn get_contents(&self) -> Text { | ||
Text::Text(self.buffer.borrow().get_contents_box()) | ||
} | ||
|
||
pub fn find(&self, text: &str) -> Option<i64> { | ||
self.update_cursor(); | ||
let_cxx_string!(text = text); | ||
let pos = self.buffer.borrow_mut().as_mut().unwrap().find(&text); | ||
(pos >= 0).then(|| pos) | ||
} | ||
|
||
pub fn rfind(&self, text: &str) -> Option<i64> { | ||
self.update_cursor(); | ||
let_cxx_string!(text = text); | ||
let pos = self.buffer.borrow_mut().as_mut().unwrap().rfind(&text); | ||
(pos >= 0).then(|| pos) | ||
} | ||
|
||
pub fn replace(&self, from: &str, to: &str, n: usize) -> i32 { | ||
self.update_cursor(); | ||
let_cxx_string!(from = from); | ||
let_cxx_string!(to = to); | ||
self.buffer | ||
.borrow_mut() | ||
.as_mut() | ||
.unwrap() | ||
.replace(&from, &to, n) | ||
} | ||
|
||
pub fn copy(&self) -> Text { | ||
self.update_cursor(); | ||
Text::Text(self.buffer.borrow().copy_box()) | ||
} | ||
|
||
pub fn cut(&self) -> Text { | ||
self.update_cursor(); | ||
Text::Text(self.buffer.borrow_mut().as_mut().unwrap().cut_box()) | ||
} | ||
|
||
pub fn paste<T: Into<Text>>(&self, text: T) { | ||
self.update_cursor(); | ||
match text.into() { | ||
Text::Text(ref text) => self.buffer.borrow_mut().as_mut().unwrap().paste_text(text), | ||
Text::Str(ref text) => { | ||
let_cxx_string!(text = text); | ||
self.buffer.borrow_mut().as_mut().unwrap().paste(&text) | ||
} | ||
} | ||
} | ||
|
||
pub fn erase_region(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().erase_region() | ||
} | ||
|
||
pub fn clear(&self) { | ||
self.buffer.borrow_mut().as_mut().unwrap().clear() | ||
} | ||
|
||
pub fn get_pos(&self) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow().get_pos() | ||
} | ||
|
||
pub fn goto_pos(&self, pos: i64) -> bool { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().goto_pos(pos) | ||
} | ||
|
||
pub fn del_backward(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().del_backward(n) | ||
} | ||
|
||
pub fn del_forward(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().del_forward(n) | ||
} | ||
|
||
pub fn backward(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().backward(n) | ||
} | ||
|
||
pub fn forward(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().forward(n) | ||
} | ||
|
||
pub fn prev_line(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().prev_line(n) | ||
} | ||
|
||
pub fn next_line(&self, n: usize) -> usize { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().next_line(n) | ||
} | ||
|
||
pub fn start_of_buffer(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().start_of_buffer() | ||
} | ||
|
||
pub fn end_of_buffer(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().end_of_buffer() | ||
} | ||
|
||
pub fn start_of_line(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().start_of_line() | ||
} | ||
|
||
pub fn end_of_line(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().end_of_line() | ||
} | ||
|
||
pub fn start_of_block(&self) -> bool { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().start_of_block() | ||
} | ||
|
||
pub fn end_of_block(&self) -> bool { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().end_of_block() | ||
} | ||
|
||
pub fn narrow_to_block(&self) -> bool { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().narrow_to_block() | ||
} | ||
|
||
pub fn narrow_to_region(&self) -> bool { | ||
self.update_cursor(); | ||
self.buffer | ||
.borrow_mut() | ||
.as_mut() | ||
.unwrap() | ||
.narrow_to_region() | ||
} | ||
|
||
pub fn widen(&self) { | ||
self.update_cursor(); | ||
self.buffer.borrow_mut().as_mut().unwrap().widen() | ||
} | ||
} | ||
|
||
impl Default for Window { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
// Private functions | ||
impl Window { | ||
fn update_cursor(&self) { | ||
self.buffer | ||
.borrow_mut() | ||
.as_mut() | ||
.unwrap() | ||
.use_cursor(self.cursor); | ||
} | ||
} |