Skip to content
This repository was archived by the owner on Jul 23, 2019. It is now read-only.

Commit a354bea

Browse files
committed
wip
1 parent c75db56 commit a354bea

File tree

2 files changed

+85
-5
lines changed

2 files changed

+85
-5
lines changed

xray_core/src/buffer_view.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ struct SelectionProps {
3939
enum BufferViewAction {
4040
UpdateScrollTop{delta: f64},
4141
SetDimensions{width: u64, height: u64},
42+
ReplaceSelectedText{text: String},
43+
MoveUp,
44+
MoveDown,
45+
MoveLeft,
46+
MoveRight,
4247
}
4348

4449
impl BufferView {
@@ -91,6 +96,20 @@ impl BufferView {
9196
self
9297
}
9398

99+
pub fn replace_selected_text(&mut self, text: &str) {
100+
{
101+
let mut buffer = self.buffer.borrow_mut();
102+
for selection in self.selections.iter().rev() {
103+
let start = buffer.offset_for_anchor(&selection.start).unwrap();
104+
let end = buffer.offset_for_anchor(&selection.end).unwrap();
105+
buffer.splice(start..end, text);
106+
}
107+
}
108+
109+
self.merge_selections();
110+
self.updated();
111+
}
112+
94113
pub fn add_selection(&mut self, start: Point, end: Point) {
95114
debug_assert!(start <= end); // TODO: Reverse selection if end < start
96115

@@ -489,6 +508,11 @@ impl View for BufferView {
489508
self.set_width(width as f64);
490509
self.set_height(height as f64);
491510
},
511+
Ok(BufferViewAction::ReplaceSelectedText{text}) => self.replace_selected_text(text.as_str()),
512+
Ok(BufferViewAction::MoveUp) => self.move_up(),
513+
Ok(BufferViewAction::MoveDown) => self.move_down(),
514+
Ok(BufferViewAction::MoveLeft) => self.move_left(),
515+
Ok(BufferViewAction::MoveRight) => self.move_right(),
492516
action @ _ => eprintln!("Unrecognized action {:?}", action),
493517
}
494518
}
@@ -866,6 +890,24 @@ mod tests {
866890
);
867891
}
868892

893+
#[test]
894+
fn test_replace_selected_text() {
895+
let mut editor = BufferView::new(Rc::new(RefCell::new(Buffer::new(1))));
896+
897+
editor.buffer.borrow_mut().splice(0..0, "abcdefgh\nhijklmno");
898+
899+
// Three selections on the same line
900+
editor.select_right();
901+
editor.select_right();
902+
editor.add_selection(Point::new(0, 3), Point::new(0, 5));
903+
editor.add_selection(Point::new(0, 7), Point::new(1, 1));
904+
editor.replace_selected_text("-");
905+
assert_eq!(
906+
String::from_utf16_lossy(editor.buffer.borrow().to_u16_chars().as_slice()),
907+
"-c-fg-ijklmno"
908+
);
909+
}
910+
869911
#[test]
870912
fn test_render() {
871913
let buffer = Rc::new(RefCell::new(Buffer::new(1)));

xray_electron/lib/render_process/text_editor/text_editor.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const Root = styled("div", {
1414
class TextEditor extends React.Component {
1515
constructor(props) {
1616
super(props);
17-
this.onWheel = this.onWheel.bind(this);
17+
this.handleMouseWheel = this.handleMouseWheel.bind(this);
18+
this.handleKeyDown = this.handleKeyDown.bind(this);
1819

1920
if (props.initialText) {
2021
buffer.splice(0, 0, props.initialText);
@@ -39,16 +40,24 @@ class TextEditor extends React.Component {
3940
height: element.offsetHeight
4041
});
4142

42-
element.addEventListener('wheel', this.onWheel, {passive: true});
43+
element.addEventListener('wheel', this.handleMouseWheel, {passive: true});
4344

45+
this.startCursorBlinking();
46+
}
47+
48+
componentWillUpdate() {
49+
if (this.state.cursorBlinkIntervalHandle) {
50+
clearInterval(this.state.cursorBlinkIntervalHandle);
51+
}
52+
this.setState({ showCursors: true });
4453
this.state.cursorBlinkIntervalHandle = window.setInterval(() => {
4554
this.setState({ showCursors: !this.state.showCursors });
4655
}, 500);
4756
}
4857

4958
componentWillUnmount() {
5059
const element = ReactDOM.findDOMNode(this);
51-
element.removeEventListener('wheel', this.onWheel, {passive: true});
60+
element.removeEventListener('wheel', this.handleMouseWheel, {passive: true});
5261
this.state.resizeObserver.disconnect();
5362
window.clearInterval(this.state.cursorBlinkIntervalHandle);
5463
}
@@ -64,7 +73,10 @@ class TextEditor extends React.Component {
6473
render() {
6574
return $(
6675
Root,
67-
{},
76+
{
77+
tabIndex: -1,
78+
onKeyDown: this.handleKeyDown
79+
},
6880
$(TextPlane, {
6981
showCursors: this.state.showCursors,
7082
lineHeight: this.props.line_height,
@@ -78,9 +90,35 @@ class TextEditor extends React.Component {
7890
);
7991
}
8092

81-
onWheel (event) {
93+
handleMouseWheel(event) {
8294
this.props.dispatch({type: 'UpdateScrollTop', delta: event.deltaY});
8395
}
96+
97+
handleKeyDown(event) {
98+
if (event.key.length === 1) {
99+
this.props.dispatch({type: 'ReplaceSelectedText', text: event.key});
100+
return;
101+
}
102+
103+
switch (event.key) {
104+
case 'ArrowUp':
105+
this.startCursorBlinking();
106+
this.props.dispatch({type: 'MoveUp'});
107+
break;
108+
case 'ArrowDown':
109+
this.startCursorBlinking();
110+
this.props.dispatch({type: 'MoveDown'});
111+
break;
112+
case 'ArrowLeft':
113+
this.startCursorBlinking();
114+
this.props.dispatch({type: 'MoveLeft'});
115+
break;
116+
case 'ArrowRight':
117+
this.startCursorBlinking();
118+
this.props.dispatch({type: 'MoveRight'});
119+
break;
120+
}
121+
}
84122
}
85123

86124
TextEditor.contextTypes = {

0 commit comments

Comments
 (0)