Skip to content

Commit

Permalink
Merge pull request #170 from curlpipe/0.6.8
Browse files Browse the repository at this point in the history
0.6.8
  • Loading branch information
curlpipe authored Oct 23, 2024
2 parents bb2192a + 6bdf62a commit 610eab2
Show file tree
Hide file tree
Showing 24 changed files with 1,439 additions and 161 deletions.
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exclude = ["cactus"]

[package]
name = "ox"
version = "0.6.7"
version = "0.6.8"
edition = "2021"
authors = ["Curlpipe <[email protected]>"]
description = "A Rust powered text editor."
Expand Down Expand Up @@ -41,4 +41,4 @@ kaolinite = { path = "./kaolinite" }
mlua = { version = "0.9.9", features = ["lua54", "vendored"] }
quick-error = "2.0.1"
shellexpand = "3.1.0"
synoptic = "2"
synoptic = "2.2.1"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ It is mainly used on linux systems, but macOS and Windows users (via WSL) are fr
- :electric_plug: Plug-In system where you can write your own plug-ins or integrate other people's
- :wrench: A wide number of options for configuration with everything from colours to the status line to syntax highlighting being open to customisation
- :moon: Ox uses Lua as a configuration language for familiarity when scripting and configuring
- 🤝 A configuration assistant to quickly get Ox set up for you from the get-go

### Out of the box features

Expand Down
52 changes: 19 additions & 33 deletions config/.oxrc
Original file line number Diff line number Diff line change
Expand Up @@ -117,47 +117,32 @@ event_mapping = {
end,
["alt_up"] = function()
-- current line information
line = editor:get_line()
y = editor.cursor.y
local line = editor:get_line()
local cursor = editor.cursor
-- insert a new line
editor:insert_line_at(line, y - 1)
editor:insert_line_at(line, cursor.y - 1)
-- delete old copy and reposition cursor
editor:remove_line_at(y + 1)
editor:move_up()
editor:remove_line_at(cursor.y + 1)
-- restore cursor position
editor:move_to(cursor.x, cursor.y - 1)
-- correct indentation level
autoindent:fix_indent()
end,
["alt_down"] = function()
-- current line information
line = editor:get_line()
y = editor.cursor.y
local line = editor:get_line()
local cursor = editor.cursor
-- insert a new line
editor:insert_line_at(line, y + 2)
editor:insert_line_at(line, cursor.y + 2)
-- delete old copy and reposition cursor
editor:remove_line_at(y)
editor:move_down()
editor:remove_line_at(cursor.y)
-- restore cursor position
editor:move_to(cursor.x, cursor.y + 1)
-- correct indentation level
autoindent:fix_indent()
end,
["ctrl_w"] = function()
y = editor.cursor.y
x = editor.cursor.x
if editor:get_character() == " " then
start = 0
else
start = 1
end
editor:move_previous_word()
new_x = editor.cursor.x
diff = x - new_x
if editor.cursor.y == y then
-- Cursor on the same line
for i = start, diff do
editor:remove_at(new_x, y)
end
else
-- Cursor has passed up onto the previous line
end
editor:remove_word()
end,
}

Expand Down Expand Up @@ -232,17 +217,18 @@ line_numbers.padding_right = 1

-- Configure Mouse Behaviour --
terminal.mouse_enabled = true
terminal.scroll_amount = 1
terminal.scroll_amount = 2

-- Configure Tab Line --
tab_line.enabled = true
tab_line.format = " {file_name}{modified} "

-- Configure Status Line --
status_line:add_part(" {file_name}{modified} │ {file_type} │") -- The left side of the status line
status_line:add_part("│ {cursor_y} / {line_count} {cursor_x} ") -- The right side of the status line

status_line.alignment = "between" -- This will put a space between the left and right sides
status_line.parts = {
" {file_name}{modified} │ {file_type} │", -- The left side of the status line
"│ {cursor_y} / {line_count} {cursor_x} ", -- The right side of the status line
}
status_line.alignment = "between" -- This will put a space between the parts (left and right sides)

-- Configure Greeting Message --
greeting_message.enabled = true
Expand Down
175 changes: 153 additions & 22 deletions kaolinite/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,30 +662,74 @@ impl Document {
self.cancel_selection();
}

/// Find the word boundaries
pub fn word_boundaries(&mut self, line: &str) -> Vec<(usize, usize)> {
let re = r"(\s{2,}|[A-Za-z0-9_]+|\.)";
let mut searcher = Searcher::new(re);
let starts: Vec<Match> = searcher.lfinds(line);
let mut ends: Vec<Match> = starts.clone();
ends.iter_mut()
.for_each(|m| m.loc.x += m.text.chars().count());
let starts: Vec<usize> = starts.iter().map(|m| m.loc.x).collect();
let ends: Vec<usize> = ends.iter().map(|m| m.loc.x).collect();
starts.into_iter().zip(ends).collect()
}

/// Find the current state of the cursor in relation to words
pub fn cursor_word_state(&mut self, words: &[(usize, usize)], x: usize) -> WordState {
let in_word = words
.iter()
.position(|(start, end)| *start <= x && x <= *end);
if let Some(idx) = in_word {
let (word_start, word_end) = words[idx];
if x == word_end {
WordState::AtEnd(idx)
} else if x == word_start {
WordState::AtStart(idx)
} else {
WordState::InCenter(idx)
}
} else {
WordState::Out
}
}

