-
Notifications
You must be signed in to change notification settings - Fork 6
/
App.re
125 lines (104 loc) · 3.7 KB
/
App.re
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
open Revery;
open Revery.UI;
open ReveryTerminal;
module Store =
Isolinear.Store.Make({
type msg = Model.msg;
type model = Model.t;
let initial = Model.initial;
let updater = Model.updater;
let subscriptions = Model.subscriptions;
});
let init = app => {
// Create a primary window for our app
let window = App.createWindow(app, "Revery Terminal");
let emptyElement = <View />;
// Connect with the isolinear store -
let redraw = UI.start(window, emptyElement);
let render = ({screen, cursor, font, _}: Model.t) =>
font
|> Option.map(font => ReveryTerminal.render(~font, ~cursor, screen))
|> Option.value(~default=emptyElement);
// ...wire up any state changes to trigger a redraw of the UI
let _unsubscribe: unit => unit =
Store.onModelChanged(newModel => newModel |> render |> redraw);
// ...and whenever there are side-effects pending, run those immediately.
let _unsubscribe: unit => unit =
Store.onPendingEffect(() => {Store.runPendingEffects()});
// Set up some nice colorized logging
Timber.App.enable(Timber.Reporter.console());
Timber.App.setLevel(Timber.Level.trace);
// And enable record backtraces, to check for exceptions
Printexc.record_backtrace(true);
Printexc.set_uncaught_exception_handler((exn, _backtrace) => {
prerr_endline("Exception: " ++ Printexc.to_string(exn))
});
// Set up Revery window listeners
// This would be even nicer if we had a 'ReveryIso' (revery + isolinear)
// project that provided subscriptions and effects for working with Revery.
let _: unit => unit =
Revery.Window.onTextInputCommit(
window, ({text}: Revery.Events.textInputEvent) => {
String.iter(
c => {
let charCode = Char.code(c) |> Uchar.of_int;
Store.dispatch(InputKey(Unicode(charCode), None));
},
text,
)
});
let _: unit => unit =
Revery.Window.onKeyDown(
window,
(keyEvent: Key.KeyEvent.t) => {
open Vterm;
let {keycode, keymod, _}: Key.KeyEvent.t = keyEvent;
if (Key.Keymod.isControlDown(keymod)) {
let keyName =
Key.Keycode.getName(keycode) |> String.lowercase_ascii;
// Only handle simple ascii case for now
if (String.length(keyName) == 1) {
let uchar = keyName.[0] |> Char.code |> Uchar.of_int;
Store.dispatch(InputKey(Unicode(uchar), Control));
};
} else {
let key =
switch (keycode) {
// From: https://wiki.libsdl.org/SDLKeycodeLookup
| 8 => Some(Backspace)
| 9 => Some(Tab)
| 13 => Some(Enter)
| 27 => Some(Escape)
| 127 => Some(Delete)
| 1073741898 => Some(Home)
| 1073741899 => Some(PageUp)
| 1073741901 => Some(End)
| 1073741902 => Some(PageDown)
| 1073741903 => Some(Right)
| 1073741904 => Some(Left)
| 1073741905 => Some(Down)
| 1073741906 => Some(Up)
| _ => None
};
key |> Option.iter(k => Store.dispatch(InputKey(k, None)));
};
},
);
let _: unit => unit =
Revery.Window.onSizeChanged(window, ({width, height}) => {
Store.dispatch(
WindowSizeChanged({pixelWidth: width, pixelHeight: height}),
)
});
Revery.Window.startTextInput(window);
// Load font, and dispatch on success
let font =
Revery.Font.Family.fromFile("JetBrainsMono-Medium.ttf")
|> Revery.Font.Family.toSkia(Revery.Font.Weight.Normal);
switch (Revery.Font.load(font)) {
| Ok(font) =>
Store.dispatch(Model.FontLoaded(Font.make(~size=12.0, font)))
| Error(msg) => failwith(msg)
};
};
App.start(init);