This commit is contained in:
Daniel Imms
2016-10-01 14:37:15 -07:00
parent c2a3cb7ee5
commit bf4f63a0e6
4 changed files with 177 additions and 73 deletions

View File

@@ -4,7 +4,8 @@
"description": "Generates editor/terminal themes using a set of colors",
"main": "dist/index.js",
"scripts": {
"build": "typings install && tsc"
"build": "typings install && tsc",
"start": "node dist/index.js"
},
"author": "Tyriar",
"license": "MIT",

View File

@@ -2,77 +2,26 @@
import * as fs from 'fs';
import * as path from 'path';
console.log('test');
interface IColorSet {
ansiGroups?: {
ansiNormal?: IAnsiColorSet;
ansiBright?: IAnsiColorSet;
}
syntaxGroups?: {
constant?: string;
identifier?: string;
statement?: string;
type?: string;
global?: string;
emphasis?: string;
special?: string;
trivial?: string;
}
uiGroups?: {
userActionNeeded?: string;
userCurrentState?: string;
backgroundState?: string;
background?: string;
foreground?: string;
}
}
interface IAnsiColorSet {
black?: string;
red?: string;
green?: string;
yellow?: string;
blue?: string;
magenta?: string;
cyan?: string;
white?: string;
}
interface IThemeGenerator {
generateTheme(colorSet: IColorSet): string;
}
interface IVscodeJsonTheme {
name?: string;
include?: string;
settings?: any[];
}
class VscodeThemeGenerator implements IThemeGenerator {
public generateTheme(colorSet: IColorSet): string {
let theme: IVscodeJsonTheme = {};
theme.name = 'Generated theme';
theme.settings = [];
if (colorSet.syntaxGroups.identifier) {
theme.settings.push({
'name': 'Function declarations',
'scope': 'entity.name.function',
'settings': {
'foreground': colorSet.syntaxGroups.identifier
}
});
}
return JSON.stringify(theme);
}
}
import { IColorSet } from './themeGenerator'
import { VscodeThemeGenerator } from './vscodeThemeGenerator'
const colorSet: IColorSet = {
syntaxGroups: {
identifier: '#F00'
}
syntax: {
identifier: '#ffffff',
string: '#87d75f',
number: '#ffcc66',
keyword: '#ff8f7e',
functionCall: '#cae682',
storage: '#88b8f6',
comment: '#989898',
class: '#cae682',
type: '#88b8f6'
},
ui: {
background: '#151515'
}
};
const themeJson = new VscodeThemeGenerator().generateTheme(colorSet);
const themeJson = new VscodeThemeGenerator().generateTheme('Generated theme 2', colorSet);
const outputFile = path.join(__dirname, '..', 'out', 'theme.json')
fs.writeFileSync(outputFile, themeJson);

43
src/themeGenerator.ts Normal file
View File

@@ -0,0 +1,43 @@
export interface IThemeGenerator {
generateTheme(name: string, colorSet: IColorSet): string;
}
export interface IColorSet {
ansi?: {
normal?: IAnsiColorSet;
bright?: IAnsiColorSet;
}
syntax?: {
functionCall?: string;
identifier?: string;
keyword?: string;
number?: string;
storage?: string;
string?: string;
comment?: string;
class?: string;
type?: string;
}
ui?: {
background?: string;
foreground?: string;
}
/*uiGroups?: {
userActionNeeded?: string;
userCurrentState?: string;
backgroundState?: string;
background?: string;
foreground?: string;
}*/
}
export interface IAnsiColorSet {
black?: string;
red?: string;
green?: string;
yellow?: string;
blue?: string;
magenta?: string;
cyan?: string;
white?: string;
}

111
src/vscodeThemeGenerator.ts Normal file
View File

@@ -0,0 +1,111 @@
import { IColorSet, IThemeGenerator } from './themeGenerator'
export interface IVscodeJsonTheme {
name?: string;
include?: string;
globalSettings?: {
background?: string;
foreground?: string;
};
settings?: any[];
}
type SourceFetcher = (colorSet: IColorSet) => string;
type ColorGenerator = (color: string) => any;
interface IRuleGenerator {
source: SourceFetcher;
generate: ColorGenerator;
}
enum FontStyle {
NONE = 0,
ITALIC = 1 << 0,
BOLD = 1 << 1,
UNDERLINE = 1 << 2
}
function getSimpleColorGenerator(name: string, scope: string, fontStyle: number = FontStyle.NONE): (color: string) => any {
return (color: string) => {
let colorRule: any = {
'name': name,
'scope': scope,
'settings': {
'foreground': color
}
};
let fontStyleValue = '';
if (fontStyle & FontStyle.ITALIC) {
fontStyleValue += ' italic';
}
if (fontStyle & FontStyle.BOLD) {
fontStyleValue += ' bold';
}
if (fontStyle & FontStyle.UNDERLINE) {
fontStyleValue += ' underline';
}
if (fontStyleValue.length > 0) {
colorRule.settings.fontStyle = fontStyleValue.trim();
}
return colorRule;
}
}
// An ordered list of rules to be applied if the source conditions are met
const vscodeJsonThemeRules: IRuleGenerator[] = [
{ source: set => set.syntax.identifier,
generate: getSimpleColorGenerator('Identifier', 'variable') },
{ source: set => set.syntax.string,
generate: getSimpleColorGenerator('String', 'string') },
{ source: set => set.syntax.number,
generate: getSimpleColorGenerator('Number', 'constant.numeric') },
{ source: set => set.syntax.keyword,
generate: getSimpleColorGenerator('Keyword', 'keyword, modifier, language.this') },
// support/module function calls (eg. join in path.join) are colored as function calls
{ source: set => set.syntax.functionCall,
generate: getSimpleColorGenerator('Function call', 'entity.name.function, support.function') },
{ source: set => set.syntax.storage,
generate: getSimpleColorGenerator('Storage', 'storage.type') },
// TypeScript modules are colored as variables
{ source: set => set.syntax.identifier,
generate: getSimpleColorGenerator('Modules', 'module.support', FontStyle.ITALIC) },
{ source: set => set.syntax.type,
generate: getSimpleColorGenerator('Type', 'type') },
{ source: set => set.syntax.comment,
generate: getSimpleColorGenerator('Comment', 'comment', FontStyle.ITALIC) },
{ source: set => set.syntax.class,
generate: getSimpleColorGenerator('Class', 'entity.name.class', FontStyle.UNDERLINE) }
];
export class VscodeThemeGenerator implements IThemeGenerator {
public generateTheme(name: string, colorSet: IColorSet): string {
let theme: IVscodeJsonTheme = {};
theme.name = name;
theme.settings = [];
if (colorSet.ui.background) {
theme.settings.push({
'name': 'background',
'settings': {
'background': colorSet.ui.background
}
});
}
if (colorSet.ui.foreground) {
theme.settings.push({
'name': 'foreground',
'settings': {
'foreground': colorSet.ui.foreground
}
});
}
vscodeJsonThemeRules.forEach(ruleGenerator => {
try {
let color = ruleGenerator.source(colorSet);
theme.settings.push(ruleGenerator.generate(<string>color));
} catch (ex) {
// Ignore when source color does not exist
}
});
return JSON.stringify(theme);
}
}