-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathModel.re
116 lines (100 loc) · 2.97 KB
/
Model.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
open ReveryTerminal;
// This type [t] is the heart of our app - the entire state
// of our terminal is contained here!
type t = {
screen: Screen.t,
cursor: Cursor.t,
font: option(Font.t),
pixelWidth: int,
pixelHeight: int,
};
let initial: t = {
screen: Screen.initial,
cursor: Cursor.initial,
font: None,
pixelWidth: 1,
pixelHeight: 1,
};
type size = {
rows: int,
columns: int,
};
type windowSize = {
pixelWidth: int,
pixelHeight: int,
};
type msg =
| InputKey(Vterm.key, Vterm.modifier)
| Terminal(Terminal.msg)
| FontLoaded(Font.t)
| WindowSizeChanged(windowSize);
let calculateRowsAndColumns = ({pixelWidth, pixelHeight, font, _}) => {
switch (font) {
| None => (0, 0)
| Some(loadedFont) =>
let {characterWidth, lineHeight, _}: Font.t = loadedFont;
let columns = int_of_float(float(pixelWidth) /. characterWidth);
let rows = int_of_float(float(pixelHeight) /. lineHeight);
(rows, columns);
};
};
let checkResizeTerminalEffect = model => {
// Get current rows / columns
let columns = Screen.getColumns(model.screen);
let rows = Screen.getColumns(model.screen);
// Check what our rows / columns should be
let (newRows, newColumns) = calculateRowsAndColumns(model);
if (newRows != rows || newColumns != columns) {
// We're out of sync - ask the terminal to resize to our new size
let effect =
Terminal.Effects.resize(~id=1, ~rows=newRows, ~columns=newColumns);
// Effects can dispatch... so we need to map from the terminal messages
// to our messages
effect |> Isolinear.Effect.map(msg => Terminal(msg));
} else {
// All good, we're at the right size - nothing to do.
Isolinear.Effect.none;
};
};
let termPropEffect = _prop => {
Isolinear.Effect.none;
};
let mapTerminalEffect = terminalEffect =>
terminalEffect |> Isolinear.Effect.map(msg => Terminal(msg));
let updater = (model, msg) => {
let noop = (model, Isolinear.Effect.none);
switch (msg) {
| InputKey(key, modifier) => (
model,
Terminal.Effects.input(~id=1, ~key, ~modifier) |> mapTerminalEffect,
)
| Terminal(ReveryTerminal.ScreenResized(screen)) => (
{...model, screen},
Isolinear.Effect.none,
)
| Terminal(ReveryTerminal.ScreenUpdated(screen)) => (
{...model, screen},
Isolinear.Effect.none,
)
| Terminal(ReveryTerminal.CursorMoved(cursor)) => (
{...model, cursor},
Isolinear.Effect.none,
)
| Terminal(ReveryTerminal.TermPropChanged(prop)) => (
model,
termPropEffect(prop),
)
| FontLoaded(font) =>
let newModel = {...model, font: Some(font)};
(newModel, checkResizeTerminalEffect(newModel));
| WindowSizeChanged({pixelWidth, pixelHeight}) =>
let newModel = {...model, pixelWidth, pixelHeight};
(newModel, checkResizeTerminalEffect(newModel));
// TODO:
| Terminal(_) => noop
};
};
let subscriptions = _model => {
Terminal.Sub.terminal(~id=1, ~cmd="/bin/bash", ~rows=40, ~columns=80)
|> Isolinear.Sub.map(msg => Terminal(msg));
};