Skip to content

Instantly share code, notes, and snippets.

@friedbrice
Created July 28, 2020 16:42
Show Gist options
  • Save friedbrice/090dd32c02c87bdbe1e37d8966e00817 to your computer and use it in GitHub Desktop.
Save friedbrice/090dd32c02c87bdbe1e37d8966e00817 to your computer and use it in GitHub Desktop.
Rudimentary Sublime Text Config for Haskell
%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
name: Haskell (Cabal)
file_extensions:
- cabal
scope: source.cabal
variables:
ident: '[a-zA-Z\_][a-zA-Z\_\-0-9]*'
contexts:
main:
- match: '--'
scope: punctuation.definition.comment.cabal
push: line_comment
- match: '^\s*({{ident}})(:)'
captures:
1: entity.name.function.cabal
2: punctuation.separator.key-value.mapping.cabal
- match: '^({{ident}})\s*(\s{{ident}})?$'
captures:
1: keyword.other.cabal
2: entity.name.function.cabal
- match: ','
scope: punctuation.separator.sequence.cabal
line_comment:
- meta_scope: comment.line.cabal
- match: '$'
pop: true
{
"scope": "meta.preprocessor.haskell",
"completions": [
"LANGUAGE",
"OPTIONS_GHC",
"INCLUDE",
"WARNING",
"DEPRECATED",
"MINIMAL",
"UNPACK",
"NOUNPACK",
"SOURCE",
"OVERLAPPING",
"OVERLAPPABLE",
"OVERLAPS",
"INCOHERENT",
"INLINE",
"NOINLINE",
"INLINABLE",
"CONLIKE",
"LINE",
"RULES",
"SPECIALIZE",
"SPECIALISE",
"AllowAmbiguousTypes",
"ApplicativeDo",
"Arrows",
"BangPatterns",
"BinaryLiterals",
"CApiFFI",
"ConstrainedClassMethods",
"ConstraintKinds",
"CPP",
"DataKinds",
"DatatypeContexts",
"DefaultSignatures",
"DeriveAnyClass",
"DeriveDataTypeable",
"DeriveFoldable",
"DeriveFunctor",
"DeriveGeneric",
"DeriveLift",
"DeriveTraversable",
"DerivingStrategies",
"DerivingVia",
"DisambiguateRecordFields",
"DuplicateRecordFields",
"EmptyCase",
"EmptyDataDecls",
"ExistentialQuantification",
"ExplicitForAll",
"ExplicitNamespaces",
"ExtendedDefaultRules",
"FlexibleContexts",
"FlexibleInstances",
"ForeignFunctionInterface",
"FunctionalDependencies",
"GADTs",
"GADTSyntax",
"GeneralizedNewtypeDeriving",
"ImplicitParams",
"ImplicitPrelude",
"ImpredicativeTypes",
"IncoherentInstances",
"InstanceSigs",
"InterruptibleFFI",
"KindSignatures",
"LambdaCase",
"LiberalTypeSynonyms",
"MagicHash",
"MonadComprehensions",
"MonadFailDesugaring",
"MonoLocalBinds",
"MonomorphismRestriction",
"MultiParamTypeClasses",
"MultiWayIf",
"NamedFieldPuns",
"NamedWildCards",
"NegativeLiterals",
"NPlusKPatterns",
"NullaryTypeClasses",
"NumDecimals",
"NumericUnderscores",
"OverlappingInstances",
"OverloadedLabels",
"OverloadedLists",
"OverloadedStrings",
"PackageImports",
"ParallelListComp",
"PartialTypeSignatures",
"PatternGuards",
"PatternSynonyms",
"PolyKinds",
"PostfixOperators",
"QuantifiedConstraints",
"QuasiQuotes",
"Rank",
"RankNTypes",
"RebindableSyntax",
"RecordWildCards",
"RecursiveDo",
"RoleAnnotations",
"Safe",
"ScopedTypeVariables",
"StandaloneDeriving",
"StaticPointers",
"Strict",
"StrictData",
"TemplateHaskell",
"TemplateHaskellQuotes",
"TraditionalRecordSyntax",
"TransformListComp",
"Trustworthy",
"TupleSections",
"TypeApplications",
"TypeFamilies",
"TypeFamilyDependencies",
"TypeInType",
"TypeOperators",
"TypeSynonymInstances",
"UnboxedSums",
"UnboxedTuples",
"UndecidableInstances",
"UndecidableSuperClasses",
"UnicodeSyntax",
"Unsafe",
"ViewPatterns",
"-Wall",
"-Werror",
"-Weverything",
"-Wincomplete-patterns",
"-Wincomplete-record-updates",
"-Wmissing-fields",
"-Wmissing-methods",
"-Wname-shadowing",
"-Wredundant-constraints",
"-Wtabs",
"-Wunused-imports",
"-Wunused-binds",
"-Wunused-do-bind",
"-Wunused-local-binds",
"-Wunused-matches",
"-Wunused-pattern-binds",
"-fdefer-out-of-scope-variables",
"-fdefer-type-errors",
"-fno-code"
]
}
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Haskell (better)
file_extensions:
- hs
scope: source.haskell
variables:
# Numeric literal patterns taken directly from the "Underscores in Numeric Literals" proposal.
digit: '0-9'
hexit: '{{digit}}A-Fa-f'
octit: '0-7'
decimal: '[{{digit}}][{{digit}}_]*'
hexadecimal: '[{{hexit}}][{{hexit}}_]*'
octal: '[{{octit}}][{{octit}}_]*'
id_tail: '[a-zà-þA-Z0-9_'']*'
type_id: '[A-Z]{{id_tail}}'
val_id: '[a-zà-þ_]{{id_tail}}'
op_id: '[!#$%&*+./<=>?@\\\^|\-~:∷→⇒]+'
contexts:
main:
- match: '^<<<<<<<.*$'
scope: invalid.haskell
- match: '^>>>>>>>.*$'
scope: invalid.haskell
- match: '^=======.*$'
scope: invalid.haskell
- match: '\bundefined\b'
scope: invalid.haskell
- match: '`({{type_id}}\.)*{{val_id}}`'
scope: keyword.operator.haskell
- match: '\b(forall)\b'
captures:
1: keyword.other.haskell
- match: '\b(module)\b'
captures:
1: keyword.other.haskell
push:
- include: comments
- meta_scope: meta.declaration.module.haskell
- match: '(where)'
captures:
1: keyword.other.haskell
pop: true
- include: module_name
- include: module_exports
- match: '[a-z]+'
scope: invalid
- match: '\b(class|instance)\b'
captures:
1: keyword.other.haskell
push:
- include: comments
- meta_scope: meta.declaration.class.haskell
- match: '^(?!\s)'
pop: true
# - match: '($|;)'
# pop: true
- match: '\b(where)\b'
captures:
1: keyword.other.haskell
pop: true
- match: '{{type_id}}'
scope: entity.other.inherited-class.haskell
- match: '\b{{val_id}}\b'
scope: variable.other.generic-type.haskell
- match: '{{op_id}}'
scope: keyword.operator.haskell
- match: '\b(import)\b'
captures:
1: keyword.other.haskell
push:
- meta_scope: meta.import.haskell
- match: '^(?!\s)'
pop: true
# - match: '($|;)'
# pop: true
- match: '(qualified|as|hiding)'
scope: keyword.other.haskell
- include: module_name
- include: module_imports
- include: comments
- match: '(deriving)\s*'
captures:
1: keyword.other.haskell
push:
- include: comments
- include: strings
- include: numbers
- meta_scope: meta.deriving.haskell
- match: '^(?!\s)'
pop: true
- match: '\bderiving\b'
scope: keyword.other.haskell
- match: '\bvia\b'
scope: keyword.other.haskell
- match: '\b{{type_id}}'
scope: entity.other.inherited-class.haskell
- match: '\b(deriving|where|data|type|case|of|let|in|newtype|default)\b'
scope: keyword.other.haskell
- match: '\binfix[lr]?\b'
scope: keyword.operator.haskell
- match: '\b(do|if|then|else)\b'
scope: keyword.control.haskell
- include: numbers
- match: '^(#)\s*\w+'
comment: In addition to Haskell's "native" syntax, GHC permits the C preprocessor to be run on a source file.
scope: meta.preprocessor.c
captures:
1: punctuation.definition.preprocessor.c
- include: pragma
- include: strings
- match: '\[(?:|e|d|t|p)\|'
comment: Points out splices in ast quotes
scope: keyword.other.quasibracket.haskell
push:
- meta_scope: meta.other.quasiquote.haskell
- match: '(.*)(\|\])'
captures:
1: string.quasiquoted.haskell
2: keyword.other.quasibracket.haskell
pop: true
- match: '\$\('
scope: keyword.other.splice.haskell
- match: '\$'
scope: string.quasiquoted.haskell
- match: '[^$]*'
scope: string.quasiquoted.haskell
- match: '\$\('
comment: Highlight the beginning of a splice.
scope: keyword.other.splice.haskell
push:
- include: main
- meta_scope: meta.other.splice.haskell
- match: '\)'
scope: keyword.other.splice.haskell
pop: true
- match: '\[[({{type_id}}\.)*a-zA-Z0-9_'']*\|'
scope: keyword.other.quasibracket.haskell
push:
- meta_scope: meta.other.quasiquote.haskell
- match: '(.*?)(\|\])'
captures:
1: string.quasiquoted.haskell
2: keyword.other.quasibracket.haskell
pop: true
- match: '.*'
scope: string.quasiquoted.haskell
- match: |-
(?x)
(')
(?:
[\ -\[\]-~] # Basic Char
| (\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE
|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS
|US|SP|DEL|[abfnrtv\\\"'\&])) # Escapes
| (\\o[0-7]+) # Octal Escapes
| (\\x[0-9A-Fa-f]+) # Hexadecimal Escapes
| (\^[A-Z@\[\]\\\^_]) # Control Chars
)
(')
scope: string.quoted.single.haskell
captures:
1: punctuation.definition.string.begin.haskell
2: constant.character.escape.haskell
3: constant.character.escape.octal.haskell
4: constant.character.escape.hexadecimal.haskell
5: constant.character.escape.control.haskell
6: punctuation.definition.string.end.haskell
- match: '^({{val_id}})\s*$'
captures:
1: entity.name.function.haskell
comment: Dirty hack to capture function declarations where the type sig starts on the line below, potential for false-positives
- match: '({{val_id}})\s*(::|∷)'
comment: Function declarations with alphanumeric identifier
captures:
1: entity.name.function.haskell
2: keyword.operator.haskell
- match: '^\(({{op_id}})\)\s*$'
captures:
1: entity.name.function.haskell
comment: Dirty hack to capture function declarations where the type sig starts on the line below, potential for false-positives
- match: '\(({{op_id}})\)\s*(::|∷)'
comment: Function declarations with operator identifier
captures:
1: entity.name.function.haskell
2: keyword.operator.haskell
- match: '\b{{type_id}}'
scope: storage.type.haskell
- include: comments
- match: '{{op_id}}'
scope: keyword.operator.haskell
block_comment:
- match: '\{-(?!#)'
scope: punctuation.definition.comment.begin.haskell
push:
- meta_scope: comment.block.haskell
- match: '\{-#'
push:
- match: '-\}'
pop: true
- include: block_comment
- include: block_comment
- match: '-\}'
scope: punctuation.definition.comment.end.haskell
pop: true
comments:
- match: '--(?![!#$%&*+./<=>?@\\\^|~:])'
scope: punctuation.definition.comment.haskell
push:
- meta_scope: comment.line.haskell
- match: '$'
pop: true
- include: block_comment
imports_exports:
- include: comments
- match: '\b({{type_id}})(\(.[^\)]*\)|)'
captures:
1: storage.type.haskell
- match: '\(({{op_id}})\)'
captures:
1: keyword.operator.haskell
- match: '\)'
pop: true
module_exports:
- match: '\('
push:
- meta_scope: meta.declaration.exports.haskell
- include: imports_exports
module_imports:
- match: '\('
push:
- meta_scope: meta.declaration.imports.haskell
- include: imports_exports
module_name:
- match: '{{type_id}}'
scope: support.other.module.haskell
pragma:
- match: '\{-#'
push:
- meta_scope: meta.preprocessor.haskell
- match: '#-\}'
pop: true
- match: '\b(LANGUAGE|OPTIONS_GHC|INCLUDE|WARNING|DEPRECATED|MINIMAL|UNPACK|NOUNPACK|SOURCE|OVERLAPPING|OVERLAPPABLE|OVERLAPS|INCOHERENT|INLINE|NOINLINE|INLINABLE|CONLIKE|LINE|RULES|SPECIALIZE|SPECIALISE)\b'
# https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#pragmas
scope: keyword.other.preprocessor.haskell
strings:
- match: '"'
push:
- meta_include_prototype: false
- meta_scope: string.quoted.double.haskell
- match: '"'
pop: true
- match: '(\\)\s*$'
captures:
1: constant.character.escape.multi-line.haskell
push:
- meta_include_prototype: false
- match: '\s+'
- match: '\\'
scope: constant.character.escape.multi-line.haskell
pop: true
- match: '(?=.)'
pop: true
- match: '\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\"''\&])'
scope: constant.character.escape.haskell
- match: '\\o{{octal}}|\\x{{hexadecimal}}|\\{{decimal}}'
scope: constant.character.escape.octal.haskell
- match: '\^[A-Z@\[\]\\\^_]'
scope: constant.character.escape.control.haskell
numbers:
- match: '\b([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\b'
comment: Floats are always decimal
scope: constant.numeric.haskell
- match: '\b([0-9]+|0([xX][0-9a-fA-F]+|[oO][0-7]+))\b'
scope: constant.numeric.haskell
@friedbrice
Copy link
Author

friedbrice commented Jul 28, 2020

Put these files in your Sublime User Project directory.

  • MacOS: '/Users/{username}/Library/Application Support/Sublime Text 3/Packages/User/'

  • Linux: /home/{username}/.config/sublime-text-3/Packages/User

  • Windows: "C:\Users\{username}\AppData\Roaming\Sublime Text 3\Packages\User"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment