diff --git a/src/components/EditorTextArea.tsx b/src/components/EditorTextArea.tsx index 46637cd..e53e1a0 100644 --- a/src/components/EditorTextArea.tsx +++ b/src/components/EditorTextArea.tsx @@ -17,7 +17,8 @@ import themes, { Theme } from '../style/themes'; import type { editor } from 'monaco-editor'; import { ResetFunction } from './Editor'; -import { logLanguage } from '../util/log-language'; +import { logLanguage } from '../util/languages/log'; +import { diffLanguage } from '../util/languages/diff'; import * as monaco from 'monaco-editor'; import { loader } from '@monaco-editor/react'; @@ -68,6 +69,8 @@ export default function EditorTextArea({ monaco.languages.register({ id: 'log' }); monaco.languages.setMonarchTokensProvider('log', logLanguage); + monaco.languages.register({ id: 'diff' }); + monaco.languages.setMonarchTokensProvider('diff', diffLanguage); monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ noSemanticValidation: true, diff --git a/src/style/themes.ts b/src/style/themes.ts index 28d2c68..e328a35 100644 --- a/src/style/themes.ts +++ b/src/style/themes.ts @@ -64,6 +64,9 @@ const themes: Themes = { logWarning: '#d29922', // yellow.3 logDate: '#33B3AE', // teal.3 logException: '#f8e3a1', // yellow.0 + diffMeta: '#33B3AE', // teal.3 + diffAddition: '#3fb950', // green.3 + diffDeletion: '#f85149', // red.4 }, }), }, @@ -100,6 +103,9 @@ const themes: Themes = { logWarning: '#d4a72c', // yellow.3 logDate: '#136061', // teal.6 logException: '#7d4e00', // yellow.6 + diffMeta: '#136061', // teal.6 + diffAddition: '#2da44e', // green.4 + diffDeletion: '#cf222e', // red.5 }, }), }, @@ -114,12 +120,15 @@ const themes: Themes = { color: '#586e75', backgroundColor: '#44475a', }, - editor: addLogColors(dracula as editor.IStandaloneThemeData, { - info: '#50FA7B', // green - error: '#FF5555', // red - warning: '#FFB86C', // orange - date: '#BD93F9', // purple - exception: '#F1FA8C', // yellow + editor: addExtraColors(dracula as editor.IStandaloneThemeData, { + logInfo: '#50FA7B', // green + logError: '#FF5555', // red + logWarning: '#FFB86C', // orange + logDate: '#BD93F9', // purple + logException: '#F1FA8C', // yellow + diffMeta: '#BD93F9', // purple + diffAddition: '#50FA7B', // green + diffDeletion: '#FF5555', // red }), }, 'monokai': { @@ -133,12 +142,15 @@ const themes: Themes = { color: '#49483E', backgroundColor: '#3E3D32', }, - editor: addLogColors(monokai as editor.IStandaloneThemeData, { - info: '#a6e22e', // green - error: '#f92672', // red - warning: '#fd971f', // orange - date: '#AB9DF2', // purple - exception: '#F1FA8C', // yellow + editor: addExtraColors(monokai as editor.IStandaloneThemeData, { + logInfo: '#a6e22e', // green + logError: '#f92672', // red + logWarning: '#fd971f', // orange + logDate: '#AB9DF2', // purple + logException: '#F1FA8C', // yellow + diffMeta: '#AB9DF2', // purple + diffAddition: '#a6e22e', // green + diffDeletion: '#f92672', // red }), }, 'solarized': { @@ -152,12 +164,15 @@ const themes: Themes = { color: '#93a1a1', // base1 backgroundColor: '#073642', // base02 }, - editor: addLogColors(solarizedDark as editor.IStandaloneThemeData, { - info: '#268bd2', // blue - error: '#dc322f', // red - warning: '#b58900', // yellow - date: '#2aa198', // cyan - exception: '#859900', // green + editor: addExtraColors(solarizedDark as editor.IStandaloneThemeData, { + logInfo: '#268bd2', // blue + logError: '#dc322f', // red + logWarning: '#b58900', // yellow + logDate: '#2aa198', // cyan + logException: '#859900', // green + diffMeta: '#2aa198', // cyan + diffAddition: '#859900', // green + diffDeletion: '#dc322f', // red }), }, 'solarized-light': { @@ -171,18 +186,32 @@ const themes: Themes = { color: '#586e75', // base01 backgroundColor: '#eee8d5', // base2 }, - editor: addLogColors(solarizedLight as editor.IStandaloneThemeData, { - info: '#268bd2', // blue - error: '#dc322f', // red - warning: '#b58900', // yellow - date: '#2aa198', // cyan - exception: '#859900', // green + editor: addExtraColors(solarizedLight as editor.IStandaloneThemeData, { + logInfo: '#268bd2', // blue + logError: '#dc322f', // red + logWarning: '#b58900', // yellow + logDate: '#2aa198', // cyan + logException: '#859900', // green + diffMeta: '#2aa198', // cyan + diffAddition: '#859900', // green + diffDeletion: '#dc322f', // red }), }, }; export default themes; +interface ExtraColors { + logInfo: Color; + logError: Color; + logWarning: Color; + logDate: Color; + logException: Color; + diffMeta: Color; + diffAddition: Color; + diffDeletion: Color; +} + interface MonacoThemeProps { base: 'vs' | 'vs-dark'; colors: { @@ -198,12 +227,7 @@ interface MonacoThemeProps { keyword: Color; type: Color; variable: Color; - logInfo: Color; - logError: Color; - logWarning: Color; - logDate: Color; - logException: Color; - }; + } & ExtraColors; } export function makeMonacoTheme( @@ -246,6 +270,9 @@ export function makeMonacoTheme( { token: 'warning.log', foreground: colors.logWarning }, { token: 'date.log', foreground: colors.logDate }, { token: 'exception.log', foreground: colors.logException }, + { token: 'meta.diff', foreground: colors.diffMeta }, + { token: 'addition.diff', foreground: colors.diffAddition }, + { token: 'deletion.diff', foreground: colors.diffDeletion }, ], colors: { 'editor.background': `#${colors.background}`, @@ -254,28 +281,23 @@ export function makeMonacoTheme( }; } -interface LogColors { - info: Color; - error: Color; - warning: Color; - date: Color; - exception: Color; -} - -export function addLogColors( +export function addExtraColors( theme: editor.IStandaloneThemeData, - logColors: LogColors + extraColors: ExtraColors ): editor.IStandaloneThemeData { const colors = Object.fromEntries( - Object.entries(logColors).map(([key, color]) => [key, color.substring(1)]) - ) as Record; + Object.entries(extraColors).map(([key, color]) => [key, color.substring(1)]) + ) as Record; theme.rules.push( ...[ - { token: 'info.log', foreground: colors.info }, - { token: 'error.log', foreground: colors.error, fontStyle: 'bold' }, - { token: 'warning.log', foreground: colors.warning }, - { token: 'date.log', foreground: colors.date }, - { token: 'exception.log', foreground: colors.exception }, + { token: 'info.log', foreground: colors.logInfo }, + { token: 'error.log', foreground: colors.logError, fontStyle: 'bold' }, + { token: 'warning.log', foreground: colors.logWarning }, + { token: 'date.log', foreground: colors.logDate }, + { token: 'exception.log', foreground: colors.logException }, + { token: 'meta.diff', foreground: colors.diffMeta }, + { token: 'addition.diff', foreground: colors.diffAddition }, + { token: 'deletion.diff', foreground: colors.diffDeletion }, ] ); return theme; diff --git a/src/util/highlighting.ts b/src/util/highlighting.ts index 30d1e21..c046b04 100644 --- a/src/util/highlighting.ts +++ b/src/util/highlighting.ts @@ -17,10 +17,10 @@ export const languages = { 'go', 'lua', 'swift', - 'c' + 'c', ], web: ['html', 'css', 'scss', 'php', 'graphql'], - misc: ['dockerfile', 'markdown', 'proto'], + misc: ['diff', 'dockerfile', 'markdown', 'proto'], }; export const languageIds = Object.values(languages).flat(1); diff --git a/src/util/languages/diff.ts b/src/util/languages/diff.ts new file mode 100644 index 0000000..808ab96 --- /dev/null +++ b/src/util/languages/diff.ts @@ -0,0 +1,30 @@ +import { languages } from 'monaco-editor'; + +export const diffLanguage: languages.IMonarchLanguage = { + defaultToken: '', + tokenizer: { + root: [ + // Meta lines (e.g., @@ -1,2 +3,4 @@) + [/@@@ +-\d+,\d+ +\+\d+,\d+ +@@@/, 'meta'], + [/^\*\*\* +\d+,\d+ +\*\*\*\*$/, 'meta'], + [/^--- +\d+,\d+ +----$/, 'meta'], + + // Comments + [/Index: .*/, 'comment'], + [/^index.*/, 'comment'], + [/={3,}/, 'comment'], + [/^-{3}.*/, 'comment'], + [/^\*{3} .*/, 'comment'], + [/^\+{3}.*/, 'comment'], + [/^diff --git.*/, 'comment'], + [/^\*{15}$/, 'comment'], + + // Additions + [/^\+.*/, 'addition'], + [/^!.*/, 'addition'], + + // Deletions + [/^-.*/, 'deletion'], + ], + }, +}; diff --git a/src/util/log-language.ts b/src/util/languages/log.ts similarity index 100% rename from src/util/log-language.ts rename to src/util/languages/log.ts