Skip to content

Commit 8d2ad72

Browse files
authored
Merge pull request #180 from curlpipe/0.7.0
0.7.0
2 parents 6c78450 + 40cb033 commit 8d2ad72

27 files changed

+894
-445
lines changed

Cargo.lock

Lines changed: 11 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ exclude = ["cactus"]
77

88
[package]
99
name = "ox"
10-
version = "0.6.10"
10+
version = "0.7.0"
1111
edition = "2021"
1212
authors = ["Curlpipe <[email protected]>"]
1313
description = "A Rust powered text editor."
@@ -28,6 +28,7 @@ assets = [
2828
]
2929

3030
#[profile.release]
31+
#debug = true
3132
#lto = true
3233
#panic = "abort"
3334
#codegen-units = 1
@@ -38,7 +39,7 @@ base64 = "0.22.1"
3839
crossterm = "0.28.1"
3940
jargon-args = "0.2.7"
4041
kaolinite = { path = "./kaolinite" }
41-
mlua = { version = "0.9.9", features = ["lua54", "vendored"] }
42-
error_set = "0.6"
42+
mlua = { version = "0.10", features = ["lua54", "vendored"] }
43+
error_set = "0.7"
4344
shellexpand = "3.1.0"
44-
synoptic = "2.2.1"
45+
synoptic = "2.2.6"

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ cargo deb
1616
cp target/debian/*.deb target/pkgs/
1717

1818
# Build for macOS (binary)
19-
export SDKROOT=../../make/MacOSX13.3.sdk/
19+
export SDKROOT=/home/luke/dev/make/MacOSX13.3.sdk/
2020
export PATH=$PATH:~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/
2121
export CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER=rust-lld
2222
cargo zigbuild --release --target x86_64-apple-darwin

config/.oxrc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,11 @@ event_mapping = {
271271
["ctrl_w"] = function()
272272
editor:remove_word()
273273
end,
274+
-- Macros
275+
["ctrl_esc"] = function()
276+
editor:macro_record_stop()
277+
editor:display_info("Macro recorded")
278+
end,
274279
}
275280

276281
-- Define user-defined commands
@@ -303,6 +308,22 @@ commands = {
303308
editor:reload_config()
304309
editor:display_info("Configuration file reloaded")
305310
end,
311+
["macro"] = function(arguments)
312+
if arguments[1] == "record" then
313+
editor:macro_record_start()
314+
editor:display_info("Recording macro, press ctrl+esc to stop")
315+
elseif arguments[1] == "play" then
316+
local reps
317+
if arguments[2] == nil then
318+
reps = 1
319+
else
320+
reps = tonumber(arguments[2])
321+
end
322+
editor:macro_play(reps)
323+
else
324+
editor:display_error(tostring(arguments[1]) .. " is not a valid macro command")
325+
end
326+
end,
306327
}
307328

308329
-- Configure Documents --

kaolinite/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ keywords = ["unicode", "text-processing"]
1212
categories = ["text-processing"]
1313

1414
[dependencies]
15-
error_set = "0.6"
16-
regex = "1.10.6"
15+
error_set = "0.7"
16+
regex = "1"
1717
ropey = "1.6.1"
1818
unicode-width = "0.2"
1919

kaolinite/src/document/cursor.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ impl Document {
186186

187187
/// Move up by 1 page
188188
pub fn move_page_up(&mut self) {
189+
self.clear_cursors();
189190
// Set x to 0
190191
self.cursor.loc.x = 0;
191192
self.char_ptr = 0;
@@ -201,6 +202,7 @@ impl Document {
201202

202203
/// Move down by 1 page
203204
pub fn move_page_down(&mut self) {
205+
self.clear_cursors();
204206
// Set x to 0
205207
self.cursor.loc.x = 0;
206208
self.char_ptr = 0;
@@ -399,4 +401,24 @@ impl Document {
399401
pub fn cancel_selection(&mut self) {
400402
self.cursor.selection_end = self.cursor.loc;
401403
}
404+
405+
/// Create a new alternative cursor
406+
pub fn new_cursor(&mut self, loc: Loc) {
407+
if let Some(idx) = self.has_cursor(loc) {
408+
self.secondary_cursors.remove(idx);
409+
} else if self.out_of_range(loc.x, loc.y).is_ok() {
410+
self.secondary_cursors.push(loc);
411+
}
412+
}
413+
414+
/// Clear all secondary cursors
415+
pub fn clear_cursors(&mut self) {
416+
self.secondary_cursors.clear();
417+
}
418+
419+
/// Determine if there is a secondary cursor at a certain position
420+
#[must_use]
421+
pub fn has_cursor(&self, loc: Loc) -> Option<usize> {
422+
self.secondary_cursors.iter().position(|c| *c == loc)
423+
}
402424
}

kaolinite/src/document/disk.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl Document {
4242
eol: false,
4343
read_only: false,
4444
},
45+
secondary_cursors: vec![],
4546
}
4647
}
4748

@@ -77,6 +78,7 @@ impl Document {
7778
tab_width: 4,
7879
old_cursor: 0,
7980
in_redo: false,
81+
secondary_cursors: vec![],
8082
})
8183
}
8284

kaolinite/src/document/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ pub struct Document {
5050
pub in_redo: bool,
5151
/// The number of spaces a tab should be rendered as
5252
pub tab_width: usize,
53+
/// Secondary cursor (for multi-cursors)
54+
pub secondary_cursors: Vec<Loc>,
5355
}
5456

5557
impl Document {
@@ -113,6 +115,7 @@ impl Document {
113115
/// # Errors
114116
/// Returns an error if there is a problem with the specified operation.
115117
pub fn forth(&mut self, ev: Event) -> Result<()> {
118+
// Perform the event
116119
match ev {
117120
Event::Insert(loc, ch) => self.insert(&loc, &ch),
118121
Event::Delete(loc, st) => self.delete_with_tab(&loc, &st),
@@ -256,9 +259,15 @@ impl Document {
256259
// Account for double width characters
257260
idx = idx.saturating_sub(self.dbl_map.count(loc, true).unwrap_or(0));
258261
// Account for tab characters
259-
idx = idx.saturating_sub(
260-
self.tab_map.count(loc, true).unwrap_or(0) * self.tab_width.saturating_sub(1),
261-
);
262+
let tabs_behind = self.tab_map.count(loc, true).unwrap_or(0);
263+
idx = if let Some(inner_idx) = self.tab_map.inside(self.tab_width, loc.x, loc.y) {
264+
// Display index is within a tab, account for it properly
265+
let existing_tabs = tabs_behind.saturating_sub(1) * self.tab_width.saturating_sub(1);
266+
idx.saturating_sub(existing_tabs + inner_idx)
267+
} else {
268+
// Display index isn't in a tab
269+
idx.saturating_sub(tabs_behind * self.tab_width.saturating_sub(1))
270+
};
262271
idx
263272
}
264273

kaolinite/src/map.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::collections::HashMap;
44
use unicode_width::UnicodeWidthChar;
55

66
/// This is a type for making a note of the location of different characters
7+
/// `HashMap`<`y_pos`, Vec<(display, character)>>
78
type CharHashMap = HashMap<usize, Vec<(usize, usize)>>;
89

910
/// Keeps notes of specific characters within a document for the purposes of double width and
@@ -166,6 +167,18 @@ impl CharMap {
166167
}
167168
Some(ctr)
168169
}
170+
171+
/// If all character maps are of size n, then determine if x would be within one,
172+
/// and return their index inside the mapped char
173+
#[must_use]
174+
pub fn inside(&self, n: usize, x: usize, y: usize) -> Option<usize> {
175+
for (disp, _) in self.get(y)? {
176+
if ((disp + 1)..(disp + n)).contains(&x) {
177+
return Some(x.saturating_sub(*disp));
178+
}
179+
}
180+
None
181+
}
169182
}
170183

171184
/// Vector that takes two usize values

src/config/assistant.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use crossterm::execute;
88
use crossterm::style::{SetBackgroundColor as Bg, SetForegroundColor as Fg};
99
use crossterm::terminal::{Clear, ClearType};
1010
use mlua::prelude::*;
11-
use std::cell::RefCell;
1211
use std::io::{stdout, Write};
13-
use std::rc::Rc;
1412

1513
pub const TROPICAL: &str = include_str!("../../plugins/themes/tropical.lua");
1614
pub const GALAXY: &str = include_str!("../../plugins/themes/galaxy.lua");
@@ -571,14 +569,14 @@ impl Assistant {
571569
pub fn demonstrate_theme(name: &str, code: &str) -> Result<String> {
572570
// Create an environment to capture all the values
573571
let lua = Lua::new();
574-
let colors = Rc::new(RefCell::new(Colors::default()));
575-
let syntax_highlighting = Rc::new(RefCell::new(SyntaxHighlighting::default()));
572+
let colors = lua.create_userdata(Colors::default())?;
573+
let syntax_highlighting = lua.create_userdata(SyntaxHighlighting::default())?;
576574
lua.globals().set("syntax", syntax_highlighting.clone())?;
577575
lua.globals().set("colors", colors.clone())?;
578576
// Access all the values
579577
lua.load(code).exec()?;
580578
// Gather the editor colours
581-
let col = colors.borrow();
579+
let col: LuaUserDataRef<Colors> = colors.borrow()?;
582580
let editor = format!(
583581
"{}{}",
584582
Fg(col.editor_fg.to_color()?),
@@ -625,28 +623,29 @@ impl Assistant {
625623
Bg(col.info_bg.to_color()?)
626624
);
627625
// Gather syntax highlighting colours
628-
let string = Fg(syntax_highlighting.borrow().get_theme("string")?);
629-
let comment = Fg(syntax_highlighting.borrow().get_theme("comment")?);
630-
let digit = Fg(syntax_highlighting.borrow().get_theme("digit")?);
631-
let keyword = Fg(syntax_highlighting.borrow().get_theme("keyword")?);
632-
let character = Fg(syntax_highlighting.borrow().get_theme("character")?);
633-
let type_syn = Fg(syntax_highlighting.borrow().get_theme("type")?);
634-
let function = Fg(syntax_highlighting.borrow().get_theme("function")?);
635-
let macro_syn = Fg(syntax_highlighting.borrow().get_theme("macro")?);
636-
let block = Fg(syntax_highlighting.borrow().get_theme("block")?);
637-
let namespace = Fg(syntax_highlighting.borrow().get_theme("namespace")?);
638-
let header = Fg(syntax_highlighting.borrow().get_theme("header")?);
639-
let struct_syn = Fg(syntax_highlighting.borrow().get_theme("struct")?);
640-
let operator = Fg(syntax_highlighting.borrow().get_theme("operator")?);
641-
let boolean = Fg(syntax_highlighting.borrow().get_theme("boolean")?);
642-
let reference = Fg(syntax_highlighting.borrow().get_theme("reference")?);
643-
let tag = Fg(syntax_highlighting.borrow().get_theme("tag")?);
644-
let heading = Fg(syntax_highlighting.borrow().get_theme("heading")?);
645-
let link = Fg(syntax_highlighting.borrow().get_theme("link")?);
646-
let bold = Fg(syntax_highlighting.borrow().get_theme("bold")?);
647-
let italic = Fg(syntax_highlighting.borrow().get_theme("italic")?);
648-
let insertion = Fg(syntax_highlighting.borrow().get_theme("insertion")?);
649-
let deletion = Fg(syntax_highlighting.borrow().get_theme("deletion")?);
626+
let syn: LuaUserDataRef<SyntaxHighlighting> = syntax_highlighting.borrow()?;
627+
let string = Fg(syn.get_theme("string")?);
628+
let comment = Fg(syn.get_theme("comment")?);
629+
let digit = Fg(syn.get_theme("digit")?);
630+
let keyword = Fg(syn.get_theme("keyword")?);
631+
let character = Fg(syn.get_theme("character")?);
632+
let type_syn = Fg(syn.get_theme("type")?);
633+
let function = Fg(syn.get_theme("function")?);
634+
let macro_syn = Fg(syn.get_theme("macro")?);
635+
let block = Fg(syn.get_theme("block")?);
636+
let namespace = Fg(syn.get_theme("namespace")?);
637+
let header = Fg(syn.get_theme("header")?);
638+
let struct_syn = Fg(syn.get_theme("struct")?);
639+
let operator = Fg(syn.get_theme("operator")?);
640+
let boolean = Fg(syn.get_theme("boolean")?);
641+
let reference = Fg(syn.get_theme("reference")?);
642+
let tag = Fg(syn.get_theme("tag")?);
643+
let heading = Fg(syn.get_theme("heading")?);
644+
let link = Fg(syn.get_theme("link")?);
645+
let bold = Fg(syn.get_theme("bold")?);
646+
let italic = Fg(syn.get_theme("italic")?);
647+
let insertion = Fg(syn.get_theme("insertion")?);
648+
let deletion = Fg(syn.get_theme("deletion")?);
650649
// Render the preview
651650
let name = format!(" {name} ");
652651
Ok(format!("{name:─^47}

0 commit comments

Comments
 (0)