Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TAB key in TextEdit, fill the space with different sizes #3879

Draft
wants to merge 38 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
175cd45
TAB key in TextEdit, fill the space with different sizes
rustbasic Jan 24, 2024
634aa80
Update text_buffer.rs
rustbasic Jan 24, 2024
3f8e70a
Update text_cursor_state.rs
rustbasic Jan 24, 2024
569be33
Update text_cursor_state.rs
rustbasic Jan 24, 2024
bcfb054
Update Cargo.toml
rustbasic Jan 24, 2024
a367c89
Merge branch 'emilk:master' into patch3
rustbasic Jan 25, 2024
f7ccce4
Update text_cursor_state.rs
rustbasic Jan 26, 2024
2a7de1b
Merge branch 'emilk:master' into patch3
rustbasic Feb 5, 2024
76da7b7
Merge branch 'emilk:master' into patch3
rustbasic Feb 5, 2024
296c040
Merge branch 'emilk:master' into patch3
rustbasic Feb 6, 2024
b0aba92
Merge branch 'emilk:master' into patch3
rustbasic Feb 7, 2024
b4ff232
Update text_cursor_state.rs
rustbasic Feb 24, 2024
cea7ebb
Merge branch 'emilk:master' into patch3
rustbasic Feb 24, 2024
d0ff012
Update text_cursor_state.rs
rustbasic Feb 24, 2024
cf1b3dc
Merge branch 'emilk:master' into patch3
rustbasic Mar 14, 2024
829f6c3
Merge branch 'emilk:master' into patch3
rustbasic Mar 25, 2024
f63537f
Merge branch 'emilk:master' into patch3
rustbasic Mar 26, 2024
8a16102
Merge branch 'emilk:master' into patch3
rustbasic Mar 27, 2024
12a9180
Merge branch 'emilk:master' into patch3
rustbasic Mar 28, 2024
d042b92
Merge branch 'emilk:master' into patch3
rustbasic Mar 29, 2024
919d984
Merge branch 'emilk:master' into patch3
rustbasic Mar 30, 2024
b6014c3
Merge branch 'emilk:master' into patch3
rustbasic Mar 30, 2024
3d51de9
Merge branch 'emilk:master' into patch3
rustbasic Mar 30, 2024
7487725
Merge branch 'emilk:master' into patch3
rustbasic Mar 31, 2024
01642f5
Merge branch 'emilk:master' into patch3
rustbasic Apr 1, 2024
db071f0
Merge branch 'emilk:master' into patch3
rustbasic Apr 1, 2024
f07170c
Merge branch 'emilk:master' into patch3
rustbasic Apr 1, 2024
2b4a271
Merge branch 'emilk:master' into patch3
rustbasic Apr 2, 2024
66e11b6
Merge branch 'emilk:master' into patch3
rustbasic Apr 2, 2024
cc55f8f
Merge branch 'emilk:master' into patch3
rustbasic Apr 3, 2024
60f2917
Merge branch 'emilk:master' into patch3
rustbasic Apr 3, 2024
bc39148
Merge branch 'emilk:master' into patch3
rustbasic Apr 5, 2024
85c6202
Merge branch 'emilk:master' into patch3
rustbasic Apr 19, 2024
82ae3ac
Merge branch 'emilk:master' into patch3
rustbasic Apr 21, 2024
4ad5579
Merge branch 'emilk:master' into patch3
rustbasic Apr 22, 2024
fec401b
Merge branch 'emilk:master' into patch3
rustbasic Apr 22, 2024
24a1e93
Merge branch 'emilk:master' into patch3
rustbasic Apr 23, 2024
e38f7ea
Merge branch 'emilk:master' into patch3
rustbasic Apr 29, 2024
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
1 change: 1 addition & 0 deletions crates/egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,4 @@ log = { workspace = true, optional = true }
puffin = { workspace = true, optional = true }
ron = { version = "0.8", optional = true }
serde = { version = "1", optional = true, features = ["derive", "rc"] }
unicode-width = "0.1.11"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid adding this dependency? It's not a huge one, but I wonder how much larger the .wasm becomes with these tables: https://github.com/unicode-rs/unicode-width/blob/master/src/tables.rs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid adding this dependency? It's not a huge one, but I wonder how much larger the .wasm becomes with these tables: https://github.com/unicode-rs/unicode-width/blob/master/src/tables.rs

I don't think this dependency can be avoided. These are codes so they will not be very large and are essential for countries that use UTF8 characters. All pictograms are also affected by this.

108 changes: 99 additions & 9 deletions crates/egui/src/text_selection/text_cursor_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,18 +302,108 @@ pub fn find_line_start(text: &str, current_index: CCursor) -> CCursor {
// number of multi byte chars.
// We need to know the char index to be able to correctly set the cursor
// later.
let chars_count = text.chars().count();
let mut char_line_indexes: Vec<usize> = create_char_line_indexes(text);
let line_start_index = get_line_start_index(&mut char_line_indexes, current_index.index);

let position = text
.chars()
.rev()
.skip(chars_count - current_index.index)
.position(|x| x == '\n');
CCursor::new(line_start_index)
}

