Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/account/editor-settings/checkboxes.tsx
5907 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
// cSpell:ignore codebar
7
8
import { defineMessage, useIntl } from "react-intl";
9
10
import { Panel, Switch } from "@cocalc/frontend/antd-bootstrap";
11
import { Rendered } from "@cocalc/frontend/app-framework";
12
import { Icon, IconName } from "@cocalc/frontend/components";
13
import { BUILD_ON_SAVE_ICON_ENABLED } from "@cocalc/frontend/frame-editors/frame-tree/commands/const";
14
import { IntlMessage, isIntlMessage } from "@cocalc/frontend/i18n";
15
import { capitalize } from "@cocalc/util/misc";
16
17
const EDITOR_SETTINGS_CHECKBOXES = {
18
extra_button_bar: defineMessage({
19
id: "account.editor-setting.checkbox.extra_button_bar",
20
defaultMessage:
21
"customizable button bar below menu bar with shortcuts to menu items",
22
}),
23
line_wrapping: defineMessage({
24
id: "account.editor-setting.checkbox.line_wrapping",
25
defaultMessage: "wrap long lines",
26
}),
27
line_numbers: defineMessage({
28
id: "account.editor-setting.checkbox.line_numbers",
29
defaultMessage: "show line numbers",
30
}),
31
jupyter_line_numbers: defineMessage({
32
id: "account.editor-setting.checkbox.jupyter_line_numbers",
33
defaultMessage: "show line numbers in Jupyter Notebooks",
34
}),
35
code_folding: defineMessage({
36
id: "account.editor-setting.checkbox.code_folding",
37
defaultMessage: "fold code using control+Q",
38
}),
39
smart_indent: defineMessage({
40
id: "account.editor-setting.checkbox.smart_indent",
41
defaultMessage: "context sensitive indentation",
42
}),
43
electric_chars: defineMessage({
44
id: "account.editor-setting.checkbox.electric_chars",
45
defaultMessage: "sometimes re-indent current line",
46
}),
47
match_brackets: defineMessage({
48
id: "account.editor-setting.checkbox.match_brackets",
49
defaultMessage: "highlight matching brackets near cursor",
50
}),
51
auto_close_brackets: defineMessage({
52
id: "account.editor-setting.checkbox.auto_close_brackets",
53
defaultMessage: "automatically close brackets",
54
}),
55
match_xml_tags: defineMessage({
56
id: "account.editor-setting.checkbox.match_xml_tags",
57
defaultMessage: "automatically match XML tags",
58
}),
59
auto_close_xml_tags: defineMessage({
60
id: "account.editor-setting.checkbox.auto_close_xml_tags",
61
defaultMessage: "automatically close XML tags",
62
}),
63
auto_close_latex: defineMessage({
64
id: "account.editor-setting.checkbox.auto_close_latex",
65
defaultMessage: "automatically close LaTeX environments",
66
}),
67
strip_trailing_whitespace: defineMessage({
68
id: "account.editor-setting.checkbox.strip_trailing_whitespace",
69
defaultMessage: "remove whenever file is saved",
70
}),
71
show_trailing_whitespace: defineMessage({
72
id: "account.editor-setting.checkbox.show_trailing_whitespace",
73
defaultMessage: "show spaces at ends of lines",
74
}),
75
spaces_instead_of_tabs: defineMessage({
76
id: "account.editor-setting.checkbox.spaces_instead_of_tabs",
77
defaultMessage: "send spaces when the tab key is pressed",
78
}),
79
build_on_save: defineMessage({
80
id: "account.editor-setting.checkbox.build_on_save",
81
defaultMessage: "build LaTex/Rmd files whenever it is saved to disk",
82
}),
83
show_exec_warning: defineMessage({
84
id: "account.editor-setting.checkbox.show_exec_warning",
85
defaultMessage: "warn that certain files are not directly executable",
86
}),
87
ask_jupyter_kernel: defineMessage({
88
id: "account.editor-setting.checkbox.ask_jupyter_kernel",
89
defaultMessage: "ask which kernel to use for a new Jupyter Notebook",
90
}),
91
show_my_other_cursors: "when editing the same file in multiple browsers",
92
disable_jupyter_virtualization: defineMessage({
93
id: "account.editor-setting.checkbox.disable_jupyter_virtualization",
94
defaultMessage:
95
"render entire Jupyter Notebook instead of just visible part (slower and not recommended)",
96
}),
97
disable_markdown_codebar: defineMessage({
98
id: "account.other-settings.markdown_codebar",
99
defaultMessage: `<strong>Disable the markdown code bar</strong> in all markdown documents.
100
Checking this hides the extra run, copy, and explain buttons in fenced code blocks.`,
101
}),
102
show_symbol_bar_labels: defineMessage({
103
id: "account.other-settings.symbol_bar_labels",
104
defaultMessage:
105
"<strong>Show Symbol Bar Labels:</strong> show labels in the frame editor symbol bar",
106
}),
107
} as const;
108
109
// Type for valid checkbox keys
110
type CheckboxKey = keyof typeof EDITOR_SETTINGS_CHECKBOXES;
111
112
// Group checkboxes into logical panels
113
const DISPLAY_SETTINGS: readonly CheckboxKey[] = [
114
"line_wrapping",
115
"line_numbers",
116
"jupyter_line_numbers",
117
"show_trailing_whitespace",
118
"show_my_other_cursors",
119
"show_symbol_bar_labels",
120
] as const;
121
122
const EDITING_BEHAVIOR: readonly CheckboxKey[] = [
123
"code_folding",
124
"smart_indent",
125
"electric_chars",
126
"spaces_instead_of_tabs",
127
"strip_trailing_whitespace",
128
] as const;
129
130
const AUTOCOMPLETION: readonly CheckboxKey[] = [
131
"match_brackets",
132
"auto_close_brackets",
133
"match_xml_tags",
134
"auto_close_xml_tags",
135
"auto_close_latex",
136
] as const;
137
138
const FILE_OPERATIONS: readonly CheckboxKey[] = [
139
"build_on_save",
140
"show_exec_warning",
141
] as const;
142
143
const JUPYTER_SETTINGS: readonly CheckboxKey[] = [
144
"ask_jupyter_kernel",
145
"disable_jupyter_virtualization",
146
] as const;
147
148
const UI_ELEMENTS: readonly CheckboxKey[] = [
149
"extra_button_bar",
150
"disable_markdown_codebar",
151
] as const;
152
153
// Settings that come from other_settings instead of editor_settings
154
const OTHER_SETTINGS_KEYS: readonly CheckboxKey[] = [
155
"disable_markdown_codebar",
156
"show_symbol_bar_labels",
157
] as const;
158
159
function isOtherSetting(name: CheckboxKey): boolean {
160
return OTHER_SETTINGS_KEYS.includes(name);
161
}
162
163
interface Props {
164
editor_settings;
165
other_settings?;
166
email_address?: string;
167
on_change: Function;
168
on_change_other_settings?: Function;
169
}
170
171
export function EditorSettingsCheckboxes(props: Props) {
172
const intl = useIntl();
173
174
function renderName(name: CheckboxKey) {
175
if (isOtherSetting(name)) return;
176
return (
177
<strong>
178
{capitalize(
179
name
180
.replace(/_/g, " ")
181
.replace(/-/g, " ")
182
.replace("xml", "XML")
183
.replace("latex", "LaTeX"),
184
) + ": "}
185
</strong>
186
);
187
}
188
189
function label_checkbox(
190
name: CheckboxKey,
191
desc: IntlMessage | Rendered | string,
192
): Rendered {
193
return (
194
<span>
195
{renderName(name)}
196
{isIntlMessage(desc) ? intl.formatMessage(desc) : desc}
197
</span>
198
);
199
}
200
201
function render_checkbox(
202
name: CheckboxKey,
203
desc: IntlMessage | Rendered | string,
204
): Rendered {
205
// Special handling for settings that are in other_settings
206
const is_other_setting = isOtherSetting(name);
207
const checked = is_other_setting
208
? !!props.other_settings?.get(name)
209
: !!props.editor_settings.get(name);
210
const onChange = is_other_setting
211
? (e) => props.on_change_other_settings?.(name, e.target.checked)
212
: (e) => props.on_change(name, e.target.checked);
213
214
return (
215
<Switch checked={checked} key={name} onChange={onChange}>
216
{label_checkbox(name, desc)}
217
</Switch>
218
);
219
}
220
221
function renderPanel(
222
header: string,
223
icon: IconName,
224
settingNames: readonly CheckboxKey[],
225
) {
226
return (
227
<Panel
228
size="small"
229
header={
230
<>
231
<Icon name={icon} /> {header}
232
</>
233
}
234
>
235
{settingNames.map((name) =>
236
render_checkbox(name, EDITOR_SETTINGS_CHECKBOXES[name]),
237
)}
238
</Panel>
239
);
240
}
241
242
return (
243
<>
244
{renderPanel("Display Settings", "eye", DISPLAY_SETTINGS)}
245
{renderPanel("Editing Behavior", "edit", EDITING_BEHAVIOR)}
246
{renderPanel("Auto-completion", "code", AUTOCOMPLETION)}
247
{renderPanel(
248
"File Operations",
249
BUILD_ON_SAVE_ICON_ENABLED,
250
FILE_OPERATIONS,
251
)}
252
{renderPanel("Jupyter Settings", "jupyter", JUPYTER_SETTINGS)}
253
{renderPanel("UI Elements", "desktop", UI_ELEMENTS)}
254
</>
255
);
256
}
257
258