Skip to content
Merged

0.6.6 #168

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion 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.5"
version = "0.6.6"
edition = "2021"
authors = ["Curlpipe <11898833+curlpipe@users.noreply.github.com>"]
description = "A Rust powered text editor."
Expand Down
4 changes: 2 additions & 2 deletions config/.oxrc
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ commands = {
end
end,
["filetype"] = function(arguments)
ext = arguments[1]
editor:set_file_type(ext)
local file_type_name = arguments[1]
editor:set_file_type(file_type_name)
end,
["reload"] = function(arguments)
editor:reload_config()
Expand Down
41 changes: 37 additions & 4 deletions kaolinite/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,10 +767,6 @@ impl Document {
/// Function to select to a specific x position
pub fn select_to_x(&mut self, x: usize) {
let line = self.line(self.loc().y).unwrap_or_default();
// If we're already at this x coordinate, just exit
if self.char_ptr == x {
return;
}
// If the move position is out of bounds, move to the end of the line
if line.chars().count() < x {
let line = self.line(self.loc().y).unwrap_or_default();
Expand Down Expand Up @@ -810,6 +806,43 @@ impl Document {
self.load_to(self.offset.y + self.size.h);
}

/// Select a word at a location
pub fn select_word_at(&mut self, loc: &Loc) {
let y = loc.y;
let x = self.character_idx(loc);
let re = format!("(\t| {{{}}}|^|\\W| )", self.tab_width);
let start = if let Some(mut mtch) = self.prev_match(&re) {
let len = mtch.text.chars().count();
let same = mtch.loc.x + len == x;
if !same {
mtch.loc.x += len;
}
self.move_to(&mtch.loc);
if same && self.loc().x != 0 {
self.move_prev_word();
}
mtch.loc.x
} else {
0
};
let re = format!("(\t| {{{}}}|\\W|$|^ +| )", self.tab_width);
let end = if let Some(mtch) = self.next_match(&re, 0) {
mtch.loc.x
} else {
self.line(y).unwrap_or_default().chars().count()
};
self.move_to(&Loc { x: start, y });
self.select_to(&Loc { x: end, y });
self.old_cursor = self.loc().x;
}

/// Select a line at a location
pub fn select_line_at(&mut self, y: usize) {
let len = self.line(y).unwrap_or_default().chars().count();
self.move_to(&Loc { x: 0, y });
self.select_to(&Loc { x: len, y });
}

/// Brings the cursor into the viewport so it can be seen
pub fn bring_cursor_in_viewport(&mut self) {
if self.offset.y > self.cursor.loc.y {
Expand Down
21 changes: 21 additions & 0 deletions kaolinite/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,27 @@ fn document_selection() {
assert!(!doc.is_loc_selected(Loc { x: 0, y: 0 }));
assert!(!doc.is_loc_selected(Loc { x: 2, y: 0 }));
assert!(!doc.is_loc_selected(Loc { x: 3, y: 0 }));
doc.select_line_at(1);
assert_eq!(
doc.selection_loc_bound(),
(Loc { x: 0, y: 1 }, Loc { x: 31, y: 1 })
);
doc.remove_selection();
doc.exe(Event::InsertLine(1, "hello there world".to_string()));
doc.exe(Event::InsertLine(2, "hello".to_string()));
doc.move_to(&Loc { x: 8, y: 1 });
doc.select_word_at(&Loc { x: 8, y: 1 });
assert_eq!(
doc.selection_loc_bound(),
(Loc { x: 6, y: 1 }, Loc { x: 11, y: 1 })
);
doc.remove_selection();
doc.move_to(&Loc { x: 0, y: 2 });
doc.select_word_at(&Loc { x: 0, y: 2 });
assert_eq!(
doc.selection_loc_bound(),
(Loc { x: 0, y: 2 }, Loc { x: 5, y: 2 })
);
}

#[test]
Expand Down
25 changes: 19 additions & 6 deletions plugins/autoindent.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--[[
Auto Indent v0.7
Auto Indent v0.8

Helps you when programming by guessing where indentation should go
and then automatically applying these guesses as you program
Expand Down Expand Up @@ -170,10 +170,23 @@ event_mapping["enter"] = function()
autoindent:disperse_block()
end

event_mapping["*"] = function()
-- Dedent where appropriate
if autoindent:causes_dedent(editor.cursor.y) then
local new_level = autoindent:get_indent(editor.cursor.y) - 1
autoindent:set_indent(editor.cursor.y, new_level)
-- For each ascii characters and punctuation
was_dedenting = false
for i = 32, 126 do
local char = string.char(i)
-- ... excluding the global event binding
if char ~= "*" then
-- Keep track of whether the line was previously dedenting beforehand
event_mapping["before:" .. char] = function()
was_dedenting = autoindent:causes_dedent(editor.cursor.y)
end
-- Trigger dedent checking
event_mapping[char] = function()
-- Dedent where appropriate
if autoindent:causes_dedent(editor.cursor.y) and not was_dedenting then
local new_level = autoindent:get_indent(editor.cursor.y) - 1
autoindent:set_indent(editor.cursor.y, new_level)
end
end
end
end
14 changes: 7 additions & 7 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ Ox: A lightweight and flexible text editor
USAGE: ox [options] [files]

OPTIONS:
--help, -h : Show this help message
--version, -v : Show the version number
--config [path], -c [path] : Specify the configuration file
--readonly, -r : Prevent opened files from writing
--filetype [ext], -f [ext] : Set the file type of files opened
--stdin : Reads file from the stdin
--help, -h : Show this help message
--version, -v : Show the version number
--config [path], -c [path] : Specify the configuration file
--readonly, -r : Prevent opened files from writing
--filetype [name], -f [name] : Set the file type of files opened
--stdin : Reads file from the stdin

EXAMPLES:
ox
ox test.txt
ox test.txt test2.txt
ox /home/user/docs/test.txt
ox -c config.lua test.txt
ox -r -c ~/.config/.oxrc -f lua my_file.lua
ox -r -c ~/.config/.oxrc -f Lua my_file.lua
tree | ox -r --stdin\
";

Expand Down
19 changes: 10 additions & 9 deletions src/config/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl LuaUserData for Editor {
});
fields.add_field_method_get("version", |_, _| Ok(VERSION));
fields.add_field_method_get("current_document_id", |_, editor| Ok(editor.ptr));
fields.add_field_method_get("document_count", |_, editor| Ok(editor.doc.len()));
fields.add_field_method_get("document_count", |_, editor| Ok(editor.files.len()));
fields.add_field_method_get("document_type", |_, editor| {
let ext = editor
.doc()
Expand Down Expand Up @@ -437,14 +437,15 @@ impl LuaUserData for Editor {
editor.doc_mut().info.read_only = status;
Ok(())
});
methods.add_method_mut("set_file_type", |_, editor, ext: String| {
let mut highlighter = editor
.config
.syntax_highlighting
.borrow()
.get_highlighter(&ext);
highlighter.run(&editor.doc().lines);
editor.highlighter[editor.ptr] = highlighter;
methods.add_method_mut("set_file_type", |_, editor, name: String| {
if let Some(file_type) = editor.config.document.borrow().file_types.get_name(&name) {
let mut highlighter = file_type.get_highlighter(&editor.config, 4);
highlighter.run(&editor.doc().lines);
editor.files[editor.ptr].highlighter = highlighter;
editor.files[editor.ptr].file_type = Some(file_type);
} else {
editor.feedback = Feedback::Error(format!("Invalid file type: {name}"));
}
Ok(())
});
// Rerendering
Expand Down
68 changes: 28 additions & 40 deletions src/config/highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::error::{OxError, Result};
use crossterm::style::Color as CColor;
use mlua::prelude::*;
use std::collections::HashMap;
use synoptic::{from_extension, Highlighter};
use synoptic::Highlighter;

use super::Color;

Expand All @@ -27,14 +27,6 @@ impl SyntaxHighlighting {
)))
}
}

/// Get a highlighter given a file extension
pub fn get_highlighter(&self, ext: &str) -> Highlighter {
self.user_rules.get(ext).map_or_else(
|| from_extension(ext, 4).unwrap_or_else(|| Highlighter::new(4)),
std::clone::Clone::clone,
)
}
}

impl LuaUserData for SyntaxHighlighting {
Expand Down Expand Up @@ -84,40 +76,36 @@ impl LuaUserData for SyntaxHighlighting {
);
methods.add_method_mut(
"new",
|_, syntax_highlighting, (extensions, rules): (LuaTable, LuaTable)| {
// Make note of the highlighter
for ext_idx in 1..=(extensions.len()?) {
// Create highlighter
let mut highlighter = Highlighter::new(4);
// Add rules one by one
for rule_idx in 1..=(rules.len()?) {
// Get rule
let rule = rules.get::<i64, HashMap<String, String>>(rule_idx)?;
// Find type of rule and attatch it to the highlighter
match rule["kind"].as_str() {
"keyword" => {
highlighter.keyword(rule["name"].clone(), &rule["pattern"]);
}
"bounded" => highlighter.bounded(
rule["name"].clone(),
rule["start"].clone(),
rule["end"].clone(),
rule["escape"] == "true",
),
"bounded_interpolation" => highlighter.bounded_interp(
rule["name"].clone(),
rule["start"].clone(),
rule["end"].clone(),
rule["i_start"].clone(),
rule["i_end"].clone(),
rule["escape"] == "true",
),
_ => unreachable!(),
|_, syntax_highlighting, (name, rules): (String, LuaTable)| {
// Create highlighter
let mut highlighter = Highlighter::new(4);
// Add rules one by one
for rule_idx in 1..=(rules.len()?) {
// Get rule
let rule = rules.get::<i64, HashMap<String, String>>(rule_idx)?;
// Find type of rule and attatch it to the highlighter
match rule["kind"].as_str() {
"keyword" => {
highlighter.keyword(rule["name"].clone(), &rule["pattern"]);
}
"bounded" => highlighter.bounded(
rule["name"].clone(),
rule["start"].clone(),
rule["end"].clone(),
rule["escape"] == "true",
),
"bounded_interpolation" => highlighter.bounded_interp(
rule["name"].clone(),
rule["start"].clone(),
rule["end"].clone(),
rule["i_start"].clone(),
rule["i_end"].clone(),
rule["escape"] == "true",
),
_ => unreachable!(),
}
let ext = extensions.get::<i64, String>(ext_idx)?;
syntax_highlighting.user_rules.insert(ext, highlighter);
}
syntax_highlighting.user_rules.insert(name, highlighter);
Ok(())
},
);
Expand Down
32 changes: 15 additions & 17 deletions src/config/interface.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::cli::VERSION;
use crate::editor::{which_extension, Editor};
use crate::editor::{Editor, FileContainer};
use crate::error::Result;
use crossterm::style::SetForegroundColor as Fg;
use kaolinite::searching::Searcher;
use kaolinite::utils::{filetype, get_absolute_path, get_file_name, icon};
use kaolinite::Document;
use kaolinite::utils::{get_absolute_path, get_file_ext, get_file_name};
use mlua::prelude::*;

use super::{issue_warning, Colors};
Expand Down Expand Up @@ -218,16 +217,17 @@ impl Default for TabLine {

impl TabLine {
/// Take the configuration information and render the tab line
pub fn render(&self, document: &Document) -> String {
let path = document
pub fn render(&self, file: &FileContainer) -> String {
let path = file
.doc
.file_name
.clone()
.unwrap_or_else(|| "[No Name]".to_string());
let file_extension = which_extension(document).unwrap_or_else(|| "Unknown".to_string());
let file_extension = get_file_ext(&path).unwrap_or_else(|| "Unknown".to_string());
let absolute_path = get_absolute_path(&path).unwrap_or_else(|| "[No Name]".to_string());
let file_name = get_file_name(&path).unwrap_or_else(|| "[No Name]".to_string());
let icon = icon(&filetype(&file_extension).unwrap_or_default());
let modified = if document.info.modified { "[+]" } else { "" };
let icon = file.file_type.clone().map_or("󰈙 ".to_string(), |t| t.icon);
let modified = if file.doc.info.modified { "[+]" } else { "" };
let mut result = self.format.clone();
result = result
.replace("{file_extension}", &file_extension)
Expand Down Expand Up @@ -277,23 +277,21 @@ impl Default for StatusLine {
impl StatusLine {
/// Take the configuration information and render the status line
pub fn render(&self, editor: &Editor, lua: &Lua, w: usize) -> String {
let file = &editor.files[editor.ptr];
let mut result = vec![];
let path = editor
.doc()
.file_name
.clone()
.unwrap_or_else(|| "[No Name]".to_string());
let file_extension = which_extension(editor.doc()).unwrap_or_else(|| "Unknown".to_string());
let file_extension = get_file_ext(&path).unwrap_or_else(|| "Unknown".to_string());
let absolute_path = get_absolute_path(&path).unwrap_or_else(|| "[No Name]".to_string());
let file_name = get_file_name(&path).unwrap_or_else(|| "[No Name]".to_string());
let file_type = filetype(&file_extension).unwrap_or_else(|| {
if file_extension.is_empty() {
"Unknown".to_string()
} else {
file_extension.to_string()
}
});
let icon = icon(&filetype(&file_extension).unwrap_or_default());
let file_type = file
.file_type
.clone()
.map_or("Unknown".to_string(), |t| t.name);
let icon = file.file_type.clone().map_or("󰈙 ".to_string(), |t| t.icon);
let modified = if editor.doc().info.modified {
"[+]"
} else {
Expand Down
Loading
Loading