From 85ca553087fcf5e3a5102e4cb7e1154fde185adc Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 30 Jul 2025 15:54:59 +0200 Subject: [PATCH 01/16] feat(syntax): add support for Haskell (#360) --- .../src/theme/semanticTokens.ts | 6 ++ .../src/theme/tokens/haskell.ts | 94 +++++++++++++++++++ .../catppuccin-vsc/src/theme/tokens/index.ts | 2 + 3 files changed, 102 insertions(+) create mode 100644 packages/catppuccin-vsc/src/theme/tokens/haskell.ts diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index 267c2457..1fa43010 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -34,6 +34,12 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { "type.defaultLibrary:go": { foreground: palette.mauve }, "variable.readonly.defaultLibrary:go": { foreground: palette.mauve }, + // Haskell: + "enumMember:haskell": { foreground: palette.blue }, // data constructor + "enum:haskell": { foreground: palette.yellow }, // type constructor + "class:haskell": { foreground: palette.yellow, fontStyle: "" }, // typeclass + "interface:haskell": { foreground: palette.pink }, // type family + // TOML syntax tomlArrayKey: { foreground: palette.blue, fontStyle: "" }, tomlTableKey: { foreground: palette.blue, fontStyle: "" }, diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts new file mode 100644 index 00000000..f741ce6d --- /dev/null +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -0,0 +1,94 @@ +import type { TextmateColors, ThemeContext } from "@/types"; + +const tokens = (context: ThemeContext): TextmateColors => { + const { palette } = context; + + /* + should preferrably appear visually distinct: + - data constructors -> use blue + - type constructors -> use yellow+italic + - typeclasses -> use yellow + */ + + return [ + { + name: "data constructors", + scope: [ + "variable.other.enummember", + "meta.declaration.data constant.other", + "constant.other", + ], + settings: { foreground: palette.blue }, + // like functions (capitalized -> still visually distinct) + }, + { + name: "type constructors", + scope: ["entity.name.type", "storage.type"], + settings: { + foreground: palette.yellow, + fontStyle: "italic", + }, + }, + { + name: "typeclasses", + scope: ["entity.name.type.class"], + settings: { + foreground: palette.yellow, + fontStyle: "", + }, + }, + { + name: "module name", + scope: "meta.declaration.module.haskell entity.name.namespace.haskell", + settings: { + foreground: palette.peach, // as in Rust + }, + }, + { + name: "imports", + scope: ["entity.name.namespace"], + settings: { foreground: palette.rosewater }, + }, + { + name: "type parameters", + scope: ["entity.name.type.parameter", "variable.other.generic-type"], + settings: { foreground: palette.maroon }, + }, + { + name: "pragma keywords", + scope: [" keyword.other.preprocessor"], + settings: { foreground: palette.red }, + }, + { + name: "pragma arguments", + scope: [" keyword.other.preprocessor.extension"], + settings: { foreground: palette.peach }, + }, + { + name: "preprocessor directives", + scope: ["meta.preprocessor"], + settings: { foreground: palette.rosewater }, + }, + + { + name: "type families", + scope: ["entity.name.type.interface"], + settings: { foreground: palette.pink }, + // we need something distinct from typeclasses + // -> pick pink which is used for meta-variables in Rust + }, + { + name: "getters in data constructors/records", + scope: ["variable.other.property", "variable.other.member"], + settings: { foreground: palette.blue }, + }, + { + name: "fix else keyword", + scope: ["keyword.control.else.haskell"], + settings: { foreground: palette.mauve }, + // catppuccin default sets to yellow considering it preprocessor-like, which it is not for Haskell + }, + ]; +}; + +export default tokens; diff --git a/packages/catppuccin-vsc/src/theme/tokens/index.ts b/packages/catppuccin-vsc/src/theme/tokens/index.ts index 7ea7e4ca..ec68c608 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/index.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/index.ts @@ -9,6 +9,7 @@ import dotenv from "./dotenv"; import gdscript from "./gdscript"; import golang from "./golang"; import graphql from "./graphql"; +import haskell from "./haskell"; import html from "./html"; import java from "./java"; import javascript from "./javascript"; @@ -296,6 +297,7 @@ export default function tokens(context: ThemeContext): TextmateColors { gdscript, golang, graphql, + haskell, html, java, javascript, From 033cc6602cfd5a33179503ec2f85c0bf4e8914df Mon Sep 17 00:00:00 2001 From: sgoudham Date: Mon, 25 Aug 2025 16:19:53 +0100 Subject: [PATCH 02/16] fix(haskell): remove rosewater override for imports --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index f741ce6d..780c2b41 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -13,11 +13,7 @@ const tokens = (context: ThemeContext): TextmateColors => { return [ { name: "data constructors", - scope: [ - "variable.other.enummember", - "meta.declaration.data constant.other", - "constant.other", - ], + scope: ["meta.declaration.data constant.other", "constant.other"], settings: { foreground: palette.blue }, // like functions (capitalized -> still visually distinct) }, @@ -44,11 +40,6 @@ const tokens = (context: ThemeContext): TextmateColors => { foreground: palette.peach, // as in Rust }, }, - { - name: "imports", - scope: ["entity.name.namespace"], - settings: { foreground: palette.rosewater }, - }, { name: "type parameters", scope: ["entity.name.type.parameter", "variable.other.generic-type"], From 4ad1aed75879df0ef9c52dab36f8b13166898a8f Mon Sep 17 00:00:00 2001 From: sgoudham Date: Mon, 25 Aug 2025 16:58:20 +0100 Subject: [PATCH 03/16] fix(haskell): be specific for type constructors --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 780c2b41..a8ccfad7 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -19,7 +19,7 @@ const tokens = (context: ThemeContext): TextmateColors => { }, { name: "type constructors", - scope: ["entity.name.type", "storage.type"], + scope: ["storage.type.haskell"], settings: { foreground: palette.yellow, fontStyle: "italic", From 0909328e16e51ea1ab31cf35e7be38272b55d9c3 Mon Sep 17 00:00:00 2001 From: sgoudham Date: Mon, 25 Aug 2025 18:34:40 +0100 Subject: [PATCH 04/16] chore: remove whitespace --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index a8ccfad7..14c5badc 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -47,12 +47,12 @@ const tokens = (context: ThemeContext): TextmateColors => { }, { name: "pragma keywords", - scope: [" keyword.other.preprocessor"], + scope: ["keyword.other.preprocessor"], settings: { foreground: palette.red }, }, { name: "pragma arguments", - scope: [" keyword.other.preprocessor.extension"], + scope: ["keyword.other.preprocessor.extension"], settings: { foreground: palette.peach }, }, { From 6631b41dd802c2e965208e5533adbd30fec15247 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 01:00:44 +0200 Subject: [PATCH 05/16] style(haskell): normalize formatting, adjust names --- .../src/theme/semanticTokens.ts | 17 ++++-- .../src/theme/tokens/haskell.ts | 52 +++++++++++++------ 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index 1fa43010..b2efc5ed 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -35,10 +35,19 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { "variable.readonly.defaultLibrary:go": { foreground: palette.mauve }, // Haskell: - "enumMember:haskell": { foreground: palette.blue }, // data constructor - "enum:haskell": { foreground: palette.yellow }, // type constructor - "class:haskell": { foreground: palette.yellow, fontStyle: "" }, // typeclass - "interface:haskell": { foreground: palette.pink }, // type family + "enumMember:haskell": /* data constructors */ { + foreground: palette.blue, + }, + "enum:haskell": /* types */ { + foreground: palette.yellow, + }, + "class:haskell": /* typeclasses */ { + foreground: palette.yellow, + fontStyle: "", + }, + "interface:haskell": /* type families */ { + foreground: palette.pink, + }, // TOML syntax tomlArrayKey: { foreground: palette.blue, fontStyle: "" }, diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 14c5badc..0adb47b6 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -1,24 +1,31 @@ import type { TextmateColors, ThemeContext } from "@/types"; -const tokens = (context: ThemeContext): TextmateColors => { - const { palette } = context; +/* + +STYLING CHOICES +--------------- - /* should preferrably appear visually distinct: - data constructors -> use blue - - type constructors -> use yellow+italic + - types -> use yellow+italic - typeclasses -> use yellow - */ + +*/ + +const tokens = (context: ThemeContext): TextmateColors => { + const { palette } = context; return [ { name: "data constructors", scope: ["meta.declaration.data constant.other", "constant.other"], - settings: { foreground: palette.blue }, + settings: { + foreground: palette.blue, + }, // like functions (capitalized -> still visually distinct) }, { - name: "type constructors", + name: "types", scope: ["storage.type.haskell"], settings: { foreground: palette.yellow, @@ -43,40 +50,53 @@ const tokens = (context: ThemeContext): TextmateColors => { { name: "type parameters", scope: ["entity.name.type.parameter", "variable.other.generic-type"], - settings: { foreground: palette.maroon }, + settings: { + foreground: palette.maroon, + }, }, { - name: "pragma keywords", + name: "special words (builtin constants-like)", scope: ["keyword.other.preprocessor"], - settings: { foreground: palette.red }, + settings: { + foreground: palette.red, + }, }, { name: "pragma arguments", scope: ["keyword.other.preprocessor.extension"], - settings: { foreground: palette.peach }, + settings: { + foreground: palette.peach, + }, }, { name: "preprocessor directives", scope: ["meta.preprocessor"], - settings: { foreground: palette.rosewater }, + settings: { + foreground: palette.rosewater, + }, }, - { name: "type families", scope: ["entity.name.type.interface"], - settings: { foreground: palette.pink }, + settings: { + foreground: palette.pink, + }, // we need something distinct from typeclasses // -> pick pink which is used for meta-variables in Rust }, { name: "getters in data constructors/records", scope: ["variable.other.property", "variable.other.member"], - settings: { foreground: palette.blue }, + settings: { + foreground: palette.blue, + }, }, { name: "fix else keyword", scope: ["keyword.control.else.haskell"], - settings: { foreground: palette.mauve }, + settings: { + foreground: palette.mauve, + }, // catppuccin default sets to yellow considering it preprocessor-like, which it is not for Haskell }, ]; From e876706db83f81ec9b698f7218d201f264ddb5eb Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 19:02:41 +0200 Subject: [PATCH 06/16] fix(haskell): remove use of never-assigned scopes The removed scopes were redundant since they are not among the scopes assigned by the only in-use Haskell textMate grammar (https://github.com/JustusAdam/language-haskell). The tokens/haskell.ts rules named "typclasses" and "type families" each relied on only such a scope and these rules are therefore removed from the file. Styling of typeclasses and type families is still possible through semantic tokens though. --- .../src/theme/semanticTokens.ts | 1 + .../src/theme/tokens/haskell.ts | 25 ++++--------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index b2efc5ed..23178b77 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -47,6 +47,7 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { }, "interface:haskell": /* type families */ { foreground: palette.pink, + // needs something distinct from typeclasses -> pick pink which is used for meta-variables in Rust }, // TOML syntax diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 0adb47b6..edb5a425 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -8,7 +8,9 @@ STYLING CHOICES should preferrably appear visually distinct: - data constructors -> use blue - types -> use yellow+italic - - typeclasses -> use yellow + - typeclasses [1] -> use yellow + +[1]: typeclasses are not distinguishable from types with only textMate scopes; requires semantic tokens */ @@ -32,14 +34,6 @@ const tokens = (context: ThemeContext): TextmateColors => { fontStyle: "italic", }, }, - { - name: "typeclasses", - scope: ["entity.name.type.class"], - settings: { - foreground: palette.yellow, - fontStyle: "", - }, - }, { name: "module name", scope: "meta.declaration.module.haskell entity.name.namespace.haskell", @@ -49,7 +43,7 @@ const tokens = (context: ThemeContext): TextmateColors => { }, { name: "type parameters", - scope: ["entity.name.type.parameter", "variable.other.generic-type"], + scope: ["variable.other.generic-type"], settings: { foreground: palette.maroon, }, @@ -75,18 +69,9 @@ const tokens = (context: ThemeContext): TextmateColors => { foreground: palette.rosewater, }, }, - { - name: "type families", - scope: ["entity.name.type.interface"], - settings: { - foreground: palette.pink, - }, - // we need something distinct from typeclasses - // -> pick pink which is used for meta-variables in Rust - }, { name: "getters in data constructors/records", - scope: ["variable.other.property", "variable.other.member"], + scope: ["variable.other.member"], settings: { foreground: palette.blue, }, From 02e2535e537257144e80bb2cf0f24e9d42bbf638 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 01:05:08 +0200 Subject: [PATCH 07/16] fix(haskell): remove module name override --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index edb5a425..e12c9286 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -34,13 +34,6 @@ const tokens = (context: ThemeContext): TextmateColors => { fontStyle: "italic", }, }, - { - name: "module name", - scope: "meta.declaration.module.haskell entity.name.namespace.haskell", - settings: { - foreground: palette.peach, // as in Rust - }, - }, { name: "type parameters", scope: ["variable.other.generic-type"], From 3941682ebde435ec1abecab979054a016faa5def Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 01:16:46 +0200 Subject: [PATCH 08/16] fix(haskell): make all selectors haskell-specific --- .../src/theme/semanticTokens.ts | 3 +++ .../src/theme/tokens/haskell.ts | 25 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index 23178b77..252b0a1f 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -49,6 +49,9 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { foreground: palette.pink, // needs something distinct from typeclasses -> pick pink which is used for meta-variables in Rust }, + "property:haskell": /* getters in data constructors/records */ { + foreground: palette.blue, + }, // TOML syntax tomlArrayKey: { foreground: palette.blue, fontStyle: "" }, diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index e12c9286..5f38f86a 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -20,7 +20,10 @@ const tokens = (context: ThemeContext): TextmateColors => { return [ { name: "data constructors", - scope: ["meta.declaration.data constant.other", "constant.other"], + scope: [ + "meta.declaration.data constant.other.haskell", + "constant.other.haskell", // to hit data constr. if no semantic tokens + ], settings: { foreground: palette.blue, }, @@ -36,35 +39,45 @@ const tokens = (context: ThemeContext): TextmateColors => { }, { name: "type parameters", - scope: ["variable.other.generic-type"], + scope: ["variable.other.generic-type.haskell"], settings: { foreground: palette.maroon, }, }, { name: "special words (builtin constants-like)", - scope: ["keyword.other.preprocessor"], + scope: [ + "keyword.other.preprocessor.haskell", + "keyword.other.preprocessor.pragma.haskell", + ], settings: { foreground: palette.red, }, }, { name: "pragma arguments", - scope: ["keyword.other.preprocessor.extension"], + scope: ["keyword.other.preprocessor.extension.haskell"], settings: { foreground: palette.peach, }, }, { name: "preprocessor directives", - scope: ["meta.preprocessor"], + scope: [ + "source.haskell meta.preprocessor.c", + "source.haskell meta.preprocessor.c punctuation.definition.preprocessor.c", + "meta.preprocessor.haskell", + ], settings: { foreground: palette.rosewater, }, }, { name: "getters in data constructors/records", - scope: ["variable.other.member"], + scope: [ + "variable.other.member.haskell", + "variable.other.member.definition.haskell", + ], settings: { foreground: palette.blue, }, From 672428683b88eb61a1964b18783b51be0257eb2d Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 16:41:54 +0200 Subject: [PATCH 09/16] refactor(haskell): split preprocessor rule --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 5f38f86a..de62e014 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -62,16 +62,22 @@ const tokens = (context: ThemeContext): TextmateColors => { }, }, { - name: "preprocessor directives", + name: "C preprocessor directives", scope: [ "source.haskell meta.preprocessor.c", "source.haskell meta.preprocessor.c punctuation.definition.preprocessor.c", - "meta.preprocessor.haskell", ], settings: { foreground: palette.rosewater, }, }, + { + name: "Haskell preprocessor directives", + scope: ["meta.preprocessor.haskell"], + settings: { + foreground: palette.rosewater, + }, + }, { name: "getters in data constructors/records", scope: [ From 61fb57e84522b5697ee7793d8cd31e073ddb02a9 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 16:50:55 +0200 Subject: [PATCH 10/16] fix(haskell): use style guide colors for preprocessor --- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index de62e014..0037bc72 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -68,14 +68,15 @@ const tokens = (context: ThemeContext): TextmateColors => { "source.haskell meta.preprocessor.c punctuation.definition.preprocessor.c", ], settings: { - foreground: palette.rosewater, + foreground: palette.yellow, }, }, { name: "Haskell preprocessor directives", scope: ["meta.preprocessor.haskell"], settings: { - foreground: palette.rosewater, + foreground: palette.overlay2, + // the enclosing block comment definitions ({-#, #-}) are scoped only with the `meta` scope -> using the comment color is the best-looking choice (also, the whole thing _is_ technically a block comment) }, }, { From 95bfca6ba7482099325bc18e92d40e60209637fd Mon Sep 17 00:00:00 2001 From: Carl Date: Tue, 2 Sep 2025 00:58:29 +0200 Subject: [PATCH 11/16] feat(haskell): anticipate lavender properties --- packages/catppuccin-vsc/src/theme/semanticTokens.ts | 2 +- packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index 252b0a1f..b6763859 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -50,7 +50,7 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { // needs something distinct from typeclasses -> pick pink which is used for meta-variables in Rust }, "property:haskell": /* getters in data constructors/records */ { - foreground: palette.blue, + foreground: palette.lavender, }, // TOML syntax diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 0037bc72..bdf9cd25 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -86,7 +86,7 @@ const tokens = (context: ThemeContext): TextmateColors => { "variable.other.member.definition.haskell", ], settings: { - foreground: palette.blue, + foreground: palette.lavender, }, }, { From c84978ddc93245e23a227dc8b559f3565a3730bc Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 16:11:33 +0200 Subject: [PATCH 12/16] feat(haskell): add styling of pattern synonyms --- packages/catppuccin-vsc/src/theme/semanticTokens.ts | 4 ++++ packages/catppuccin-vsc/src/theme/tokens/haskell.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index b6763859..dd54810f 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -52,6 +52,10 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { "property:haskell": /* getters in data constructors/records */ { foreground: palette.lavender, }, + "macro:haskell": /* pattern synonyms */ { + foreground: palette.blue, + fontStyle: "", + }, // TOML syntax tomlArrayKey: { foreground: palette.blue, fontStyle: "" }, diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index bdf9cd25..1f68d703 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -23,6 +23,7 @@ const tokens = (context: ThemeContext): TextmateColors => { scope: [ "meta.declaration.data constant.other.haskell", "constant.other.haskell", // to hit data constr. if no semantic tokens + "meta.declaration.pattern constant.other.haskell", // pattern synonyms ], settings: { foreground: palette.blue, From 4b7172abb3a8d90513230e8fbb17c88e3820cc69 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 01:41:25 +0200 Subject: [PATCH 13/16] fix(haskell): make italics styling consistent --- .../catppuccin-vsc/src/theme/semanticTokens.ts | 15 +++++++++++++++ .../catppuccin-vsc/src/theme/tokens/haskell.ts | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/catppuccin-vsc/src/theme/semanticTokens.ts b/packages/catppuccin-vsc/src/theme/semanticTokens.ts index dd54810f..80714872 100644 --- a/packages/catppuccin-vsc/src/theme/semanticTokens.ts +++ b/packages/catppuccin-vsc/src/theme/semanticTokens.ts @@ -37,9 +37,15 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { // Haskell: "enumMember:haskell": /* data constructors */ { foreground: palette.blue, + fontStyle: "", }, "enum:haskell": /* types */ { foreground: palette.yellow, + fontStyle: context.options.italicKeywords ? "italic" : undefined, + }, + "type:haskell": /* type aliases */ { + foreground: palette.yellow, + fontStyle: context.options.italicKeywords ? "italic" : undefined, }, "class:haskell": /* typeclasses */ { foreground: palette.yellow, @@ -47,15 +53,24 @@ export const getSemanticTokens = (context: ThemeContext): SemanticTokens => { }, "interface:haskell": /* type families */ { foreground: palette.pink, + fontStyle: "", // needs something distinct from typeclasses -> pick pink which is used for meta-variables in Rust }, "property:haskell": /* getters in data constructors/records */ { foreground: palette.lavender, + fontStyle: context.options.italicKeywords ? "italic" : undefined, }, "macro:haskell": /* pattern synonyms */ { foreground: palette.blue, fontStyle: "", }, + "typeParameter:haskell": { + foreground: palette.maroon, + fontStyle: "", + }, + "variable:haskell": { + fontStyle: "", + }, // TOML syntax tomlArrayKey: { foreground: palette.blue, fontStyle: "" }, diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 1f68d703..7d51efdf 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -27,8 +27,8 @@ const tokens = (context: ThemeContext): TextmateColors => { ], settings: { foreground: palette.blue, + fontStyle: "", }, - // like functions (capitalized -> still visually distinct) }, { name: "types", @@ -43,6 +43,7 @@ const tokens = (context: ThemeContext): TextmateColors => { scope: ["variable.other.generic-type.haskell"], settings: { foreground: palette.maroon, + fontStyle: "", }, }, { @@ -88,6 +89,7 @@ const tokens = (context: ThemeContext): TextmateColors => { ], settings: { foreground: palette.lavender, + fontStyle: "italic", }, }, { From 8c5d5dc08bed34b404886ec461d6b88ff76ef4af Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 20:12:58 +0200 Subject: [PATCH 14/16] chore(haskell): adjust and extend leading comment --- .../src/theme/tokens/haskell.ts | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 7d51efdf..f619a69c 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -5,13 +5,27 @@ import type { TextmateColors, ThemeContext } from "@/types"; STYLING CHOICES --------------- - should preferrably appear visually distinct: - - data constructors -> use blue - - types -> use yellow+italic - - typeclasses [1] -> use yellow + language element ->color ->fontStyle + ----------------- ------- ----------- + functions blue italic + data constructors blue - + types yellow italic + typeclasses [1] yellow - + +It would be preferrable for each listed language element to appear visually distinct from the other. With choices above, that is also achieved, granted setting `italicKeywords` is active. [1]: typeclasses are not distinguishable from types with only textMate scopes; requires semantic tokens + +GRAMMAR REF. +------------ + +https://github.com/JustusAdam/language-haskell + +- is the only Haskell textMate grammar in use +- (is the upstream of the Haskell VS Code extension) +- generated listing of all assigned scopes: https://github.com/JustusAdam/language-haskell/blob/master/scope-lists/haskell.scope-db.yaml + */ const tokens = (context: ThemeContext): TextmateColors => { From bc32838f3626ed5cb1c3bced76bf014a2cb9518c Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 1 Sep 2025 12:52:56 +0200 Subject: [PATCH 15/16] feat(haskell): add general improvements and fixes --- .../src/theme/tokens/haskell.ts | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index f619a69c..7b7b4b54 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -38,6 +38,8 @@ const tokens = (context: ThemeContext): TextmateColors => { "meta.declaration.data constant.other.haskell", "constant.other.haskell", // to hit data constr. if no semantic tokens "meta.declaration.pattern constant.other.haskell", // pattern synonyms + "constant.language.unit.haskell punctuation", + "constant.language.unit.unboxed.haskell punctuation", ], settings: { foreground: palette.blue, @@ -52,6 +54,19 @@ const tokens = (context: ThemeContext): TextmateColors => { fontStyle: "italic", }, }, + { + name: "`()` unit type (not italicized)", + scope: [ + "support.constant.unit.haskell punctuation", + "support.constant.unit.haskell keyword.operator.hash", + "support.constant.unit.unboxed.haskell punctuation", + "support.constant.unit.unboxed.haskell keyword.operator.hash", + ], + settings: { + foreground: palette.yellow, + fontStyle: "", + }, + }, { name: "type parameters", scope: ["variable.other.generic-type.haskell"], @@ -65,6 +80,10 @@ const tokens = (context: ThemeContext): TextmateColors => { scope: [ "keyword.other.preprocessor.haskell", "keyword.other.preprocessor.pragma.haskell", + "keyword.other.default.haskell", + "keyword.other.role.nominal.haskell", + "keyword.other.role.representational.haskell", + "keyword.other.role.phantom.haskell", ], settings: { foreground: palette.red, @@ -114,6 +133,95 @@ const tokens = (context: ThemeContext): TextmateColors => { }, // catppuccin default sets to yellow considering it preprocessor-like, which it is not for Haskell }, + { + name: "char literals (are enum variants)", + scope: [ + "string.quoted.single.haskell", + "string.quoted.single.haskell punctuation.definition.string", + ], + settings: { + foreground: palette.teal, + }, + }, + { + name: "operators", + scope: [ + "storage.type.operator.haskell", + "storage.type.operator.infix.haskell", + "entity.name.function.infix.haskell", // op. in parens, e g: (+) + "punctuation.backtick.haskell", // e g: x `op` y + ], + settings: { + foreground: palette.teal, + fontStyle: "", + }, + }, + { + name: "the , in `(,)`", + scope: [ + "support.constant.tuple.haskell", + "support.constant.tuple.unboxed.haskell", + ], + settings: { + foreground: palette.teal, + fontStyle: "", + }, + // the scoping doesn't allow distinguishing `(,)` in types (= type function) and terms (= data constructor) -> color as an operator since that works OK for both + }, + { + name: "a few special symbols", + scope: [ + "keyword.operator.lambda.haskell", + "keyword.operator.pipe.haskell", + "keyword.operator.double-dot.haskell", + "variable.other.member.wildcard.haskell", + ], + settings: { + foreground: palette.red, + }, + // neither operators nor delimiters, and should preferrably appear distinct from both + }, + { + name: "delimiter-like", + scope: [ + "meta.type-application keyword.operator.prefix.at.haskell", + // symbols in pattern-matching: + "keyword.operator.infix.tight.at.haskell", // @ in pair@(x,y) + "keyword.operator.prefix.tilde.haskell", // ~ in ~(x,y) + "keyword.operator.prefix.bang.haskell", + // delimiters in type signatures: + "keyword.operator.double-colon.haskell", + "keyword.operator.big-arrow.haskell", + // delimiters in type signatures - the . after `forall`: + "meta.function.type-declaration keyword.operator.period.haskell", + "meta.type-declaration keyword.operator.period.haskell", + "meta.declaration.type keyword.operator.period.haskell", + ], + settings: { + foreground: palette.overlay2, + fontStyle: "", + }, + // these are not operators, but are either delimiter-like, or punctuation that benefits from not drawing visual attention + // -> color as delimiters/overlay2 since: closer to style guide + looks better + improves code readability + }, + { + name: "TemplateHaskell and QuasiQuoter (macros)", + scope: [ + "keyword.operator.prefix.dollar.haskell", + "keyword.operator.quasi-quotation.begin.haskell", + "keyword.operator.quasi-quotation.end.haskell", + ], + settings: { + foreground: palette.pink, // like macros in rust + }, + }, + { + name: "minus sign in negative num literals", + scope: ["keyword.operator.prefix.minus.haskell"], + settings: { + foreground: palette.peach, + }, + }, ]; }; From 3af0f46f44fb0293c5ed422dd27ad99fd8d8897f Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 13 Oct 2025 11:00:00 +0200 Subject: [PATCH 16/16] fix(haskell): adjust pragmas, preprocessor styling --- .../catppuccin-vsc/src/theme/tokens/haskell.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts index 7b7b4b54..3a9f6a23 100644 --- a/packages/catppuccin-vsc/src/theme/tokens/haskell.ts +++ b/packages/catppuccin-vsc/src/theme/tokens/haskell.ts @@ -78,8 +78,6 @@ const tokens = (context: ThemeContext): TextmateColors => { { name: "special words (builtin constants-like)", scope: [ - "keyword.other.preprocessor.haskell", - "keyword.other.preprocessor.pragma.haskell", "keyword.other.default.haskell", "keyword.other.role.nominal.haskell", "keyword.other.role.representational.haskell", @@ -89,11 +87,21 @@ const tokens = (context: ThemeContext): TextmateColors => { foreground: palette.red, }, }, + { + name: "pragma specifiers", + scope: [ + "keyword.other.preprocessor.haskell", + "keyword.other.preprocessor.pragma.haskell", + ], + settings: { + foreground: palette.rosewater, + }, + }, { name: "pragma arguments", scope: ["keyword.other.preprocessor.extension.haskell"], settings: { - foreground: palette.peach, + foreground: palette.red, }, }, { @@ -103,7 +111,7 @@ const tokens = (context: ThemeContext): TextmateColors => { "source.haskell meta.preprocessor.c punctuation.definition.preprocessor.c", ], settings: { - foreground: palette.yellow, + foreground: palette.rosewater, }, }, {