pub fn create_char_line_indexes(text: &str) -> Vec<usize> {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not from an English-speaking country, so it's hard for me to choose even a single word.
I would appreciate it if emilk could make a suggestion.

let mut line_indexes = vec![0];

let mut count = 0;
for c in text.chars() {
count += 1;
if c == '\n' {
line_indexes.push(count);
}
}
line_indexes.push(count);

line_indexes
}

pub fn get_line_start_index(line_indexes: &mut [usize], index: usize) -> usize {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot of naked usize. If you use CCursor you can make it clear wether or not something is a byte offset or a character offset

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this, we can easily find out the current Colume and line within TextEdit. I'm using this, and I'm sure others might want to use it too.

Copy link
Owner

@emilk emilk Mar 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it return a byte index or a char index? The name doesn't tell me, neither does the return type.

What about the arguments, are they byte indexes or char indices? Try to put yourself into the shoes of someone who is just reading the function header

let (_current_line, line_start) = get_line_and_start_index(line_indexes, index);
line_start
}

pub fn get_line_and_start_index(line_indexes: &mut [usize], index: usize) -> (usize, usize) {
let mut current_line = 1;
for (i, line_start) in line_indexes.iter().enumerate() {
current_line = i;
if *line_start > index {
break;
}
}

(current_line, line_indexes[current_line - 1])
}

match position {
Some(pos) => CCursor::new(current_index.index - pos),
None => CCursor::new(0),
pub fn get_current_column(text: &str, line_indexes: &mut [usize], index: usize) -> usize {
let (current_column, _total_column) =
get_current_column_total_column(text, line_indexes, index);
current_column
}

pub fn get_current_column_total_column(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you shouldn't be using get_ everywhere

https://rust-lang.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter

I'm not from an English-speaking country, so it's hard for me to choose even a single word.
I would appreciate it if emilk could make a suggestion.

text: &str,
line_indexes: &mut [usize],
index: usize,
) -> (usize, usize) {
let (current_column, total_column, _total_line) =
get_current_column_total_column_line(text, line_indexes, index);
(current_column, total_column)
}

pub fn get_current_column_total_column_line(
text: &str,
line_indexes: &mut [usize],
index: usize,
) -> (usize, usize, usize) {
let (current_column, _current_line, total_columns, total_lines) =
get_current_column_line_total_column_line(text, line_indexes, index);

(current_column, total_columns, total_lines)
}

pub fn get_current_column_line_total_column_line(
text: &str,
line_indexes: &mut [usize],
index: usize,
) -> (usize, usize, usize, usize) {
let (current_line, line_start_index) = get_line_and_start_index(line_indexes, index);

let total_lines = line_indexes.len() - 1;

let mut i: usize = line_start_index;
let mut current_column: usize = 1;
let mut total_columns: usize = 0;
while let Some(c) = text.chars().nth(i) {
if c == '\n' {
break;
} else if c == '\t' {
total_columns += text::TAB_SIZE;
} else {
// The simple( not exact ) width :
// let width = match c.len_utf8() > 2 {
// true => 2,
// false => 1,
// };

// The exact width :
let width = unicode_width::UnicodeWidthChar::width_cjk(c).unwrap_or(2);

total_columns += width;
}

if i < index {
current_column = total_columns + 1;
}
i += 1;
}

(current_column, current_line, total_columns, total_lines)
}

pub fn byte_index_from_char_index(s: &str, char_index: usize) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/widgets/text_edit/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ fn events(
// TODO(emilk): support removing indentation over a selection?
text.decrease_indentation(&mut ccursor);
} else {
text.insert_text_at(&mut ccursor, "\t", char_limit);
text.insert_tab_to_space(&mut ccursor, "\t", char_limit);
}
Some(CCursorRange::one(ccursor))
}
Expand Down
25 changes: 25 additions & 0 deletions crates/egui/src/widgets/text_edit/text_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,31 @@ pub trait TextBuffer {
}
}

fn insert_tab_to_space(
&mut self,
ccursor: &mut CCursor,
text_to_insert: &str,
char_limit: usize,
) {
let tab_size: usize = TAB_SIZE;
let mut text_to_insert: String = text_to_insert.to_owned();
if text_to_insert == "\t" {
let mut line_indexes: Vec<usize> =
crate::text_selection::text_cursor_state::create_char_line_indexes(self.as_str());
let current_column = crate::text_selection::text_cursor_state::get_current_column(
self.as_str(),
&mut line_indexes,
ccursor.index,
);
let tab_size_gap = (current_column - 1) % tab_size;
let add_space_size = tab_size - tab_size_gap;

text_to_insert = " ".repeat(add_space_size);
}

self.insert_text_at(ccursor, &text_to_insert, char_limit);
}

fn decrease_indentation(&mut self, ccursor: &mut CCursor) {
let line_start = find_line_start(self.as_str(), *ccursor);

Expand Down
Loading