/// Moves to the previous word in the document
pub fn move_prev_word(&mut self) -> Status {
let Loc { x, y } = self.char_loc();
// Handle case where we're at the beginning of the line
if x == 0 && y != 0 {
return Status::StartOfLine;
}
let re = format!("(\t| {{{}}}|^|\\W|$| )", self.tab_width);
let mut searcher = Searcher::new(&re);
let line = self
.line(y)
.unwrap_or_default()
.chars()
.take(x)
.collect::<String>();
let mut matches = searcher.rfinds(&line);
if let Some(mtch) = matches.first() {
if mtch.loc.x == x {
matches.remove(0);
// Find where all the words are
let line = self.line(y).unwrap_or_default();
let words = self.word_boundaries(&line);
let state = self.cursor_word_state(&words, x);
// Work out where to move to
let new_x = match state {
// Go to start of line if at beginning
WordState::AtEnd(0) | WordState::InCenter(0) | WordState::AtStart(0) => 0,
// Cursor is at the middle / end of a word, move to previous end
WordState::AtEnd(idx) | WordState::InCenter(idx) => words[idx.saturating_sub(1)].1,
WordState::AtStart(idx) => words[idx.saturating_sub(1)].0,
WordState::Out => {
// Cursor is not touching any words, find previous end
let mut shift_back = x;
while let WordState::Out = self.cursor_word_state(&words, shift_back) {
shift_back = shift_back.saturating_sub(1);
if shift_back == 0 {
break;
}
}
match self.cursor_word_state(&words, shift_back) {
WordState::AtEnd(idx) => words[idx].1,
_ => 0,
}
}
}
if let Some(mtch) = matches.first_mut() {
mtch.loc.y = self.loc().y;
self.move_to(&mtch.loc);
}
};
// Perform the move
self.move_to_x(new_x);
// Clean up
self.old_cursor = self.loc().x;
Status::None
}
Expand All @@ -694,18 +738,97 @@ impl Document {
pub fn move_next_word(&mut self) -> Status {
let Loc { x, y } = self.char_loc();
let line = self.line(y).unwrap_or_default();
// Handle case where we're at the end of the line
if x == line.chars().count() && y != self.len_lines() {
return Status::EndOfLine;
}
let re = format!("(\t| {{{}}}|\\W|$|^ +| )", self.tab_width);
if let Some(mut mtch) = self.next_match(&re, 0) {
mtch.loc.x += mtch.text.chars().count();
self.move_to(&mtch.loc);
}
// Find and move to the next word
let line = self.line(y).unwrap_or_default();
let words = self.word_boundaries(&line);
let state = self.cursor_word_state(&words, x);
// Work out where to move to
let new_x = match state {
// Cursor is at the middle / end of a word, move to next end
WordState::AtEnd(idx) | WordState::InCenter(idx) => {
if let Some(word) = words.get(idx + 1) {
word.1
} else {
// No next word exists, just go to end of line
line.chars().count()
}
}
WordState::AtStart(idx) => {
// Cursor is at the start of a word, move to next start
if let Some(word) = words.get(idx + 1) {
word.0
} else {
// No next word exists, just go to end of line
line.chars().count()
}
}
WordState::Out => {
// Cursor is not touching any words, find next start
let mut shift_forward = x;
while let WordState::Out = self.cursor_word_state(&words, shift_forward) {
shift_forward += 1;
if shift_forward >= line.chars().count() {
break;
}
}
match self.cursor_word_state(&words, shift_forward) {
WordState::AtStart(idx) => words[idx].0,
_ => line.chars().count(),
}
}
};
// Perform the move
self.move_to_x(new_x);
// Clean up
self.old_cursor = self.loc().x;
Status::None
}

/// Function to delete a word at a certain location
/// # Errors
/// Errors if out of range
pub fn delete_word(&mut self) -> Result<()> {
let Loc { x, y } = self.char_loc();
let line = self.line(y).unwrap_or_default();
let words = self.word_boundaries(&line);
let state = self.cursor_word_state(&words, x);
let delete_upto = match state {
WordState::InCenter(idx) | WordState::AtEnd(idx) => {
// Delete back to start of this word
words[idx].0
}
WordState::AtStart(0) => 0,
WordState::AtStart(idx) => {
// Delete back to start of the previous word
words[idx.saturating_sub(1)].0
}
WordState::Out => {
// Delete back to the end of the previous word
let mut shift_back = x;
while let WordState::Out = self.cursor_word_state(&words, shift_back) {
shift_back = shift_back.saturating_sub(1);
if shift_back == 0 {
break;
}
}
let char = line.chars().nth(shift_back);
let state = self.cursor_word_state(&words, shift_back);
match (char, state) {
// Shift to start of previous word if there is a space
(Some(' '), WordState::AtEnd(idx)) => words[idx].0,
// Shift to end of previous word if there is not a space
(_, WordState::AtEnd(idx)) => words[idx].1,
_ => 0,
}
}
};
self.delete(delete_upto..=x, y)
}

/// Function to search the document to find the next occurance of a regex
pub fn next_match(&mut self, regex: &str, inc: usize) -> Option<Match> {
// Prepare
Expand Down Expand Up @@ -1204,3 +1327,11 @@ pub struct Cursor {
pub loc: Loc,
pub selection_end: Loc,
}

/// State of a word
pub enum WordState {
AtStart(usize),
AtEnd(usize),
InCenter(usize),
Out,
}
2 changes: 1 addition & 1 deletion kaolinite/src/searching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::utils::Loc;
use regex::Regex;

/// Stores information about a match in a document
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Match {
pub loc: Loc,
pub text: String,
Expand Down
Loading

0 comments on commit 610eab2

Please sign in to comment.