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

Add support for loading custom themes #53

Merged
merged 1 commit into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ git config split-diffs.theme-name monochrome-light

![Screenshot of Monochrome Light theme](screenshots/monochrome-light.png?raw=true)

## Custom Themes

Default themes are loaded from the `git-split-diffs` bundle. To load a custom theme, set `theme-directory` in git config and create a `{theme-name}.json` file in that directory with the theme's definition. You can use one of the existing themes in [themes/](https://github.com/banga/git-split-diffs/tree/main/themes) as a starting point.

```
git config split-diffs.theme-directory </path/to/theme>
git config split-diffs.theme-name <name>
```

This will use `/path/to/theme/name.json` as the theme.

## Performance

Tested by measuring the time it took to pipe the output `git log -p` to `/dev/null` via `git-split-diffs` with the default theme:
Expand All @@ -191,6 +202,10 @@ See [#narrow-terminals](#narrow-terminals)

Text coloring is implemented using Chalk which supports [various levels of color](https://github.com/chalk/chalk#supportscolor). If Chalk is producing fewer colors than your terminal supports, try overriding Chalk's detection using a variation of the `--color` flag, e.g. `--color=16m` for true color. See Chalk's documentation or [this useful gist on terminal support](https://gist.github.com/XVilka/8346728) if issues persist.

### Want to remove background colors from a theme?

See [#custom-themes](#custom-themes) for instructions on customizing themes. Removing `backgroundColor` should usually work.

## Acknowledgements

- [diff-so-fancy](https://github.com/so-fancy/diff-so-fancy) for showing what's possible
Expand Down
4 changes: 1 addition & 3 deletions src/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ export type Config = Theme & {
HIGHLIGHT_LINE_CHANGES: boolean;
};

export const DEFAULT_THEME_NAME = 'dark';

export const CONFIG_DEFAULTS: Omit<Config, keyof Theme> = {
MIN_LINE_WIDTH: 80,
WRAP_LINES: true,
HIGHLIGHT_LINE_CHANGES: true,
};

export function getConfig(gitConfig: GitConfig): Config {
const theme = loadTheme(gitConfig.THEME_NAME ?? DEFAULT_THEME_NAME);
const theme = loadTheme(gitConfig.THEME_DIRECTORY, gitConfig.THEME_NAME);

return {
...CONFIG_DEFAULTS,
Expand Down
6 changes: 5 additions & 1 deletion src/getGitConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DEFAULT_THEME_NAME } from './getConfig';
import {
DEFAULT_MIN_LINE_WIDTH,
DEFAULT_THEME_DIRECTORY,
DEFAULT_THEME_NAME,
GitConfig,
getGitConfig,
} from './getGitConfig';
Expand All @@ -10,6 +11,7 @@ const DEFAULT_CONFIG: GitConfig = {
HIGHLIGHT_LINE_CHANGES: true,
MIN_LINE_WIDTH: DEFAULT_MIN_LINE_WIDTH,
THEME_NAME: DEFAULT_THEME_NAME,
THEME_DIRECTORY: DEFAULT_THEME_DIRECTORY,
};

describe('getGitConfig', () => {
Expand All @@ -24,13 +26,15 @@ split-diffs.wrap-lines=false
split-diffs.highlight-line-changes=false
split-diffs.min-line-width=40
split-diffs.theme-name=arctic
split-diffs.theme-directory=/tmp
split-diffs.syntax-highlighting-theme=dark-plus
`)
).toEqual({
WRAP_LINES: false,
HIGHLIGHT_LINE_CHANGES: false,
MIN_LINE_WIDTH: 40,
THEME_NAME: 'arctic',
THEME_DIRECTORY: '/tmp',
SYNTAX_HIGHLIGHTING_THEME: 'dark-plus',
});
});
Expand Down
11 changes: 11 additions & 0 deletions src/getGitConfig.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import path from 'path';
import { fileURLToPath } from 'url';

export type GitConfig = {
MIN_LINE_WIDTH: number;
WRAP_LINES: boolean;
HIGHLIGHT_LINE_CHANGES: boolean;
THEME_DIRECTORY: string;
THEME_NAME: string;
SYNTAX_HIGHLIGHTING_THEME?: string;
};

export const DEFAULT_MIN_LINE_WIDTH = 80;
export const DEFAULT_THEME_DIRECTORY = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'..',
'themes'
);
export const DEFAULT_THEME_NAME = 'dark';

const GIT_CONFIG_KEY_PREFIX = 'split-diffs';
Expand Down Expand Up @@ -44,6 +53,8 @@ export function getGitConfig(configString: string): GitConfig {
MIN_LINE_WIDTH: minLineWidth,
WRAP_LINES: rawConfig['wrap-lines'] !== 'false',
HIGHLIGHT_LINE_CHANGES: rawConfig['highlight-line-changes'] !== 'false',
THEME_DIRECTORY:
rawConfig['theme-directory'] ?? DEFAULT_THEME_DIRECTORY,
THEME_NAME: rawConfig['theme-name'] ?? DEFAULT_THEME_NAME,
SYNTAX_HIGHLIGHTING_THEME: rawConfig['syntax-highlighting-theme'],
};
Expand Down
20 changes: 14 additions & 6 deletions src/previewTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ import { Config } from './getConfig';
import { getContextForConfig } from './context';
import { loadTheme } from './themes';
import { transformContentsStreaming } from './transformContentsStreaming';
import { DEFAULT_THEME_DIRECTORY } from './getGitConfig';

const CONFIG = {
MIN_LINE_WIDTH: 40,
WRAP_LINES: true,
HIGHLIGHT_LINE_CHANGES: true,
};

async function previewTheme(themeName: string, content: string) {
const theme = loadTheme(themeName);
async function previewTheme(
themeDirectory: string,
themeName: string,
content: string
) {
const theme = loadTheme(themeDirectory, themeName);

const { rows, columns } = terminalSize();
const config: Config = {
Expand All @@ -41,19 +46,22 @@ async function previewTheme(themeName: string, content: string) {
}

function main() {
if (process.argv.length !== 4) {
console.error(`Usage: ${process.argv[1]} <sha> <theme name>`);
if (process.argv.length < 4) {
console.error(
`Usage: ${process.argv[1]} <sha> <theme name> [theme directory]`
);
process.exit(1);
}

const [, , sha, themeName] = process.argv;
const [, , sha, themeName, themeDirectory = DEFAULT_THEME_DIRECTORY] =
process.argv;

const content = execSync(`git show ${sha}`).toString();

// Clear screen
process.stdout.write('\x1bc');

previewTheme(themeName, content);
previewTheme(themeDirectory, themeName, content);
}

main();
17 changes: 7 additions & 10 deletions src/themes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import * as assert from 'assert';
import * as path from 'path';
import * as fs from 'fs';
import { fileURLToPath } from 'url';
import * as shiki from 'shiki';

const THEMES_DIR = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'..',
'themes'
);
/**
* Colors are always specified as hex strings
*/
Expand Down Expand Up @@ -165,14 +159,17 @@ export function parseColorDefinition(definition: ColorDefinition): ThemeColor {
};
}

function loadThemeDefinition(themeName: string): ThemeDefinition {
function loadThemeDefinition(
themesDir: string,
themeName: string
): ThemeDefinition {
return JSON.parse(
fs.readFileSync(path.join(THEMES_DIR, `${themeName}.json`)).toString()
fs.readFileSync(path.join(themesDir, `${themeName}.json`)).toString()
) as ThemeDefinition;
}

export function loadTheme(themeName: string): Theme {
const themeDefinition = loadThemeDefinition(themeName);
export function loadTheme(themesDir: string, themeName: string): Theme {
const themeDefinition = loadThemeDefinition(themesDir, themeName);

const theme: Partial<Theme> = {
SYNTAX_HIGHLIGHTING_THEME: themeDefinition.SYNTAX_HIGHLIGHTING_THEME,
Expand Down