Skip to content

Commit 876453c

Browse files
committed
It appears to work
1 parent d8cf8c2 commit 876453c

File tree

4 files changed

+80
-20
lines changed

4 files changed

+80
-20
lines changed

setup.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export ZDOTDIR=/home/zshtest
2+
stty -tostop

src/brackets.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
use std::collections::HashMap;
44
use std::ffi::CString;
55
use linkroot;
6-
use std::os::raw::c_char;
7-
use {shfunc, getshfunc, doshfunc, Shfunc};
6+
use std::os::raw::{c_char, c_void};
7+
use {shfunc, getshfunc, doshfunc, Shfunc, newlinklist, insertlinknode, linknode};
88

9-
fn brackets_paint(buf: &str, widget: &str, cursor: usize) {
10-
let mut style: &str;
9+
pub fn brackets_paint(buf: &str, widget: &str, cursor: usize) {
10+
let mut style: String;
1111
let mut level: usize = 0;
1212
let mut matching_pos: usize = 0;
13-
let mut bracket_color_size: usize = 0;
13+
let mut bracket_color_size: usize = 5; // TODO
1414
let mut buf_len: usize = 0;
1515
let mut pos: usize = 0;
1616

@@ -29,7 +29,10 @@ fn brackets_paint(buf: &str, widget: &str, cursor: usize) {
2929
last_of_level.insert(level, i);
3030
},
3131
')' | ']' | '}' => {
32-
matching_pos = *last_of_level.get(&level).unwrap();
32+
let matching_pos = match last_of_level.get(&level) {
33+
Some(val) => *val,
34+
None => continue
35+
};
3336
level_pos.insert(i, level);
3437
level -= 1;
3538

@@ -50,20 +53,21 @@ fn brackets_paint(buf: &str, widget: &str, cursor: usize) {
5053
}
5154
}
5255

53-
for pos in level_pos.values() {
56+
for pos in level_pos.keys() {
5457
if matching.contains_key(pos) {
55-
style = "fg=yellow"; // TODO
58+
style = format!("bracket-level-{}", ((level_pos[pos] - 1) % bracket_color_size) + 1);
5659
} else {
57-
style = "fg=red";
60+
style = "bracket-error".to_owned();
5861
}
62+
do_highlight(*pos, *pos + 1, &style);
5963

6064
}
6165

6266
if widget != "zle-line-finish" {
6367
pos = cursor + 1;
6468
if level_pos.get(&pos).is_some() && matching.get(&pos).is_some() {
6569
let other_pos = matching[&pos];
66-
do_highlight(other_pos - 1, other_pos, "standout");
70+
do_highlight(other_pos, other_pos + 1, "standout");
6771
}
6872
}
6973

@@ -78,10 +82,27 @@ fn brackets_match(first: char, second: char) -> bool {
7882
}
7983
}
8084

85+
#[cfg(not(test))]
8186
fn do_highlight(start: usize, end: usize, style: &str) {
82-
let func_name = CString::new("_zsh_highlight_add_highlight").unwrap();
8387
unsafe {
84-
let func: Shfunc = getshfunc(func_name.as_ptr() as *mut c_char);
85-
doshfunc(func, 0 as *mut linkroot, 1);
88+
let func_name = str_to_ptr("_zsh_highlight_add_highlight");
89+
let func = getshfunc(func_name as *mut c_char);
90+
91+
let list = newlinklist();
92+
insertlinknode(list, (*list).list.as_ref().last as *const linknode as *mut linknode, func_name);
93+
insertlinknode(list, (*list).list.as_ref().last as *const linknode as *mut linknode, str_to_ptr(&start.to_string()));
94+
insertlinknode(list, (*list).list.as_ref().last as *const linknode as *mut linknode, str_to_ptr(&end.to_string()));
95+
insertlinknode(list, (*list).list.as_ref().last as *const linknode as *mut linknode, str_to_ptr(style));
96+
97+
doshfunc(func, list as *mut linkroot, 1);
8698
}
8799
}
100+
101+
#[cfg(test)]
102+
fn do_highlight(start: usize, end: usize, style: &str) {
103+
}
104+
105+
106+
fn str_to_ptr(s: &str) -> *mut c_void {
107+
CString::new(s.to_string()).unwrap().into_raw() as *mut c_void
108+
}

src/lib.rs

+43-7
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ include!("bindings.rs");
1010
#[macro_use]
1111
extern crate lazy_static;
1212

13+
mod brackets;
14+
1315
use std::ptr::{null, null_mut};
1416
use std::os::raw::{c_int, c_char};
15-
use std::ffi::CString;
17+
use std::ffi::{CString, CStr};
1618
use std::mem::transmute;
19+
use std::slice;
1720

18-
mod brackets;
21+
use brackets::brackets_paint;
1922

2023
// https://github.com/rust-lang/rfcs/issues/400#issuecomment-274140470
2124
macro_rules! cstr {
@@ -38,8 +41,8 @@ pub static mut bintab: BinWrapper<'static> = BinWrapper(&mut [builtin {
3841
flags: 0
3942
},
4043
handlerfunc: Some(bin_fastbrackets),
41-
minargs: 0,
42-
maxargs: -1,
44+
minargs: 2,
45+
maxargs: 3,
4346
funcid: 0,
4447
optstr: null_mut(),
4548
defopts: null_mut()
@@ -105,14 +108,47 @@ pub extern fn enables_(m: Module, enables: *mut *mut c_int) -> c_int {
105108
}
106109

107110
#[no_mangle]
108-
pub extern fn bin_fastbrackets(name: *mut c_char, args: *mut *mut c_char, options: Options, func: c_int) -> c_int {
109-
println!("Called!");
111+
pub extern fn bin_fastbrackets(name: *mut c_char, mut raw_args: *mut *mut c_char, options: Options, func: c_int) -> c_int {
112+
let mut args: Vec<String> = Vec::new();
113+
114+
unsafe {
115+
while *raw_args != null_mut() {
116+
args.push(CStr::from_ptr(*raw_args as *const c_char).to_str().unwrap().to_owned());
117+
raw_args = raw_args.offset(1);
118+
}
119+
}
120+
121+
let cursor = 0;
122+
if args.len() == 2 {
123+
let cursor = 0;
124+
} else {
125+
let cursor = match args[2].parse::<usize>() {
126+
Ok(s) => s,
127+
Err(e) => {
128+
unsafe { zwarnnam(name, CString::new(format!("Invalid cursor argument: {:?}", e)).unwrap().into_raw()) } ;
129+
return 1
130+
}
131+
};
132+
}
133+
brackets_paint(&args[0], &args[1], cursor);
134+
110135
0
111136
}
112137

113138
#[cfg(test)]
114139
mod tests {
140+
use brackets::brackets_paint;
141+
use std::str;
142+
115143
#[test]
116-
fn it_works() {
144+
fn simple_bracket() {
145+
brackets_paint("[]", "lol", 0);
117146
}
147+
148+
/*#[test]
149+
fn large_buffer() {
150+
let data = &[b'a'; 30_000];
151+
let buf = unsafe { str::from_utf8_unchecked(data) };
152+
brackets_paint(&buf, "hi", 0);
153+
}*/
118154
}

test.sh

100644100755
+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
zmodload aaron/fastbrackets
2+
fastbrackets 1 2 3

0 commit comments

Comments
 (0)