Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new-log-viewer: Add custom Monaco editor themes and a Monaco language for logs. #69

Merged
merged 8 commits into from
Sep 16, 2024
15 changes: 12 additions & 3 deletions new-log-viewer/src/components/Editor/MonacoInstance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import "./index.css";


interface MonacoEditorProps {
actions: ActionType[],
lineNum: number,
text: string,
actions: ActionType[],
themeName: "dark" | "light",

beforeMount?: BeforeMountCallback,
beforeTextUpdate?: BeforeTextUpdateCallback,
onCursorExplicitPosChange: CursorExplicitPosChangeCallback,
Expand All @@ -40,9 +42,10 @@ interface MonacoEditorProps {
* the editor.
*
* @param props
* @param props.actions
* @param props.lineNum
* @param props.text
* @param props.actions
* @param props.themeName
* @param props.beforeMount
* @param props.beforeTextUpdate
* @param props.onCursorExplicitPosChange
Expand All @@ -52,9 +55,10 @@ interface MonacoEditorProps {
* @return
*/
const MonacoInstance = ({
actions,
lineNum,
text,
actions,
themeName,
beforeMount,
beforeTextUpdate,
onMount,
Expand Down Expand Up @@ -98,6 +102,11 @@ const MonacoInstance = ({
onMount,
]);

// On `themeName` update, set the theme in the editor.
useEffect(() => {
monaco.editor.setTheme(themeName);
}, [themeName]);

// On `text` update, set the text and position cursor in the editor.
useEffect(() => {
if (null === editorRef.current) {
Expand Down
36 changes: 36 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/language.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {TOKEN_NAMES} from "./typings";


const LOG_LANGUAGE_NAME = "logLanguage";


/**
* Registers a custom log language in the Monaco editor.
*/
const setupCustomLogLanguage = () => {
junhaoliao marked this conversation as resolved.
Show resolved Hide resolved
monaco.languages.register({
id: LOG_LANGUAGE_NAME,
});
monaco.languages.setMonarchTokensProvider(LOG_LANGUAGE_NAME, {
tokenizer: {
root: [
/* eslint-disable @stylistic/js/array-element-newline */
["INFO", TOKEN_NAMES.CUSTOM_INFO],
["WARN", TOKEN_NAMES.CUSTOM_WARN],
["ERROR", TOKEN_NAMES.CUSTOM_ERROR],
["FATAL", TOKEN_NAMES.CUSTOM_FATAL],
[/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3})Z/, TOKEN_NAMES.CUSTOM_DATE],
[/^[\t ]*at.*$/, TOKEN_NAMES.CUSTOM_EXCEPTION],
[/(\d+(?:\.\d+)?([eE])([+-])[0-9](\.[0-9])?|\d+(?:\.\d+)?)/, TOKEN_NAMES.CUSTOM_NUMBER],
junhaoliao marked this conversation as resolved.
Show resolved Hide resolved
/* eslint-enable @stylistic/js/array-element-newline */
],
},
});
};

export {
LOG_LANGUAGE_NAME,
setupCustomLogLanguage,
};
45 changes: 45 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {THEME_NAME} from "../../../typings/config";
import {TOKEN_NAMES} from "./typings";


/**
* Sets up custom themes for the Monaco editor.
*/
const setupThemes = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: Grammatically, this should be setUpThemes since setup is a noun, not a verb. Feel free to ignore if you think it's more confusing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about initThemes?

On the other hand, for consistency we should rename the other functions as well. Any objection if we do the renaming in the same PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm, that might touch a lot of places. We could leave it as setupXxx for now and do the refactoring in another PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

monaco.editor.defineTheme(THEME_NAME.DARK, {
base: "vs-dark",
inherit: true,
rules: [
{token: TOKEN_NAMES.CUSTOM_INFO, foreground: "#098658"},
{token: TOKEN_NAMES.CUSTOM_WARN, foreground: "#ce9178"},
{token: TOKEN_NAMES.CUSTOM_ERROR, foreground: "#ce9178", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_FATAL, foreground: "#ce9178", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_DATE, foreground: "#529955"},
{token: TOKEN_NAMES.CUSTOM_EXCEPTION, foreground: "#ce723b", fontStyle: "italic"},
{token: TOKEN_NAMES.CUSTOM_NUMBER, foreground: "#3f9ccb"},
{token: TOKEN_NAMES.COMMENT, foreground: "#008000"},
],
colors: {
"editor.lineHighlightBackground": "#3c3c3c",
},
});
monaco.editor.defineTheme(THEME_NAME.LIGHT, {
base: "vs",
inherit: true,
rules: [
{token: TOKEN_NAMES.CUSTOM_INFO, foreground: "#098658"},
{token: TOKEN_NAMES.CUSTOM_WARN, foreground: "#b81560"},
{token: TOKEN_NAMES.CUSTOM_ERROR, foreground: "#ac1515", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_FATAL, foreground: "#ac1515", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_DATE, foreground: "#008000"},
{token: TOKEN_NAMES.CUSTOM_EXCEPTION, foreground: "#ce723b", fontStyle: "italic"},
{token: TOKEN_NAMES.CUSTOM_NUMBER, foreground: "#3f9ccb"},
],
colors: {},
});
};


export {setupThemes};
Henry8192 marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 12 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
import {ACTION_NAME} from "../../../utils/actions";


enum TOKEN_NAMES {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum TOKEN_NAMES {
enum TOKEN_NAME {

Plural naming is reserved for arrays.

CUSTOM_INFO = "customInfo",
CUSTOM_WARN = "customEarn",
junhaoliao marked this conversation as resolved.
Show resolved Hide resolved
CUSTOM_ERROR = "customError",
CUSTOM_FATAL = "customFatal",
CUSTOM_DATE = "customDate",
CUSTOM_EXCEPTION = "customException",
CUSTOM_NUMBER = "customNumber",
COMMENT = "comment",
}

/**
* Gets called when the cursor position is explicitly changed in the editor.
*
Expand Down Expand Up @@ -55,6 +66,7 @@ interface CustomMonacoEditorHandlers {
onCustomAction?: CustomActionCallback,
}

export {TOKEN_NAMES};
export type {
BeforeMountCallback,
BeforeTextUpdateCallback,
Expand Down
9 changes: 9 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import {
setupFocusOnBacktickDown,
setupMobileZoom,
} from "./actions";
import {
LOG_LANGUAGE_NAME,
setupCustomLogLanguage,
} from "./language";
import {setupThemes} from "./theme";
Henry8192 marked this conversation as resolved.
Show resolved Hide resolved
import {CustomMonacoEditorHandlers} from "./typings";


Expand Down Expand Up @@ -38,12 +43,16 @@ const createMonacoEditor = (
actions: ActionType[],
handlers: CustomMonacoEditorHandlers
): monaco.editor.IStandaloneCodeEditor => {
setupCustomLogLanguage();
setupThemes();

const editor = monaco.editor.create(
editorContainer,
{
// eslint-disable-next-line no-warning-comments
// TODO: Add custom observer to debounce automatic layout
automaticLayout: true,
language: LOG_LANGUAGE_NAME,
maxTokenizationLineLength: 30_000,
mouseWheelZoom: true,
readOnly: true,
Expand Down
40 changes: 25 additions & 15 deletions new-log-viewer/src/components/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import {

import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {useColorScheme} from "@mui/joy";

import {StateContext} from "../../contexts/StateContextProvider";
import {
updateWindowUrlHashParams,
UrlContext,
} from "../../contexts/UrlContextProvider";
import {Nullable} from "../../typings/common";
import {CONFIG_KEY} from "../../typings/config";
import {
CONFIG_KEY,
THEME_NAME,
} from "../../typings/config";
import {BeginLineNumToLogEventNumMap} from "../../typings/worker";
import {
ACTION_NAME,
Expand All @@ -36,12 +41,28 @@ import {goToPositionAndCenter} from "./MonacoInstance/utils";
import "./index.css";


/**
* Resets the cached page size in case it causes a client OOM. If it doesn't, the saved value
* will be restored when {@link restoreCachedPageSize} is called.
*/
const resetCachedPageSize = () => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was pulled out from Editor to avoid max lines lint violation.

const error = setConfig(
{key: CONFIG_KEY.PAGE_SIZE, value: CONFIG_DEFAULT[CONFIG_KEY.PAGE_SIZE]}
);

if (null !== error) {
console.error(`Unexpected error returned by setConfig(): ${error}`);
}
};

/**
* Renders a read-only editor for viewing logs.
*
* @return
*/
const Editor = () => {
const {mode, systemMode} = useColorScheme();

const {beginLineNumToLogEventNum, logData, numEvents} = useContext(StateContext);
const {logEventNum} = useContext(UrlContext);

Expand Down Expand Up @@ -100,20 +121,6 @@ const Editor = () => {
});
}, []);

/**
* Resets the cached page size in case it causes a client OOM. If it doesn't, the saved value
* will be restored when {@link restoreCachedPageSize} is called.
*/
const resetCachedPageSize = useCallback(() => {
const error = setConfig(
{key: CONFIG_KEY.PAGE_SIZE, value: CONFIG_DEFAULT[CONFIG_KEY.PAGE_SIZE]}
);

if (null !== error) {
console.error(`Unexpected error returned by setConfig(): ${error}`);
}
}, []);

/**
* Restores the cached page size that was unset in {@link resetCachedPageSize};
*/
Expand Down Expand Up @@ -192,6 +199,9 @@ const Editor = () => {
beforeTextUpdate={resetCachedPageSize}
lineNum={lineNum}
text={logData}
themeName={(("system" === mode) ?
systemMode :
mode) ?? THEME_NAME.DARK}
onCursorExplicitPosChange={handleCursorExplicitPosChange}
onCustomAction={handleEditorCustomAction}
onMount={handleMount}
Expand Down
Loading