From be54221cd9aa24f84dc517ad80bb3c0af27cb9e4 Mon Sep 17 00:00:00 2001 From: Devin Lake Date: Mon, 16 Dec 2024 15:55:00 -0500 Subject: [PATCH] fix: Updated plugin parsers to parse kdl format --- Cargo.lock | 6 + Exec.kdl | 7 + config/Binary.kdl | 63 + config/Hipcheck.kdl | 8 +- config/Langs.kdl | 1999 +++++++++++++++++ config/Typos.kdl | 11 + config/local.Hipcheck.kdl | 14 +- hipcheck/src/config.rs | 8 +- hipcheck/src/policy/config_to_policy.rs | 6 +- plugins/binary/Cargo.toml | 1 + plugins/binary/src/binary_detector.rs | 82 +- plugins/binary/src/fs.rs | 24 - plugins/binary/src/main.rs | 2 +- plugins/binary/src/util/fs.rs | 25 + plugins/binary/src/util/kdl.rs | 79 + plugins/binary/src/util/mod.rs | 4 + plugins/churn/Cargo.toml | 2 + plugins/churn/src/linguist/fs.rs | 17 +- plugins/churn/src/linguist/kdl_util.rs | 79 + plugins/churn/src/linguist/mod.rs | 82 +- plugins/entropy/Cargo.toml | 1 + .../src/{linguist/mod.rs => linguist.rs} | 80 +- plugins/entropy/src/linguist/fs.rs | 23 - plugins/entropy/src/main.rs | 6 +- plugins/entropy/src/metric.rs | 2 +- plugins/entropy/src/{linguist => util}/db.rs | 0 plugins/entropy/src/util/fs.rs | 25 + plugins/entropy/src/util/kdl.rs | 79 + plugins/entropy/src/util/mod.rs | 5 + plugins/linguist/Cargo.toml | 1 + plugins/linguist/src/fs.rs | 23 - plugins/linguist/src/linguist.rs | 67 +- plugins/linguist/src/main.rs | 2 +- plugins/linguist/src/util/fs.rs | 25 + plugins/linguist/src/util/kdl.rs | 79 + plugins/linguist/src/util/mod.rs | 2 + plugins/typo/Cargo.toml | 1 + plugins/typo/src/languages.rs | 64 +- plugins/typo/src/util/fs.rs | 14 +- plugins/typo/src/util/kdl.rs | 79 + plugins/typo/src/util/mod.rs | 1 + 41 files changed, 2945 insertions(+), 153 deletions(-) create mode 100644 Exec.kdl create mode 100644 config/Binary.kdl create mode 100644 config/Langs.kdl create mode 100644 config/Typos.kdl delete mode 100644 plugins/binary/src/fs.rs create mode 100644 plugins/binary/src/util/fs.rs create mode 100644 plugins/binary/src/util/kdl.rs create mode 100644 plugins/binary/src/util/mod.rs create mode 100644 plugins/churn/src/linguist/kdl_util.rs rename plugins/entropy/src/{linguist/mod.rs => linguist.rs} (69%) delete mode 100644 plugins/entropy/src/linguist/fs.rs rename plugins/entropy/src/{linguist => util}/db.rs (100%) create mode 100644 plugins/entropy/src/util/fs.rs create mode 100644 plugins/entropy/src/util/kdl.rs create mode 100644 plugins/entropy/src/util/mod.rs delete mode 100644 plugins/linguist/src/fs.rs create mode 100644 plugins/linguist/src/util/fs.rs create mode 100644 plugins/linguist/src/util/kdl.rs create mode 100644 plugins/linguist/src/util/mod.rs create mode 100644 plugins/typo/src/util/kdl.rs diff --git a/Cargo.lock b/Cargo.lock index 253a0a12..d68dd490 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,6 +328,7 @@ dependencies = [ "clap", "content_inspector", "hipcheck-sdk", + "kdl 4.7.1", "log", "pathbuf", "schemars", @@ -464,8 +465,10 @@ dependencies = [ name = "churn" version = "0.3.0" dependencies = [ + "anyhow", "clap", "hipcheck-sdk", + "kdl 4.7.1", "log", "pathbuf", "salsa", @@ -941,6 +944,7 @@ dependencies = [ "finl_unicode", "futures", "hipcheck-sdk", + "kdl 4.7.1", "ordered-float", "pathbuf", "rayon", @@ -2813,6 +2817,7 @@ dependencies = [ "anyhow", "clap", "hipcheck-sdk", + "kdl 4.7.1", "log", "pathbuf", "serde", @@ -4794,6 +4799,7 @@ dependencies = [ "anyhow", "clap", "hipcheck-sdk", + "kdl 4.7.1", "log", "maplit", "pathbuf", diff --git a/Exec.kdl b/Exec.kdl new file mode 100644 index 00000000..d03ba0dc --- /dev/null +++ b/Exec.kdl @@ -0,0 +1,7 @@ +plugin { + backoff-interval 1000000 + max-spawn-attempts 3 + max-conn-attempts 5 + jitter-percent 10 + grpc-msg-buffer-size 10 +} diff --git a/config/Binary.kdl b/config/Binary.kdl new file mode 100644 index 00000000..a040ddf7 --- /dev/null +++ b/config/Binary.kdl @@ -0,0 +1,63 @@ +//############################################################################### +// Binary.kdl +// +// This configuration file defines known binary file formats (executables and +// precompiled objects) and their file extensions in order to identify non- +// source files included in repositories. +// +// ----------------------------------------------------------------------------- +// References: +// +// https://en.wikipedia.org/wiki/List_of_file_formats#Object_code,_executable_files,_shared_and_dynamically_linked_libraries +// +// ----------------------------------------------------------------------------- +// +// name - Name of the format in question. +// type - executable, object, combination, or nil +// extensions - An Array of associated extensions (the first is considered the +// primary extension; the others should be listed alphanumerically) +// notes - Optional, short text description of format. Useful if uncommon. +// +//############################################################################### + +format { + format name="8BF" notes="Image editor plugins" type="executable" { + extensions "8bf" "8ba" "8bc" "8be" "8bi" "8bp" "8bs" "8by" "8li" "8ly" + } + format name="Objective C static library" type="object" { + extensions "a" + } + format name="Android Application Package" type="executable" { + extensions "apk" "apkm" "apks" "xapk" + } + format name="macOS Appplication Bundle" type="executable" { + extensions "app" + } + format name="Java class file" type="object" { + extensions "class" + } + format name="COM file" notes="DOS command file" type="executable" { + extensions "com" + } + format name="Dynamic-link library" notes="Microsoft shared library" type="object" { + extension "dll" + } + format name="Executable and Linkable Format" notes="Unix ELF" type="combination" { + extensions "elf" "axf" "bin" "o" "prx" "puff" "ko" "mod" "so" + } + format name="Microsoft Executable" type="executable" { + extensions "exe" "acm" "ax" "cpl" "drv" "efi" "mui" "ocx" "scr" "sys" "tsp" + } + format name="iOS App Store Package" type="executable" { + extensions "ipa" + } + format name="Java Archive" type="combination" { + extensions "jar" "ear" "war" + } + format name="XPInstall" notes="Mozilla Cross-Platform Install" type="executable" { + extensions "xpi" + } + format name="Mach-O" notes="Mach object file format, macOS/iOS" type="object" { + extensions "dylib" "bundle" + } +} diff --git a/config/Hipcheck.kdl b/config/Hipcheck.kdl index 299aa49c..28c1a08c 100644 --- a/config/Hipcheck.kdl +++ b/config/Hipcheck.kdl @@ -22,7 +22,7 @@ analyze { category "practices" { analysis "mitre/activity" policy="(lte $ P52w)" weight=3 analysis "mitre/binary" { - binary-file #rel("Binary.toml") + binary-file #rel("Binary.kdl") binary-file-threshold 0 } analysis "mitre/fuzz" policy="(eq #t $)" @@ -31,7 +31,7 @@ analyze { category "attacks" { analysis "mitre/typo" { - typo-file #rel("Typos.toml") + typo-file #rel("Typos.kdl") count-threshold 0 } @@ -42,12 +42,12 @@ analyze { } analysis "mitre/entropy" policy="(eq 0 (count (filter (gt 8.0) $)))" { - langs-file #rel("Langs.toml") + langs-file #rel("Langs.kdl") entropy-threshold 10.0 commit-percentage 0.0 } analysis "mitre/churn" policy="(lte (divz (count (filter (gt 3) $)) (count $)) 0.02)" { - langs-file #rel("Langs.toml") + langs-file #rel("Langs.kdl") } } } diff --git a/config/Langs.kdl b/config/Langs.kdl new file mode 100644 index 00000000..e32054a1 --- /dev/null +++ b/config/Langs.kdl @@ -0,0 +1,1999 @@ +languages { + language name="1C Enterprise" type="programming" color="#814CCC" tm_scope="source.bsl" ace_mode="text" language_id=0 { + extensions ".bsl" ".os" + } + language name="4D" type="programming" tm_scope="source.4dm" ace_mode="text" language_id=577529595 { + extensions ".4dm" + } + language name="ABAP" type="programming" color="#E8274B" tm_scope="source.abap" ace_mode="abap" language_id=1 { + extensions ".abap" + } + language name="ABNF" type="data" tm_scope="source.abnf" ace_mode="text" language_id=429 { + extensions ".abnf" + } + language name="AGS Script" type="programming" color="#B9D9FF" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=2 { + aliases "ags" + extensions ".asc" ".ash" + } + language name="AL" type="programming" color="#3AA2B5" tm_scope="source.al" ace_mode="text" language_id=658971832 { + extensions ".al" + } + language name="AMPL" type="programming" color="#E6EFBB" tm_scope="source.ampl" ace_mode="text" language_id=3 { + extensions ".ampl" ".mod" + } + language name="ANTLR" type="programming" color="#9DC3FF" tm_scope="source.antlr" ace_mode="text" language_id=4 { + extensions ".g4" + } + language name="API Blueprint" type="markup" color="#2ACCA8" tm_scope="text.html.markdown.source.gfm.apib" ace_mode="markdown" language_id=5 { + extensions ".apib" + } + language name="APL" type="programming" color="#5A8164" tm_scope="source.apl" ace_mode="text" codemirror_mime_type="text/apl" language_id=6 { + extensions ".apl" ".dyalog" + interpreters "apl" "aplx" "dyalog" + } + language name="ASL" type="programming" tm_scope="source.asl" ace_mode="text" language_id=124996147 { + extensions ".asl" ".dsl" + } + language name="ASN.1" type="data" tm_scope="source.asn" ace_mode="text" codemirror_mime_type="text/x-ttcn-asn" language_id=7 { + extensions ".asn" ".asn1" + } + language name="ASP.NET" type="programming" color="#9400ff" tm_scope="text.html.asp" ace_mode="text" codemirror_mime_type="application/x-aspx" language_id=564186416 { + aliases "aspx" "aspx-vb" + extensions ".asax" ".ascx" ".ashx" ".asmx" ".aspx" ".axd" + } + language name="ATS" type="programming" color="#1ac620" tm_scope="source.ats" ace_mode="ocaml" language_id=9 { + aliases "ats2" + extensions ".dats" ".hats" ".sats" + } + language name="ActionScript" type="programming" color="#882B0F" tm_scope="source.actionscript.3" ace_mode="actionscript" language_id=10 { + aliases "actionscript 3" "actionscript3" "as3" + extensions ".as" + } + language name="Ada" type="programming" color="#02f88c" tm_scope="source.ada" ace_mode="ada" language_id=11 { + aliases "ada95" "ada2005" + extensions ".adb" ".ada" ".ads" + } + language name="Adobe Font Metrics" type="data" tm_scope="source.afm" ace_mode="text" language_id=147198098 { + aliases "acfm" "adobe composite font metrics" "adobe multiple font metrics" "amfm" + extensions ".afm" + } + language name="Agda" type="programming" color="#315665" tm_scope="source.agda" ace_mode="text" language_id=12 { + extensions ".agda" + } + language name="Alloy" type="programming" color="#64C800" tm_scope="source.alloy" ace_mode="text" language_id=13 { + extensions ".als" + } + language name="Alpine Abuild" type="programming" group="Shell" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=14 { + aliases "abuild" "apkbuild" + filenames "APKBUILD" + } + language name="Altium Designer" type="data" tm_scope="source.ini" ace_mode="ini" language_id=187772328 { + aliases "altium" + extensions ".OutJob" ".PcbDoc" ".PrjPCB" ".SchDoc" + } + language name="AngelScript" type="programming" color="#C7D7DC" tm_scope="source.angelscript" ace_mode="text" codemirror_mime_type="text/x-c++src" language_id=389477596 { + extensions ".as" ".angelscript" + } + language name="Ant Build System" type="data" tm_scope="text.xml.ant" ace_mode="xml" codemirror_mime_type="application/xml" language_id=15 { + filenames "ant.xml" "build.xml" + } + language name="ApacheConf" type="data" tm_scope="source.apache-config" ace_mode="apache_conf" language_id=16 { + aliases "aconf" "apache" + filenames ".htaccess" "apache2.conf" "httpd.conf" + extensions ".apacheconf" ".vhost" + } + language name="Apex" type="programming" color="#1797c0" tm_scope="source.java" ace_mode="java" codemirror_mime_type="text/x-java" language_id=17 { + extensions ".cls" + } + language name="Apollo Guidance Computer" type="programming" group="Assembly" color="#0B3D91" tm_scope="source.agc" ace_mode="assembly_x86" language_id=18 { + extensions ".agc" + } + language name="AppleScript" type="programming" color="#101F1F" tm_scope="source.applescript" ace_mode="applescript" language_id=19 { + aliases "osascript" + extensions ".applescript" ".scpt" + interpreters "osascript" + } + language name="Arc" type="programming" color="#aa2afe" tm_scope="none" ace_mode="text" language_id=20 { + extensions ".arc" + } + language name="AsciiDoc" type="prose" wrap="true" tm_scope="text.html.asciidoc" ace_mode="asciidoc" language_id=22 { + extensions ".asciidoc" ".adoc" ".asc" + } + language name="AspectJ" type="programming" color="#a957b0" tm_scope="source.aspectj" ace_mode="text" language_id=23 { + extensions ".aj" + } + language name="Assembly" type="programming" color="#6E4C13" tm_scope="source.assembly" ace_mode="assembly_x86" language_id=24 { + aliases "asm" "nasm" + extensions ".asm" ".a51" ".i" ".inc" ".nasm" + } + language name="Asymptote" type="programming" color="#ff0000" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-kotlin" language_id=591605007 { + extensions ".asy" + interpreters "asy" + } + language name="Augeas" type="programming" tm_scope="none" ace_mode="text" language_id=25 { + extensions ".aug" + } + language name="AutoHotkey" type="programming" color="#6594b9" tm_scope="source.ahk" ace_mode="autohotkey" language_id=26 { + aliases "ahk" + extensions ".ahk" ".ahkl" + } + language name="AutoIt" type="programming" color="#1C3552" tm_scope="source.autoit" ace_mode="autohotkey" language_id=27 { + aliases "au3" "AutoIt3" "AutoItScript" + extensions ".au3" + } + language name="Avro IDL" type="data" tm_scope="source.avro" ace_mode="text" language_id=785497837 { + extensions ".avdl" + } + language name="Awk" type="programming" tm_scope="source.awk" ace_mode="text" language_id=28 { + extensions ".awk" ".auk" ".gawk" ".mawk" ".nawk" + interpreters "awk" "gawk" "mawk" "nawk" + } + language name="Ballerina" type="programming" color="#FF5000" tm_scope="source.ballerina" ace_mode="text" language_id=720859680 { + extensions ".bal" + } + language name="Batchfile" type="programming" color="#C1F12E" tm_scope="source.batchfile" ace_mode="batchfile" language_id=29 { + aliases "bat" "batch" "dosbatch" "winbatch" + extensions ".bat" ".cmd" + } + language name="Befunge" type="programming" tm_scope="source.befunge" ace_mode="text" language_id=30 { + extensions ".befunge" + } + language name="BibTeX" type="markup" group="TeX" tm_scope="text.bibtex" ace_mode="tex" codemirror_mime_type="text/x-stex" language_id=982188347 { + extensions ".bib" ".bibtex" + } + language name="Bison" type="programming" group="Yacc" color="#6A463F" tm_scope="source.yacc" ace_mode="text" language_id=31 { + extensions ".bison" + } + language name="BitBake" type="programming" tm_scope="none" ace_mode="text" language_id=32 { + extensions ".bb" + } + language name="Blade" type="markup" color="#f7523f" tm_scope="text.html.php.blade" ace_mode="text" language_id=33 { + extensions ".blade" ".blade.php" + } + language name="BlitzBasic" type="programming" tm_scope="source.blitzmax" ace_mode="text" language_id=34 { + aliases "b3d" "blitz3d" "blitzplus" "bplus" + extensions ".bb" ".decls" + } + language name="BlitzMax" type="programming" color="#cd6400" tm_scope="source.blitzmax" ace_mode="text" language_id=35 { + aliases "bmax" + extensions ".bmx" + } + language name="Bluespec" type="programming" tm_scope="source.bsv" ace_mode="verilog" language_id=36 { + extensions ".bsv" + } + language name="Boo" type="programming" color="#d4bec1" tm_scope="source.boo" ace_mode="text" language_id=37 { + extensions ".boo" + } + language name="Brainfuck" type="programming" color="#2F2530" tm_scope="source.bf" ace_mode="text" codemirror_mime_type="text/x-brainfuck" language_id=38 { + extensions ".b" ".bf" + } + language name="Brightscript" type="programming" tm_scope="source.brightscript" ace_mode="text" language_id=39 { + extensions ".brs" + } + language name="C" type="programming" color="#555555" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=41 { + extensions ".c" ".cats" ".h" ".idc" + interpreters "tcc" + } + language name="C#" type="programming" color="#178600" tm_scope="source.cs" ace_mode="csharp" codemirror_mime_type="text/x-csharp" language_id=42 { + aliases "csharp" + extensions ".cs" ".cake" ".csx" ".linq" + } + language name="C++" type="programming" color="#f34b7d" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=43 { + aliases "cpp" + extensions ".cpp" ".c++" ".cc" ".cp" ".cxx" ".h" ".h++" ".hh" ".hpp" ".hxx" ".inc" ".inl" ".ino" ".ipp" ".re" ".tcc" ".tpp" + } + language name="C-ObjDump" type="data" tm_scope="objdump.x86asm" ace_mode="assembly_x86" language_id=44 { + extensions ".c-objdump" + } + language name="C2hs Haskell" type="programming" group="Haskell" tm_scope="source.haskell" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=45 { + aliases "c2hs" + extensions ".chs" + } + language name="CLIPS" type="programming" tm_scope="source.clips" ace_mode="text" language_id=46 { + extensions ".clp" + } + language name="CMake" type="programming" tm_scope="source.cmake" ace_mode="text" codemirror_mime_type="text/x-cmake" language_id=47 { + filenames "CMakeLists.txt" + extensions ".cmake" ".cmake.in" + } + language name="COBOL" type="programming" tm_scope="source.cobol" ace_mode="cobol" codemirror_mime_type="text/x-cobol" language_id=48 { + extensions ".cob" ".cbl" ".ccp" ".cobol" ".cpy" + } + language name="COLLADA" type="data" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=49 { + extensions ".dae" + } + language name="CSON" type="data" color="#244776" tm_scope="source.coffee" ace_mode="coffee" codemirror_mime_type="text/x-coffeescript" language_id=424 { + extensions ".cson" + } + language name="CSS" type="markup" color="#563d7c" tm_scope="source.css" ace_mode="css" codemirror_mime_type="text/css" language_id=50 { + extensions ".css" + } + language name="CSV" type="data" tm_scope="none" ace_mode="text" language_id=51 { + extensions ".csv" + } + language name="CWeb" type="programming" tm_scope="none" ace_mode="text" language_id=657332628 { + extensions ".w" + } + language name="Cabal Config" type="data" tm_scope="source.cabal" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=677095381 { + aliases "Cabal" + filenames "cabal.config" "cabal.project" + extensions ".cabal" + } + language name="Cap'n Proto" type="programming" tm_scope="source.capnp" ace_mode="text" language_id=52 { + extensions ".capnp" + } + language name="CartoCSS" type="programming" tm_scope="source.css.mss" ace_mode="text" language_id=53 { + aliases "Carto" + extensions ".mss" + } + language name="Ceylon" type="programming" color="#dfa535" tm_scope="source.ceylon" ace_mode="text" language_id=54 { + extensions ".ceylon" + } + language name="Chapel" type="programming" color="#8dc63f" tm_scope="source.chapel" ace_mode="text" language_id=55 { + aliases "chpl" + extensions ".chpl" + } + language name="Charity" type="programming" tm_scope="none" ace_mode="text" language_id=56 { + extensions ".ch" + } + language name="ChucK" type="programming" tm_scope="source.java" ace_mode="java" codemirror_mime_type="text/x-java" language_id=57 { + extensions ".ck" + } + language name="Cirru" type="programming" color="#ccccff" tm_scope="source.cirru" ace_mode="cirru" language_id=58 { + extensions ".cirru" + } + language name="Clarion" type="programming" color="#db901e" tm_scope="source.clarion" ace_mode="text" language_id=59 { + extensions ".clw" + } + language name="Classic ASP" type="programming" color="#6a40fd" tm_scope="text.html.asp" ace_mode="text" language_id=8 { + aliases "asp" + extensions ".asp" + } + language name="Clean" type="programming" color="#3F85AF" tm_scope="source.clean" ace_mode="text" language_id=60 { + extensions ".icl" ".dcl" + } + language name="Click" type="programming" color="#E4E6F3" tm_scope="source.click" ace_mode="text" language_id=61 { + extensions ".click" + } + language name="Clojure" type="programming" color="#db5855" tm_scope="source.clojure" ace_mode="clojure" codemirror_mime_type="text/x-clojure" language_id=62 { + filenames "riemann.config" + extensions ".clj" ".boot" ".cl2" ".cljc" ".cljs" ".cljs.hl" ".cljscm" ".cljx" ".hic" + } + language name="Closure Templates" type="markup" group="HTML" tm_scope="text.html.soy" ace_mode="soy_template" codemirror_mime_type="text/x-soy" language_id=357046146 { + aliases "soy" + extensions ".soy" + } + language name="Cloud Firestore Security Rules" type="data" tm_scope="source.firestore" ace_mode="less" codemirror_mime_type="text/css" language_id=407996372 { + filenames "firestore.rules" + } + language name="CoNLL-U" type="data" tm_scope="text.conllu" ace_mode="text" language_id=421026389 { + aliases "CoNLL" "CoNLL-X" + extensions ".conllu" ".conll" + } + language name="CodeQL" type="programming" tm_scope="source.ql" ace_mode="text" language_id=424259634 { + aliases "ql" + extensions ".ql" ".qll" + } + language name="CoffeeScript" type="programming" color="#244776" tm_scope="source.coffee" ace_mode="coffee" codemirror_mime_type="text/x-coffeescript" language_id=63 { + aliases "coffee" "coffee-script" + filenames "Cakefile" + extensions ".coffee" "._coffee" ".cake" ".cjsx" ".iced" + interpreters "coffee" + } + language name="ColdFusion" type="programming" color="#ed2cd6" tm_scope="text.html.cfm" ace_mode="coldfusion" language_id=64 { + aliases "cfm" "cfml" "coldfusion html" + extensions ".cfm" ".cfml" + } + language name="ColdFusion CFC" type="programming" group="ColdFusion" color="#ed2cd6" tm_scope="source.cfscript" ace_mode="coldfusion" language_id=65 { + aliases "cfc" + extensions ".cfc" + } + language name="Common Lisp" type="programming" color="#3fb68b" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=66 { + aliases "lisp" + extensions ".lisp" ".asd" ".cl" ".l" ".lsp" ".ny" ".podsl" ".sexp" + interpreters "lisp" "sbcl" "ccl" "clisp" "ecl" + } + language name="Common Workflow Language" type="programming" color="#B5314C" tm_scope="source.cwl" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=988547172 { + aliases "cwl" + extensions ".cwl" + interpreters "cwl-runner" + } + language name="Component Pascal" type="programming" color="#B0CE4E" tm_scope="source.pascal" ace_mode="pascal" codemirror_mime_type="text/x-pascal" language_id=67 { + aliases "delphi" "objectpascal" + extensions ".cp" ".cps" + } + language name="Cool" type="programming" tm_scope="source.cool" ace_mode="text" language_id=68 { + extensions ".cl" + } + language name="Coq" type="programming" tm_scope="source.coq" ace_mode="text" language_id=69 { + extensions ".coq" ".v" + } + language name="Cpp-ObjDump" type="data" tm_scope="objdump.x86asm" ace_mode="assembly_x86" language_id=70 { + aliases "c++-objdump" + extensions ".cppobjdump" ".c++-objdump" ".c++objdump" ".cpp-objdump" ".cxx-objdump" + } + language name="Creole" type="prose" wrap="true" tm_scope="text.html.creole" ace_mode="text" language_id=71 { + extensions ".creole" + } + language name="Crystal" type="programming" color="#000100" tm_scope="source.crystal" ace_mode="ruby" codemirror_mime_type="text/x-crystal" language_id=72 { + extensions ".cr" + interpreters "crystal" + } + language name="Csound" type="programming" tm_scope="source.csound" ace_mode="csound_orchestra" language_id=73 { + aliases "csound-orc" + extensions ".orc" ".udo" + } + language name="Csound Document" type="programming" tm_scope="source.csound-document" ace_mode="csound_document" language_id=74 { + aliases "csound-csd" + extensions ".csd" + } + language name="Csound Score" type="programming" tm_scope="source.csound-score" ace_mode="csound_score" language_id=75 { + aliases "csound-sco" + extensions ".sco" + } + language name="Cuda" type="programming" color="#3A4E3A" tm_scope="source.cuda-c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=77 { + extensions ".cu" ".cuh" + } + language name="Cycript" type="programming" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="text/javascript" language_id=78 { + extensions ".cy" + } + language name="Cython" type="programming" group="Python" tm_scope="source.cython" ace_mode="text" codemirror_mime_type="text/x-cython" language_id=79 { + aliases "pyrex" + extensions ".pyx" ".pxd" ".pxi" + } + language name="D" type="programming" color="#ba595e" tm_scope="source.d" ace_mode="d" codemirror_mime_type="text/x-d" language_id=80 { + extensions ".d" ".di" + } + language name="D-ObjDump" type="data" tm_scope="objdump.x86asm" ace_mode="assembly_x86" language_id=81 { + extensions ".d-objdump" + } + language name="DIGITAL Command Language" type="programming" tm_scope="none" ace_mode="text" language_id=82 { + aliases "dcl" + extensions ".com" + } + language name="DM" type="programming" color="#447265" tm_scope="source.dm" ace_mode="c_cpp" language_id=83 { + aliases "byond" + extensions ".dm" + } + language name="DNS Zone" type="data" tm_scope="text.zone_file" ace_mode="text" language_id=84 { + extensions ".zone" ".arpa" + } + language name="DTrace" type="programming" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=85 { + aliases "dtrace-script" + extensions ".d" + interpreters "dtrace" + } + language name="Dafny" type="programming" color="#FFEC25" tm_scope="text.dfy.dafny" ace_mode="text" language_id=969323346 { + extensions ".dfy" + interpreters "dafny" + } + language name="Darcs Patch" type="data" tm_scope="none" ace_mode="text" language_id=86 { + aliases "dpatch" + extensions ".darcspatch" ".dpatch" + } + language name="Dart" type="programming" color="#00B4AB" tm_scope="source.dart" ace_mode="dart" codemirror_mime_type="application/dart" language_id=87 { + extensions ".dart" + interpreters "dart" + } + language name="DataWeave" type="programming" color="#003a52" tm_scope="source.data-weave" ace_mode="text" language_id=974514097 { + extensions ".dwl" + } + language name="Dhall" type="programming" color="#dfafff" tm_scope="source.haskell" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=793969321 { + extensions ".dhall" + } + language name="Diff" type="data" tm_scope="source.diff" ace_mode="diff" codemirror_mime_type="text/x-diff" language_id=88 { + aliases "udiff" + extensions ".diff" ".patch" + } + language name="DirectX 3D File" type="data" tm_scope="none" ace_mode="text" language_id=201049282 { + extensions ".x" + } + language name="Dockerfile" type="programming" color="#384d54" tm_scope="source.dockerfile" ace_mode="dockerfile" codemirror_mime_type="text/x-dockerfile" language_id=89 { + filenames "Dockerfile" + extensions ".dockerfile" + } + language name="Dogescript" type="programming" color="#cca760" tm_scope="none" ace_mode="text" language_id=90 { + extensions ".djs" + } + language name="Dylan" type="programming" color="#6c616e" tm_scope="source.dylan" ace_mode="text" codemirror_mime_type="text/x-dylan" language_id=91 { + extensions ".dylan" ".dyl" ".intr" ".lid" + } + language name="E" type="programming" color="#ccce35" tm_scope="none" ace_mode="text" language_id=92 { + extensions ".E" + interpreters "rune" + } + language name="EBNF" type="data" tm_scope="source.ebnf" ace_mode="text" codemirror_mime_type="text/x-ebnf" language_id=430 { + extensions ".ebnf" + } + language name="ECL" type="programming" color="#8a1267" tm_scope="none" ace_mode="text" codemirror_mime_type="text/x-ecl" language_id=93 { + extensions ".ecl" ".eclxml" + } + language name="ECLiPSe" type="programming" group="prolog" tm_scope="source.prolog.eclipse" ace_mode="prolog" language_id=94 { + extensions ".ecl" + } + language name="EJS" type="markup" group="HTML" color="#a91e50" tm_scope="text.html.js" ace_mode="ejs" language_id=95 { + extensions ".ejs" ".ect" ".jst" + } + language name="EML" type="data" tm_scope="text.eml.basic" ace_mode="text" language_id=529653389 { + extensions ".eml" ".mbox" + } + language name="EQ" type="programming" color="#a78649" tm_scope="source.cs" ace_mode="csharp" codemirror_mime_type="text/x-csharp" language_id=96 { + extensions ".eq" + } + language name="Eagle" type="data" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=97 { + extensions ".sch" ".brd" + } + language name="Easybuild" type="data" group="Python" tm_scope="source.python" ace_mode="python" codemirror_mime_type="text/x-python" language_id=342840477 { + extensions ".eb" + } + language name="Ecere Projects" type="data" group="JavaScript" tm_scope="source.json" ace_mode="json" codemirror_mime_type="application/json" language_id=98 { + extensions ".epj" + } + language name="EditorConfig" type="data" group="INI" tm_scope="source.editorconfig" ace_mode="ini" codemirror_mime_type="text/x-properties" language_id=96139566 { + aliases "editor-config" + filenames ".editorconfig" + } + language name="Edje Data Collection" type="data" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=342840478 { + extensions ".edc" + } + language name="Eiffel" type="programming" color="#4d6977" tm_scope="source.eiffel" ace_mode="eiffel" codemirror_mime_type="text/x-eiffel" language_id=99 { + extensions ".e" + } + language name="Elixir" type="programming" color="#6e4a7e" tm_scope="source.elixir" ace_mode="elixir" language_id=100 { + filenames "mix.lock" + extensions ".ex" ".exs" + interpreters "elixir" + } + language name="Elm" type="programming" color="#60B5CC" tm_scope="source.elm" ace_mode="elm" codemirror_mime_type="text/x-elm" language_id=101 { + extensions ".elm" + } + language name="Emacs Lisp" type="programming" color="#c065db" tm_scope="source.emacs.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=102 { + aliases "elisp" "emacs" + filenames ".abbrev_defs" ".emacs" ".emacs.desktop" ".gnus" ".spacemacs" ".viper" "Cask" "Project.ede" "_emacs" "abbrev_defs" + extensions ".el" ".emacs" ".emacs.desktop" + } + language name="EmberScript" type="programming" color="#FFF4F3" tm_scope="source.coffee" ace_mode="coffee" codemirror_mime_type="text/x-coffeescript" language_id=103 { + extensions ".em" ".emberscript" + } + language name="Erlang" type="programming" color="#B83998" tm_scope="source.erlang" ace_mode="erlang" codemirror_mime_type="text/x-erlang" language_id=104 { + filenames "Emakefile" "rebar.config" "rebar.config.lock" "rebar.lock" + extensions ".erl" ".app.src" ".es" ".escript" ".hrl" ".xrl" ".yrl" + interpreters "escript" + } + language name="F#" type="programming" color="#b845fc" tm_scope="source.fsharp" ace_mode="text" codemirror_mime_type="text/x-fsharp" language_id=105 { + aliases "fsharp" + extensions ".fs" ".fsi" ".fsx" + } + language name="F*" fs_name="Fstar" type="programming" color="#572e30" tm_scope="source.fstar" ace_mode="text" language_id=336943375 { + aliases "fstar" + extensions ".fst" + } + language name="FIGlet Font" type="data" tm_scope="source.figfont" ace_mode="text" language_id=686129783 { + aliases "FIGfont" + extensions ".flf" + } + language name="FLUX" type="programming" color="#88ccff" tm_scope="none" ace_mode="text" language_id=106 { + extensions ".fx" ".flux" + } + language name="Factor" type="programming" color="#636746" tm_scope="source.factor" ace_mode="text" codemirror_mime_type="text/x-factor" language_id=108 { + filenames ".factor-boot-rc" ".factor-rc" + extensions ".factor" + } + language name="Fancy" type="programming" color="#7b9db4" tm_scope="source.fancy" ace_mode="text" language_id=109 { + filenames "Fakefile" + extensions ".fy" ".fancypack" + } + language name="Fantom" type="programming" color="#14253c" tm_scope="source.fan" ace_mode="text" language_id=110 { + extensions ".fan" + } + language name="Faust" type="programming" color="#c37240" tm_scope="source.faust" ace_mode="text" language_id=622529198 { + extensions ".dsp" + } + language name="Filebench WML" type="programming" tm_scope="none" ace_mode="text" language_id=111 { + extensions ".f" + } + language name="Filterscript" type="programming" group="RenderScript" tm_scope="none" ace_mode="text" language_id=112 { + extensions ".fs" + } + language name="Formatted" type="data" tm_scope="none" ace_mode="text" language_id=113 { + extensions ".for" ".eam.fs" + } + language name="Forth" type="programming" color="#341708" tm_scope="source.forth" ace_mode="forth" codemirror_mime_type="text/x-forth" language_id=114 { + extensions ".fth" ".4th" ".f" ".for" ".forth" ".fr" ".frt" ".fs" + } + language name="Fortran" type="programming" group="Fortran" color="#4d41b1" tm_scope="source.fortran" ace_mode="text" codemirror_mime_type="text/x-fortran" language_id=107 { + extensions ".f" ".f77" ".for" ".fpp" + } + language name="Fortran Free Form" type="programming" group="Fortran" tm_scope="source.fortran.modern" ace_mode="text" codemirror_mime_type="text/x-fortran" language_id=761352333 { + extensions ".f90" ".f03" ".f08" ".f95" + } + language name="FreeMarker" type="programming" color="#0050b2" tm_scope="text.html.ftl" ace_mode="ftl" language_id=115 { + aliases "ftl" + extensions ".ftl" + } + language name="Frege" type="programming" color="#00cafe" tm_scope="source.haskell" ace_mode="haskell" language_id=116 { + extensions ".fr" + } + language name="Futhark" type="programming" color="#5f021f" tm_scope="source.futhark" ace_mode="text" language_id=97358117 { + extensions ".fut" + } + language name="G-code" type="programming" color="#D08CF2" tm_scope="source.gcode" ace_mode="gcode" language_id=117 { + extensions ".g" ".cnc" ".gco" ".gcode" + } + language name="GAML" type="programming" color="#FFC766" tm_scope="none" ace_mode="text" language_id=290345951 { + extensions ".gaml" + } + language name="GAMS" type="programming" tm_scope="none" ace_mode="text" language_id=118 { + extensions ".gms" + } + language name="GAP" type="programming" tm_scope="source.gap" ace_mode="text" language_id=119 { + extensions ".g" ".gap" ".gd" ".gi" ".tst" + } + language name="GCC Machine Description" type="programming" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=121 { + extensions ".md" + } + language name="GDB" type="programming" tm_scope="source.gdb" ace_mode="text" language_id=122 { + extensions ".gdb" ".gdbinit" + } + language name="GDScript" type="programming" color="#355570" tm_scope="source.gdscript" ace_mode="text" language_id=123 { + extensions ".gd" + } + language name="GEDCOM" type="data" tm_scope="source.gedcom" ace_mode="text" language_id=459577965 { + extensions ".ged" + } + language name="GLSL" type="programming" tm_scope="source.glsl" ace_mode="glsl" language_id=124 { + extensions ".glsl" ".fp" ".frag" ".frg" ".fs" ".fsh" ".fshader" ".geo" ".geom" ".glslf" ".glslv" ".gs" ".gshader" ".shader" ".tesc" ".tese" ".vert" ".vrx" ".vsh" ".vshader" + } + language name="GN" type="data" tm_scope="source.gn" ace_mode="python" codemirror_mime_type="text/x-python" language_id=302957008 { + filenames ".gn" + extensions ".gn" ".gni" + interpreters "gn" + } + language name="Game Maker Language" type="programming" color="#71b417" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=125 { + extensions ".gml" + } + language name="Genie" type="programming" color="#fb855d" tm_scope="none" ace_mode="text" language_id=792408528 { + extensions ".gs" + } + language name="Genshi" type="programming" tm_scope="text.xml.genshi" ace_mode="xml" codemirror_mime_type="text/xml" language_id=126 { + aliases "xml+genshi" "xml+kid" + extensions ".kid" + } + language name="Gentoo Ebuild" type="programming" group="Shell" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=127 { + extensions ".ebuild" + } + language name="Gentoo Eclass" type="programming" group="Shell" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=128 { + extensions ".eclass" + } + language name="Gerber Image" type="data" tm_scope="source.gerber" ace_mode="text" language_id=404627610 { + aliases "rs-274x" + extensions ".gbr" ".gbl" ".gbo" ".gbp" ".gbs" ".gko" ".gml" ".gpb" ".gpt" ".gtl" ".gto" ".gtp" ".gts" ".sol" + interpreters "gerbv" "gerbview" + } + language name="Gettext Catalog" type="prose" searchable="false" tm_scope="source.po" ace_mode="text" language_id=129 { + aliases "pot" + extensions ".po" ".pot" + } + language name="Gherkin" type="programming" color="#5B2063" tm_scope="text.gherkin.feature" ace_mode="text" language_id=76 { + aliases "cucumber" + extensions ".feature" ".story" + } + language name="Git Attributes" type="data" group="INI" tm_scope="source.gitattributes" ace_mode="gitignore" codemirror_mime_type="text/x-sh" language_id=956324166 { + aliases "gitattributes" + filenames ".gitattributes" + } + language name="Git Config" type="data" group="INI" tm_scope="source.gitconfig" ace_mode="ini" codemirror_mime_type="text/x-properties" language_id=807968997 { + aliases "gitconfig" "gitmodules" + filenames ".gitconfig" ".gitmodules" + extensions ".gitconfig" + } + language name="Glyph" type="programming" color="#c1ac7f" tm_scope="source.tcl" ace_mode="tcl" codemirror_mime_type="text/x-tcl" language_id=130 { + extensions ".glf" + } + language name="Glyph Bitmap Distribution Format" type="data" tm_scope="source.bdf" ace_mode="text" language_id=997665271 { + extensions ".bdf" + } + language name="Gnuplot" type="programming" color="#f0a9f0" tm_scope="source.gnuplot" ace_mode="text" language_id=131 { + extensions ".gp" ".gnu" ".gnuplot" ".p" ".plot" ".plt" + interpreters "gnuplot" + } + language name="Go" type="programming" color="#00ADD8" tm_scope="source.go" ace_mode="golang" codemirror_mime_type="text/x-go" language_id=132 { + aliases "golang" + extensions ".go" + } + language name="Golo" type="programming" color="#88562A" tm_scope="source.golo" ace_mode="text" language_id=133 { + extensions ".golo" + } + language name="Gosu" type="programming" color="#82937f" tm_scope="source.gosu.2" ace_mode="text" language_id=134 { + extensions ".gs" ".gst" ".gsx" ".vark" + } + language name="Grace" type="programming" tm_scope="source.grace" ace_mode="text" language_id=135 { + extensions ".grace" + } + language name="Gradle" type="data" tm_scope="source.groovy.gradle" ace_mode="text" language_id=136 { + extensions ".gradle" + } + language name="Grammatical Framework" type="programming" color="#ff0000" tm_scope="source.gf" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=137 { + aliases "gf" + extensions ".gf" + } + language name="Graph Modeling Language" type="data" tm_scope="none" ace_mode="text" language_id=138 { + extensions ".gml" + } + language name="GraphQL" type="data" color="#e10098" tm_scope="source.graphql" ace_mode="text" language_id=139 { + extensions ".graphql" ".gql" ".graphqls" + } + language name="Graphviz (DOT)" type="data" tm_scope="source.dot" ace_mode="text" language_id=140 { + extensions ".dot" ".gv" + } + language name="Groovy" type="programming" color="#e69f56" tm_scope="source.groovy" ace_mode="groovy" codemirror_mime_type="text/x-groovy" language_id=142 { + filenames "Jenkinsfile" + extensions ".groovy" ".grt" ".gtpl" ".gvy" + interpreters "groovy" + } + language name="Groovy Server Pages" type="programming" group="Groovy" tm_scope="text.html.jsp" ace_mode="jsp" codemirror_mime_type="application/x-jsp" language_id=143 { + aliases "gsp" "java server page" + extensions ".gsp" + } + language name="HAProxy" type="data" tm_scope="source.haproxy-config" ace_mode="text" language_id=366607477 { + filenames "haproxy.cfg" + extensions ".cfg" + } + language name="HCL" type="programming" tm_scope="source.terraform" ace_mode="ruby" codemirror_mime_type="text/x-ruby" language_id=144 { + aliases "terraform" + extensions ".hcl" ".nomad" ".tf" ".tfvars" ".workflow" + } + language name="HLSL" type="programming" tm_scope="source.hlsl" ace_mode="text" language_id=145 { + extensions ".hlsl" ".cginc" ".fx" ".fxh" ".hlsli" + } + language name="HTML" type="markup" color="#e34c26" tm_scope="text.html.basic" ace_mode="html" codemirror_mime_type="text/html" language_id=146 { + aliases "xhtml" + extensions ".html" ".htm" ".html.hl" ".inc" ".st" ".xht" ".xhtml" + } + language name="HTML+Django" type="markup" group="HTML" tm_scope="text.html.django" ace_mode="django" codemirror_mime_type="text/x-django" language_id=147 { + aliases "django" "html+django/jinja" "html+jinja" "htmldjango" "njk" "nunjucks" + extensions ".jinja" ".j2" ".jinja2" ".njk" + } + language name="HTML+ECR" type="markup" group="HTML" tm_scope="text.html.ecr" ace_mode="text" codemirror_mime_type="text/html" language_id=148 { + aliases "ecr" + extensions ".ecr" + } + language name="HTML+EEX" type="markup" group="HTML" tm_scope="text.html.elixir" ace_mode="text" codemirror_mime_type="text/html" language_id=149 { + aliases "eex" "leex" + extensions ".eex" ".html.leex" + } + language name="HTML+ERB" type="markup" group="HTML" tm_scope="text.html.erb" ace_mode="text" codemirror_mime_type="application/x-erb" language_id=150 { + aliases "erb" "rhtml" "html+ruby" + extensions ".erb" ".erb.deface" ".rhtml" + } + language name="HTML+PHP" type="markup" group="HTML" tm_scope="text.html.php" ace_mode="php" codemirror_mime_type="application/x-httpd-php" language_id=151 { + extensions ".phtml" + } + language name="HTML+Razor" type="markup" group="HTML" tm_scope="text.html.cshtml" ace_mode="razor" codemirror_mime_type="text/html" language_id=479039817 { + aliases "razor" + extensions ".cshtml" ".razor" + } + language name="HTTP" type="data" tm_scope="source.httpspec" ace_mode="text" codemirror_mime_type="message/http" language_id=152 { + extensions ".http" + } + language name="HXML" type="data" tm_scope="source.hxml" ace_mode="text" language_id=786683730 { + extensions ".hxml" + } + language name="Hack" type="programming" color="#878787" tm_scope="source.hack" ace_mode="php" codemirror_mime_type="application/x-httpd-php" language_id=153 { + extensions ".hack" ".hh" ".hhi" ".php" + } + language name="Haml" type="markup" color="#ece2a9" tm_scope="text.haml" ace_mode="haml" codemirror_mime_type="text/x-haml" language_id=154 { + extensions ".haml" ".haml.deface" + } + language name="Handlebars" type="markup" color="#f7931e" tm_scope="text.html.handlebars" ace_mode="handlebars" language_id=155 { + aliases "hbs" "htmlbars" + extensions ".handlebars" ".hbs" + } + language name="Harbour" type="programming" color="#0e60e3" tm_scope="source.harbour" ace_mode="text" language_id=156 { + extensions ".hb" + } + language name="Haskell" type="programming" color="#5e5086" tm_scope="source.haskell" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=157 { + extensions ".hs" ".hs-boot" ".hsc" + interpreters "runghc" "runhaskell" "runhugs" + } + language name="Haxe" type="programming" color="#df7900" tm_scope="source.hx" ace_mode="haxe" codemirror_mime_type="text/x-haxe" language_id=158 { + extensions ".hx" ".hxsl" + } + language name="HiveQL" type="programming" color="#dce200" tm_scope="source.hql" ace_mode="sql" language_id=931814087 { + extensions ".q" ".hql" + } + language name="HolyC" type="programming" color="#ffefaf" tm_scope="source.hc" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=928121743 { + extensions ".hc" + } + language name="Hy" type="programming" color="#7790B2" tm_scope="source.hy" ace_mode="text" language_id=159 { + aliases "hylang" + extensions ".hy" + interpreters "hy" + } + language name="HyPhy" type="programming" tm_scope="none" ace_mode="text" language_id=160 { + extensions ".bf" + } + language name="IDL" type="programming" color="#a3522f" tm_scope="source.idl" ace_mode="text" codemirror_mime_type="text/x-idl" language_id=161 { + extensions ".pro" ".dlm" + } + language name="IGOR Pro" type="programming" color="#0000cc" tm_scope="source.igor" ace_mode="text" language_id=162 { + aliases "igor" "igorpro" + extensions ".ipf" + } + language name="INI" type="data" tm_scope="source.ini" ace_mode="ini" codemirror_mime_type="text/x-properties" language_id=163 { + aliases "dosini" + filenames "buildozer.spec" + extensions ".ini" ".cfg" ".dof" ".lektorproject" ".prefs" ".pro" ".properties" + } + language name="IRC log" type="data" tm_scope="none" ace_mode="text" codemirror_mime_type="text/mirc" language_id=164 { + aliases "irc" "irc logs" + extensions ".irclog" ".weechatlog" + } + language name="Idris" type="programming" color="#b30000" tm_scope="source.idris" ace_mode="text" language_id=165 { + extensions ".idr" ".lidr" + } + language name="Ignore List" type="data" group="INI" tm_scope="source.gitignore" ace_mode="gitignore" codemirror_mime_type="text/x-sh" language_id=74444240 { + aliases "ignore" "gitignore" "git-ignore" + filenames ".atomignore" ".babelignore" ".bzrignore" ".coffeelintignore" ".cvsignore" ".dockerignore" ".eslintignore" ".gitignore" ".nodemonignore" ".npmignore" ".prettierignore" ".stylelintignore" ".vscodeignore" "gitignore-global" "gitignore_global" + extensions ".gitignore" + } + language name="Inform 7" type="programming" wrap="true" tm_scope="source.inform7" ace_mode="text" language_id=166 { + aliases "i7" "inform7" + extensions ".ni" ".i7x" + } + language name="Inno Setup" type="programming" tm_scope="source.inno" ace_mode="text" language_id=167 { + extensions ".iss" ".isl" + } + language name="Io" type="programming" color="#a9188d" tm_scope="source.io" ace_mode="io" language_id=168 { + extensions ".io" + interpreters "io" + } + language name="Ioke" type="programming" color="#078193" tm_scope="source.ioke" ace_mode="text" language_id=169 { + extensions ".ik" + interpreters "ioke" + } + language name="Isabelle" type="programming" color="#FEFE00" tm_scope="source.isabelle.theory" ace_mode="text" language_id=170 { + extensions ".thy" + } + language name="Isabelle ROOT" type="programming" group="Isabelle" tm_scope="source.isabelle.root" ace_mode="text" language_id=171 { + filenames "ROOT" + } + language name="J" type="programming" color="#9EEDFF" tm_scope="source.j" ace_mode="text" language_id=172 { + extensions ".ijs" + interpreters "jconsole" + } + language name="JFlex" type="programming" group="Lex" color="#DBCA00" tm_scope="source.jflex" ace_mode="text" language_id=173 { + extensions ".flex" ".jflex" + } + language name="JSON" type="data" searchable="false" tm_scope="source.json" ace_mode="json" codemirror_mime_type="application/json" language_id=174 { + filenames ".arcconfig" ".htmlhintrc" ".tern-config" ".tern-project" ".watchmanconfig" "composer.lock" "mcmod.info" + extensions ".json" ".avsc" ".geojson" ".gltf" ".har" ".ice" ".JSON-tmLanguage" ".jsonl" ".mcmeta" ".tfstate" ".tfstate.backup" ".topojson" ".webapp" ".webmanifest" ".yy" ".yyp" + } + language name="JSON with Comments" type="data" group="JSON" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="text/javascript" language_id=423 { + aliases "jsonc" + filenames ".babelrc" ".eslintrc.json" ".jscsrc" ".jshintrc" ".jslintrc" "devcontainer.json" "jsconfig.json" "language-configuration.json" "tsconfig.json" "tslint.json" + extensions ".jsonc" ".sublime-build" ".sublime-commands" ".sublime-completions" ".sublime-keymap" ".sublime-macro" ".sublime-menu" ".sublime-mousemap" ".sublime-project" ".sublime-settings" ".sublime-theme" ".sublime-workspace" ".sublime_metrics" ".sublime_session" + } + language name="JSON5" type="data" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="application/json" language_id=175 { + extensions ".json5" + } + language name="JSONLD" type="data" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="application/json" language_id=176 { + extensions ".jsonld" + } + language name="JSONiq" type="programming" color="#40d47e" tm_scope="source.jq" ace_mode="jsoniq" codemirror_mime_type="application/json" language_id=177 { + extensions ".jq" + } + language name="JSX" type="programming" group="JavaScript" tm_scope="source.js.jsx" ace_mode="javascript" codemirror_mime_type="text/jsx" language_id=178 { + extensions ".jsx" + } + language name="Jasmin" type="programming" tm_scope="source.jasmin" ace_mode="java" language_id=180 { + extensions ".j" + } + language name="Java" type="programming" color="#b07219" tm_scope="source.java" ace_mode="java" codemirror_mime_type="text/x-java" language_id=181 { + extensions ".java" + } + language name="Java Properties" type="data" tm_scope="source.java-properties" ace_mode="properties" codemirror_mime_type="text/x-properties" language_id=519377561 { + extensions ".properties" + } + language name="Java Server Pages" type="programming" group="Java" tm_scope="text.html.jsp" ace_mode="jsp" codemirror_mime_type="application/x-jsp" language_id=182 { + aliases "jsp" + extensions ".jsp" + } + language name="JavaScript" type="programming" color="#f1e05a" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="text/javascript" language_id=183 { + aliases "js" "node" + filenames "Jakefile" + extensions ".js" "._js" ".bones" ".cjs" ".es" ".es6" ".frag" ".gs" ".jake" ".jsb" ".jscad" ".jsfl" ".jsm" ".jss" ".mjs" ".njs" ".pac" ".sjs" ".ssjs" ".xsjs" ".xsjslib" + interpreters "chakra" "d8" "gjs" "js" "node" "nodejs" "qjs" "rhino" "v8" "v8-shell" + } + language name="JavaScript+ERB" type="programming" group="JavaScript" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="application/javascript" language_id=914318960 { + extensions ".js.erb" + } + language name="Jison" type="programming" group="Yacc" tm_scope="source.jison" ace_mode="text" language_id=284531423 { + extensions ".jison" + } + language name="Jison Lex" type="programming" group="Lex" tm_scope="source.jisonlex" ace_mode="text" language_id=406395330 { + extensions ".jisonlex" + } + language name="Jolie" type="programming" color="#843179" tm_scope="source.jolie" ace_mode="text" language_id=998078858 { + extensions ".ol" ".iol" + interpreters "jolie" + } + language name="Jsonnet" type="programming" color="#0064bd" tm_scope="source.jsonnet" ace_mode="text" language_id=664885656 { + extensions ".jsonnet" ".libsonnet" + } + language name="Julia" type="programming" color="#a270ba" tm_scope="source.julia" ace_mode="julia" codemirror_mime_type="text/x-julia" language_id=184 { + extensions ".jl" + interpreters "julia" + } + language name="Jupyter Notebook" type="markup" color="#DA5B0B" tm_scope="source.json" ace_mode="json" codemirror_mime_type="application/json" language_id=185 { + aliases "IPython Notebook" + filenames "Notebook" + extensions ".ipynb" + } + language name="KRL" type="programming" color="#28430A" tm_scope="none" ace_mode="text" language_id=186 { + extensions ".krl" + } + language name="Kaitai Struct" type="programming" color="#773b37" tm_scope="source.yaml" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=818804755 { + aliases "ksy" + extensions ".ksy" + } + language name="KiCad Layout" type="data" tm_scope="source.pcb.sexp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=187 { + aliases "pcbnew" + filenames "fp-lib-table" + extensions ".kicad_pcb" ".kicad_mod" ".kicad_wks" + } + language name="KiCad Legacy Layout" type="data" tm_scope="source.pcb.board" ace_mode="text" language_id=140848857 { + extensions ".brd" + } + language name="KiCad Schematic" type="data" tm_scope="source.pcb.schematic" ace_mode="text" language_id=622447435 { + aliases "eeschema schematic" + extensions ".sch" + } + language name="Kit" type="markup" tm_scope="text.html.basic" ace_mode="html" codemirror_mime_type="text/html" language_id=188 { + extensions ".kit" + } + language name="Kotlin" type="programming" color="#F18E33" tm_scope="source.kotlin" ace_mode="text" codemirror_mime_type="text/x-kotlin" language_id=189 { + extensions ".kt" ".ktm" ".kts" + } + language name="LFE" type="programming" color="#4C3023" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=190 { + extensions ".lfe" + } + language name="LLVM" type="programming" color="#185619" tm_scope="source.llvm" ace_mode="text" language_id=191 { + extensions ".ll" + } + language name="LOLCODE" type="programming" color="#cc9900" tm_scope="none" ace_mode="text" language_id=192 { + extensions ".lol" + } + language name="LSL" type="programming" color="#3d9970" tm_scope="source.lsl" ace_mode="lsl" language_id=193 { + extensions ".lsl" ".lslp" + interpreters "lsl" + } + language name="LTspice Symbol" type="data" tm_scope="source.ltspice.symbol" ace_mode="text" codemirror_mime_type="text/x-spreadsheet" language_id=1013566805 { + extensions ".asy" + } + language name="LabVIEW" type="programming" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=194 { + extensions ".lvproj" ".lvlib" + } + language name="Lark" type="data" group="EBNF" color="#0b130f" tm_scope="source.lark" ace_mode="text" codemirror_mime_type="text/x-ebnf" language_id=758480799 { + extensions ".lark" + } + language name="Lasso" type="programming" color="#999999" tm_scope="file.lasso" ace_mode="text" language_id=195 { + aliases "lassoscript" + extensions ".lasso" ".las" ".lasso8" ".lasso9" + } + language name="Latte" type="markup" color="#f2a542" tm_scope="text.html.smarty" ace_mode="smarty" codemirror_mime_type="text/x-smarty" language_id=196 { + extensions ".latte" + } + language name="Lean" type="programming" tm_scope="source.lean" ace_mode="text" language_id=197 { + extensions ".lean" ".hlean" + } + language name="Less" type="markup" color="#1d365d" tm_scope="source.css.less" ace_mode="less" codemirror_mime_type="text/css" language_id=198 { + extensions ".less" + } + language name="Lex" type="programming" color="#DBCA00" tm_scope="source.lex" ace_mode="text" language_id=199 { + aliases "flex" + filenames "Lexer.x" "lexer.x" + extensions ".l" ".lex" + } + language name="LilyPond" type="programming" tm_scope="source.lilypond" ace_mode="text" language_id=200 { + extensions ".ly" ".ily" + } + language name="Limbo" type="programming" tm_scope="none" ace_mode="text" language_id=201 { + extensions ".b" ".m" + } + language name="Linker Script" type="data" tm_scope="none" ace_mode="text" language_id=202 { + filenames "ld.script" + extensions ".ld" ".lds" ".x" + } + language name="Linux Kernel Module" type="data" tm_scope="none" ace_mode="text" language_id=203 { + extensions ".mod" + } + language name="Liquid" type="markup" tm_scope="text.html.liquid" ace_mode="liquid" language_id=204 { + extensions ".liquid" + } + language name="Literate Agda" type="programming" group="Agda" tm_scope="none" ace_mode="text" language_id=205 { + extensions ".lagda" + } + language name="Literate CoffeeScript" type="programming" group="CoffeeScript" wrap="true" tm_scope="source.litcoffee" ace_mode="text" language_id=206 { + aliases "litcoffee" + extensions ".litcoffee" ".coffee.md" + } + language name="Literate Haskell" type="programming" group="Haskell" tm_scope="text.tex.latex.haskell" ace_mode="text" codemirror_mime_type="text/x-literate-haskell" language_id=207 { + aliases "lhaskell" "lhs" + extensions ".lhs" + } + language name="LiveScript" type="programming" color="#499886" tm_scope="source.livescript" ace_mode="livescript" codemirror_mime_type="text/x-livescript" language_id=208 { + aliases "live-script" "ls" + filenames "Slakefile" + extensions ".ls" "._ls" + } + language name="Logos" type="programming" tm_scope="source.logos" ace_mode="text" language_id=209 { + extensions ".xm" ".x" ".xi" + } + language name="Logtalk" type="programming" tm_scope="source.logtalk" ace_mode="text" language_id=210 { + extensions ".lgt" ".logtalk" + } + language name="LookML" type="programming" color="#652B81" tm_scope="source.yaml" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=211 { + extensions ".lookml" ".model.lkml" ".view.lkml" + } + language name="LoomScript" type="programming" tm_scope="source.loomscript" ace_mode="text" language_id=212 { + extensions ".ls" + } + language name="Lua" type="programming" color="#000080" tm_scope="source.lua" ace_mode="lua" codemirror_mime_type="text/x-lua" language_id=213 { + filenames ".luacheckrc" + extensions ".lua" ".fcgi" ".nse" ".p8" ".pd_lua" ".rbxs" ".rockspec" ".wlua" + interpreters "lua" + } + language name="M" type="programming" tm_scope="none" ace_mode="text" codemirror_mime_type="text/x-mumps" language_id=214 { + aliases "mumps" + extensions ".mumps" ".m" + } + language name="M4" type="programming" tm_scope="source.m4" ace_mode="text" language_id=215 { + extensions ".m4" + } + language name="M4Sugar" type="programming" group="M4" tm_scope="source.m4" ace_mode="text" language_id=216 { + aliases "autoconf" + filenames "configure.ac" + extensions ".m4" + } + language name="MATLAB" type="programming" color="#e16737" tm_scope="source.matlab" ace_mode="matlab" codemirror_mime_type="text/x-octave" language_id=225 { + aliases "octave" + extensions ".matlab" ".m" + } + language name="MAXScript" type="programming" color="#00a6a6" tm_scope="source.maxscript" ace_mode="text" language_id=217 { + extensions ".ms" ".mcr" + } + language name="MLIR" type="programming" color="#5EC8DB" tm_scope="source.mlir" ace_mode="text" language_id=448253929 { + extensions ".mlir" + } + language name="MQL4" type="programming" color="#62A8D6" tm_scope="source.mql5" ace_mode="c_cpp" language_id=426 { + extensions ".mq4" ".mqh" + } + language name="MQL5" type="programming" color="#4A76B8" tm_scope="source.mql5" ace_mode="c_cpp" language_id=427 { + extensions ".mq5" ".mqh" + } + language name="MTML" type="markup" color="#b7e1f4" tm_scope="text.html.basic" ace_mode="html" codemirror_mime_type="text/html" language_id=218 { + extensions ".mtml" + } + language name="MUF" type="programming" group="Forth" tm_scope="none" ace_mode="forth" codemirror_mime_type="text/x-forth" language_id=219 { + extensions ".muf" ".m" + } + language name="Macaulay2" type="programming" color="#d8ffff" tm_scope="source.m2" ace_mode="text" language_id=34167825 { + aliases "m2" + extensions ".m2" + interpreters "M2" + } + language name="Makefile" type="programming" color="#427819" tm_scope="source.makefile" ace_mode="makefile" codemirror_mime_type="text/x-cmake" language_id=220 { + aliases "bsdmake" "make" "mf" + filenames "BSDmakefile" "GNUmakefile" "Kbuild" "Makefile" "Makefile.am" "Makefile.boot" "Makefile.frag" "Makefile.in" "Makefile.inc" "Makefile.wat" "makefile" "makefile.sco" "mkfile" + extensions ".mak" ".d" ".make" ".mk" ".mkfile" + interpreters "make" + } + language name="Mako" type="programming" tm_scope="text.html.mako" ace_mode="text" language_id=221 { + extensions ".mako" ".mao" + } + language name="Markdown" type="prose" color="#083fa1" wrap="true" tm_scope="source.gfm" ace_mode="markdown" codemirror_mime_type="text/x-gfm" language_id=222 { + aliases "pandoc" + filenames "contents.lr" + extensions ".md" ".markdown" ".mdown" ".mdwn" ".mdx" ".mkd" ".mkdn" ".mkdown" ".ronn" ".workbook" + } + language name="Marko" type="markup" color="#42bff2" tm_scope="text.marko" ace_mode="text" codemirror_mime_type="text/html" language_id=932782397 { + aliases "markojs" + extensions ".marko" + } + language name="Mask" type="markup" color="#f97732" tm_scope="source.mask" ace_mode="mask" language_id=223 { + extensions ".mask" + } + language name="Mathematica" type="programming" tm_scope="source.mathematica" ace_mode="text" codemirror_mime_type="text/x-mathematica" language_id=224 { + aliases "mma" + extensions ".mathematica" ".cdf" ".m" ".ma" ".mt" ".nb" ".nbp" ".wl" ".wlt" + } + language name="Maven POM" type="data" tm_scope="text.xml.pom" ace_mode="xml" codemirror_mime_type="text/xml" language_id=226 { + filenames "pom.xml" + } + language name="Max" type="programming" color="#c4a79c" tm_scope="source.json" ace_mode="json" codemirror_mime_type="application/json" language_id=227 { + aliases "max/msp" "maxmsp" + extensions ".maxpat" ".maxhelp" ".maxproj" ".mxt" ".pat" + } + language name="MediaWiki" type="prose" wrap="true" tm_scope="text.html.mediawiki" ace_mode="text" language_id=228 { + extensions ".mediawiki" ".wiki" + } + language name="Mercury" type="programming" color="#ff2b2b" tm_scope="source.mercury" ace_mode="prolog" language_id=229 { + extensions ".m" ".moo" + interpreters "mmi" + } + language name="Meson" type="programming" color="#007800" tm_scope="source.meson" ace_mode="text" language_id=799141244 { + filenames "meson.build" "meson_options.txt" + } + language name="Metal" type="programming" color="#8f14e9" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=230 { + extensions ".metal" + } + language name="Microsoft Developer Studio Project" type="data" tm_scope="none" ace_mode="text" language_id=800983837 { + extensions ".dsp" + } + language name="MiniD" type="programming" searchable="false" tm_scope="none" ace_mode="text" language_id=231 { + extensions ".minid" + } + language name="Mirah" type="programming" color="#c7a938" tm_scope="source.ruby" ace_mode="ruby" codemirror_mime_type="text/x-ruby" language_id=232 { + extensions ".druby" ".duby" ".mirah" + } + language name="Modelica" type="programming" tm_scope="source.modelica" ace_mode="text" codemirror_mime_type="text/x-modelica" language_id=233 { + extensions ".mo" + } + language name="Modula-2" type="programming" tm_scope="source.modula2" ace_mode="text" language_id=234 { + extensions ".mod" + } + language name="Modula-3" type="programming" color="#223388" tm_scope="source.modula-3" ace_mode="text" language_id=564743864 { + extensions ".i3" ".ig" ".m3" ".mg" + } + language name="Module Management System" type="programming" tm_scope="none" ace_mode="text" language_id=235 { + filenames "descrip.mmk" "descrip.mms" + extensions ".mms" ".mmk" + } + language name="Monkey" type="programming" tm_scope="source.monkey" ace_mode="text" language_id=236 { + extensions ".monkey" ".monkey2" + } + language name="Moocode" type="programming" tm_scope="none" ace_mode="text" language_id=237 { + extensions ".moo" + } + language name="MoonScript" type="programming" tm_scope="source.moonscript" ace_mode="text" language_id=238 { + extensions ".moon" + interpreters "moon" + } + language name="Motorola 68K Assembly" type="programming" group="Assembly" tm_scope="source.m68k" ace_mode="assembly_x86" language_id=477582706 { + aliases "m68k" + extensions ".asm" ".i" ".inc" ".s" ".x68" + } + language name="Muse" type="prose" wrap="true" tm_scope="text.muse" ace_mode="text" language_id=474864066 { + aliases "amusewiki" "emacs muse" + extensions ".muse" + } + language name="Mustache" type="markup" group="HTML" tm_scope="text.html.smarty" ace_mode="smarty" codemirror_mime_type="text/x-smarty" language_id=638334590 { + extensions ".mustache" + } + language name="Myghty" type="programming" tm_scope="none" ace_mode="text" language_id=239 { + extensions ".myt" + } + language name="NASL" type="programming" tm_scope="source.nasl" ace_mode="text" language_id=171666519 { + extensions ".nasl" ".inc" + } + language name="NCL" type="programming" color="#28431f" tm_scope="source.ncl" ace_mode="text" language_id=240 { + extensions ".ncl" + } + language name="NEON" type="data" tm_scope="source.neon" ace_mode="text" language_id=481192983 { + aliases "nette object notation" "ne-on" + extensions ".neon" + } + language name="NL" type="data" tm_scope="none" ace_mode="text" language_id=241 { + extensions ".nl" + } + language name="NPM Config" type="data" group="INI" tm_scope="source.ini.npmrc" ace_mode="text" language_id=685022663 { + aliases "npmrc" + filenames ".npmrc" + } + language name="NSIS" type="programming" tm_scope="source.nsis" ace_mode="text" codemirror_mime_type="text/x-nsis" language_id=242 { + extensions ".nsi" ".nsh" + } + language name="NWScript" type="programming" color="#111522" tm_scope="source.c.nwscript" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=731233819 { + extensions ".nss" + } + language name="Nearley" type="programming" color="#990000" tm_scope="source.ne" ace_mode="text" language_id=521429430 { + extensions ".ne" ".nearley" + } + language name="Nemerle" type="programming" color="#3d3c6e" tm_scope="source.nemerle" ace_mode="text" language_id=243 { + extensions ".n" + } + language name="NetLinx" type="programming" color="#0aa0ff" tm_scope="source.netlinx" ace_mode="text" language_id=244 { + extensions ".axs" ".axi" + } + language name="NetLinx+ERB" type="programming" color="#747faa" tm_scope="source.netlinx.erb" ace_mode="text" language_id=245 { + extensions ".axs.erb" ".axi.erb" + } + language name="NetLogo" type="programming" color="#ff6375" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=246 { + extensions ".nlogo" + } + language name="NewLisp" type="programming" color="#87AED7" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=247 { + extensions ".nl" ".lisp" ".lsp" + interpreters "newlisp" + } + language name="Nextflow" type="programming" color="#3ac486" tm_scope="source.nextflow" ace_mode="groovy" language_id=506780613 { + filenames "nextflow.config" + extensions ".nf" + interpreters "nextflow" + } + language name="Nginx" type="data" tm_scope="source.nginx" ace_mode="text" codemirror_mime_type="text/x-nginx-conf" language_id=248 { + aliases "nginx configuration file" + filenames "nginx.conf" + extensions ".nginx" ".nginxconf" ".vhost" + } + language name="Nim" type="programming" color="#ffc200" tm_scope="source.nim" ace_mode="text" language_id=249 { + filenames "nim.cfg" + extensions ".nim" ".nim.cfg" ".nimble" ".nimrod" ".nims" + } + language name="Ninja" type="data" tm_scope="source.ninja" ace_mode="text" language_id=250 { + extensions ".ninja" + } + language name="Nit" type="programming" color="#009917" tm_scope="source.nit" ace_mode="text" language_id=251 { + extensions ".nit" + } + language name="Nix" type="programming" color="#7e7eff" tm_scope="source.nix" ace_mode="nix" language_id=252 { + aliases "nixos" + extensions ".nix" + } + language name="Nu" type="programming" color="#c9df40" tm_scope="source.nu" ace_mode="scheme" codemirror_mime_type="text/x-scheme" language_id=253 { + aliases "nush" + filenames "Nukefile" + extensions ".nu" + interpreters "nush" + } + language name="NumPy" type="programming" group="Python" color="#9C8AF9" tm_scope="none" ace_mode="text" codemirror_mime_type="text/x-python" language_id=254 { + extensions ".numpy" ".numpyw" ".numsc" + } + language name="OCaml" type="programming" color="#3be133" tm_scope="source.ocaml" ace_mode="ocaml" codemirror_mime_type="text/x-ocaml" language_id=255 { + extensions ".ml" ".eliom" ".eliomi" ".ml4" ".mli" ".mll" ".mly" + interpreters "ocaml" "ocamlrun" "ocamlscript" + } + language name="ObjDump" type="data" tm_scope="objdump.x86asm" ace_mode="assembly_x86" language_id=256 { + extensions ".objdump" + } + language name="Object Data Instance Notation" type="data" tm_scope="source.odin-ehr" ace_mode="text" language_id=985227236 { + extensions ".odin" + } + language name="ObjectScript" type="programming" color="#424893" tm_scope="source.objectscript" ace_mode="text" language_id=202735509 { + extensions ".cls" + } + language name="Objective-C" type="programming" color="#438eff" tm_scope="source.objc" ace_mode="objectivec" codemirror_mime_type="text/x-objectivec" language_id=257 { + aliases "obj-c" "objc" "objectivec" + extensions ".m" ".h" + } + language name="Objective-C++" type="programming" color="#6866fb" tm_scope="source.objc++" ace_mode="objectivec" codemirror_mime_type="text/x-objectivec" language_id=258 { + aliases "obj-c++" "objc++" "objectivec++" + extensions ".mm" + } + language name="Objective-J" type="programming" color="#ff0c5a" tm_scope="source.js.objj" ace_mode="text" language_id=259 { + aliases "obj-j" "objectivej" "objj" + extensions ".j" ".sj" + } + language name="Odin" type="programming" color="#60AFFE" tm_scope="source.odin" ace_mode="text" language_id=889244082 { + aliases "odinlang" "odin-lang" + extensions ".odin" + } + language name="Omgrofl" type="programming" color="#cabbff" tm_scope="none" ace_mode="text" language_id=260 { + extensions ".omgrofl" + } + language name="Opa" type="programming" tm_scope="source.opa" ace_mode="text" language_id=261 { + extensions ".opa" + } + language name="Opal" type="programming" color="#f7ede0" tm_scope="source.opal" ace_mode="text" language_id=262 { + extensions ".opal" + } + language name="Open Policy Agent" type="programming" tm_scope="source.rego" ace_mode="text" language_id=840483232 { + extensions ".rego" + } + language name="OpenCL" type="programming" group="C" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=263 { + extensions ".cl" ".opencl" + } + language name="OpenEdge ABL" type="programming" tm_scope="source.abl" ace_mode="text" language_id=264 { + aliases "progress" "openedge" "abl" + extensions ".p" ".cls" ".w" + } + language name="OpenQASM" type="programming" color="#AA70FF" tm_scope="source.qasm" ace_mode="text" language_id=153739399 { + extensions ".qasm" + } + language name="OpenRC runscript" type="programming" group="Shell" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=265 { + aliases "openrc" + interpreters "openrc-run" + } + language name="OpenSCAD" type="programming" tm_scope="source.scad" ace_mode="scad" language_id=266 { + extensions ".scad" + } + language name="OpenStep Property List" type="data" tm_scope="source.plist" ace_mode="text" language_id=598917541 { + extensions ".plist" + } + language name="OpenType Feature File" type="data" tm_scope="source.opentype" ace_mode="text" language_id=374317347 { + aliases "AFDKO" + extensions ".fea" + } + language name="Org" type="prose" wrap="true" tm_scope="none" ace_mode="text" language_id=267 { + extensions ".org" + } + language name="Ox" type="programming" tm_scope="source.ox" ace_mode="text" language_id=268 { + extensions ".ox" ".oxh" ".oxo" + } + language name="Oxygene" type="programming" color="#cdd0e3" tm_scope="none" ace_mode="text" language_id=269 { + extensions ".oxygene" + } + language name="Oz" type="programming" color="#fab738" tm_scope="source.oz" ace_mode="text" codemirror_mime_type="text/x-oz" language_id=270 { + extensions ".oz" + } + language name="P4" type="programming" color="#7055b5" tm_scope="source.p4" ace_mode="text" language_id=348895984 { + extensions ".p4" + } + language name="PHP" type="programming" color="#4F5D95" tm_scope="text.html.php" ace_mode="php" codemirror_mime_type="application/x-httpd-php" language_id=272 { + aliases "inc" + filenames ".php" ".php_cs" ".php_cs.dist" "Phakefile" + extensions ".php" ".aw" ".ctp" ".fcgi" ".inc" ".php3" ".php4" ".php5" ".phps" ".phpt" + interpreters "php" + } + language name="PLSQL" type="programming" color="#dad8d8" tm_scope="none" ace_mode="sql" codemirror_mime_type="text/x-plsql" language_id=273 { + extensions ".pls" ".bdy" ".ddl" ".fnc" ".pck" ".pkb" ".pks" ".plb" ".plsql" ".prc" ".spc" ".sql" ".tpb" ".tps" ".trg" ".vw" + } + language name="PLpgSQL" type="programming" tm_scope="source.sql" ace_mode="pgsql" codemirror_mime_type="text/x-sql" language_id=274 { + extensions ".pgsql" ".sql" + } + language name="POV-Ray SDL" type="programming" tm_scope="source.pov-ray sdl" ace_mode="text" language_id=275 { + aliases "pov-ray" "povray" + extensions ".pov" ".inc" + } + language name="Pan" type="programming" color="#cc0000" tm_scope="source.pan" ace_mode="text" language_id=276 { + extensions ".pan" + } + language name="Papyrus" type="programming" color="#6600cc" tm_scope="source.papyrus.skyrim" ace_mode="text" language_id=277 { + extensions ".psc" + } + language name="Parrot" type="programming" color="#f3ca0a" tm_scope="none" ace_mode="text" language_id=278 { + extensions ".parrot" + } + language name="Parrot Assembly" type="programming" group="Parrot" tm_scope="none" ace_mode="text" language_id=279 { + aliases "pasm" + extensions ".pasm" + interpreters "parrot" + } + language name="Parrot Internal Representation" type="programming" group="Parrot" tm_scope="source.parrot.pir" ace_mode="text" language_id=280 { + aliases "pir" + extensions ".pir" + interpreters "parrot" + } + language name="Pascal" type="programming" color="#E3F171" tm_scope="source.pascal" ace_mode="pascal" codemirror_mime_type="text/x-pascal" language_id=281 { + extensions ".pas" ".dfm" ".dpr" ".inc" ".lpr" ".pascal" ".pp" + interpreters "instantfpc" + } + language name="Pawn" type="programming" color="#dbb284" tm_scope="source.pawn" ace_mode="text" language_id=271 { + extensions ".pwn" ".inc" ".sma" + } + language name="Pep8" type="programming" color="#C76F5B" tm_scope="source.pep8" ace_mode="text" language_id=840372442 { + extensions ".pep" + } + language name="Perl" type="programming" color="#0298c3" tm_scope="source.perl" ace_mode="perl" codemirror_mime_type="text/x-perl" language_id=282 { + aliases "cperl" + filenames "Makefile.PL" "Rexfile" "ack" "cpanfile" + extensions ".pl" ".al" ".cgi" ".fcgi" ".perl" ".ph" ".plx" ".pm" ".psgi" ".t" + interpreters "cperl" "perl" + } + language name="Pic" type="markup" group="Roff" tm_scope="source.pic" ace_mode="text" codemirror_mime_type="text/troff" language_id=425 { + extensions ".pic" ".chem" + } + language name="Pickle" type="data" tm_scope="none" ace_mode="text" language_id=284 { + extensions ".pkl" + } + language name="PicoLisp" type="programming" tm_scope="source.lisp" ace_mode="lisp" language_id=285 { + extensions ".l" + interpreters "picolisp" "pil" + } + language name="PigLatin" type="programming" color="#fcd7de" tm_scope="source.pig_latin" ace_mode="text" language_id=286 { + extensions ".pig" + } + language name="Pike" type="programming" color="#005390" tm_scope="source.pike" ace_mode="text" language_id=287 { + extensions ".pike" ".pmod" + interpreters "pike" + } + language name="PlantUML" type="data" tm_scope="source.wsd" ace_mode="text" language_id=833504686 { + extensions ".puml" ".iuml" ".plantuml" + } + language name="Pod" type="prose" wrap="true" tm_scope="none" ace_mode="perl" codemirror_mime_type="text/x-perl" language_id=288 { + extensions ".pod" + interpreters "perl" + } + language name="Pod 6" type="prose" wrap="true" tm_scope="source.raku" ace_mode="perl" language_id=155357471 { + extensions ".pod" ".pod6" + interpreters "perl6" + } + language name="PogoScript" type="programming" color="#d80074" tm_scope="source.pogoscript" ace_mode="text" language_id=289 { + extensions ".pogo" + } + language name="Pony" type="programming" tm_scope="source.pony" ace_mode="text" language_id=290 { + extensions ".pony" + } + language name="PostCSS" type="markup" group="CSS" tm_scope="source.postcss" ace_mode="text" language_id=262764437 { + extensions ".pcss" ".postcss" + } + language name="PostScript" type="markup" color="#da291c" tm_scope="source.postscript" ace_mode="text" language_id=291 { + aliases "postscr" + extensions ".ps" ".eps" ".epsi" ".pfa" + } + language name="PowerBuilder" type="programming" color="#8f0f8d" tm_scope="none" ace_mode="text" language_id=292 { + extensions ".pbt" ".sra" ".sru" ".srw" + } + language name="PowerShell" type="programming" color="#012456" tm_scope="source.powershell" ace_mode="powershell" codemirror_mime_type="application/x-powershell" language_id=293 { + aliases "posh" "pwsh" + extensions ".ps1" ".psd1" ".psm1" + interpreters "pwsh" + } + language name="Prisma" type="data" color="#0c344b" tm_scope="source.prisma" ace_mode="text" language_id=499933428 { + extensions ".prisma" + } + language name="Processing" type="programming" color="#0096D8" tm_scope="source.processing" ace_mode="text" language_id=294 { + extensions ".pde" + } + language name="Proguard" type="data" tm_scope="none" ace_mode="text" language_id=716513858 { + extensions ".pro" + } + language name="Prolog" type="programming" color="#74283c" tm_scope="source.prolog" ace_mode="prolog" language_id=295 { + extensions ".pl" ".pro" ".prolog" ".yap" + interpreters "swipl" "yap" + } + language name="Propeller Spin" type="programming" color="#7fa2a7" tm_scope="source.spin" ace_mode="text" language_id=296 { + extensions ".spin" + } + language name="Protocol Buffer" type="data" tm_scope="source.protobuf" ace_mode="protobuf" codemirror_mime_type="text/x-protobuf" language_id=297 { + aliases "protobuf" "Protocol Buffers" + extensions ".proto" + } + language name="Public Key" type="data" tm_scope="none" ace_mode="text" codemirror_mime_type="application/pgp" language_id=298 { + extensions ".asc" ".pub" + } + language name="Pug" type="markup" color="#a86454" tm_scope="text.jade" ace_mode="jade" codemirror_mime_type="text/x-pug" language_id=179 { + extensions ".jade" ".pug" + } + language name="Puppet" type="programming" color="#302B6D" tm_scope="source.puppet" ace_mode="text" codemirror_mime_type="text/x-puppet" language_id=299 { + filenames "Modulefile" + extensions ".pp" + } + language name="Pure Data" type="data" tm_scope="none" ace_mode="text" language_id=300 { + extensions ".pd" + } + language name="PureBasic" type="programming" color="#5a6986" tm_scope="none" ace_mode="text" language_id=301 { + extensions ".pb" ".pbi" + } + language name="PureScript" type="programming" color="#1D222D" tm_scope="source.purescript" ace_mode="haskell" codemirror_mime_type="text/x-haskell" language_id=302 { + extensions ".purs" + } + language name="Python" type="programming" color="#3572A5" tm_scope="source.python" ace_mode="python" codemirror_mime_type="text/x-python" language_id=303 { + aliases "python3" "rusthon" + filenames ".gclient" "DEPS" "SConscript" "SConstruct" "Snakefile" "wscript" + extensions ".py" ".cgi" ".fcgi" ".gyp" ".gypi" ".lmi" ".py3" ".pyde" ".pyi" ".pyp" ".pyt" ".pyw" ".rpy" ".smk" ".spec" ".tac" ".wsgi" ".xpy" + interpreters "python" "python2" "python3" + } + language name="Python console" type="programming" group="Python" searchable="false" tm_scope="text.python.console" ace_mode="text" language_id=428 { + aliases "pycon" + } + language name="Python traceback" type="data" group="Python" searchable="false" tm_scope="text.python.traceback" ace_mode="text" language_id=304 { + extensions ".pytb" + } + language name="Q#" type="programming" color="#fed659" tm_scope="source.qsharp" ace_mode="text" language_id=697448245 { + aliases "qsharp" + extensions ".qs" + } + language name="QML" type="programming" color="#44a51c" tm_scope="source.qml" ace_mode="text" language_id=305 { + extensions ".qml" ".qbs" + } + language name="QMake" type="programming" tm_scope="source.qmake" ace_mode="text" language_id=306 { + extensions ".pro" ".pri" + interpreters "qmake" + } + language name="Qt Script" type="programming" color="#00b841" tm_scope="source.js" ace_mode="javascript" codemirror_mime_type="text/javascript" language_id=558193693 { + filenames "installscript.qs" "toolchain_installscript.qs" + extensions ".qs" + } + language name="Quake" type="programming" color="#882233" tm_scope="source.quake" ace_mode="text" language_id=375265331 { + filenames "m3makefile" "m3overrides" + } + language name="R" type="programming" color="#198CE7" tm_scope="source.r" ace_mode="r" codemirror_mime_type="text/x-rsrc" language_id=307 { + aliases "R" "Rscript" "splus" + filenames ".Rprofile" "expr-dist" + extensions ".r" ".rd" ".rsx" + interpreters "Rscript" + } + language name="RAML" type="markup" color="#77d9fb" tm_scope="source.yaml" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=308 { + extensions ".raml" + } + language name="RDoc" type="prose" wrap="true" tm_scope="text.rdoc" ace_mode="rdoc" language_id=309 { + extensions ".rdoc" + } + language name="REALbasic" type="programming" tm_scope="source.vbnet" ace_mode="text" language_id=310 { + extensions ".rbbas" ".rbfrm" ".rbmnu" ".rbres" ".rbtbar" ".rbuistate" + } + language name="REXX" type="programming" tm_scope="source.rexx" ace_mode="text" language_id=311 { + aliases "arexx" + extensions ".rexx" ".pprx" ".rex" + interpreters "regina" "rexx" + } + language name="RMarkdown" type="prose" wrap="true" tm_scope="source.gfm" ace_mode="markdown" codemirror_mime_type="text/x-gfm" language_id=313 { + extensions ".rmd" + } + language name="RPC" type="programming" tm_scope="source.c" ace_mode="c_cpp" language_id=1031374237 { + aliases "rpcgen" "oncrpc" "xdr" + extensions ".x" + } + language name="RPM Spec" type="data" tm_scope="source.rpm-spec" ace_mode="text" codemirror_mime_type="text/x-rpm-spec" language_id=314 { + aliases "specfile" + extensions ".spec" + } + language name="RUNOFF" type="markup" color="#665a4e" wrap="true" tm_scope="text.runoff" ace_mode="text" language_id=315 { + extensions ".rnh" ".rno" + } + language name="Racket" type="programming" color="#3c5caa" tm_scope="source.racket" ace_mode="lisp" language_id=316 { + extensions ".rkt" ".rktd" ".rktl" ".scrbl" + interpreters "racket" + } + language name="Ragel" type="programming" color="#9d5200" tm_scope="none" ace_mode="text" language_id=317 { + aliases "ragel-rb" "ragel-ruby" + extensions ".rl" + } + language name="Raku" type="programming" color="#0000fb" tm_scope="source.raku" ace_mode="perl" codemirror_mime_type="text/x-perl" language_id=283 { + aliases "perl6" "perl-6" + extensions ".6pl" ".6pm" ".nqp" ".p6" ".p6l" ".p6m" ".pl" ".pl6" ".pm" ".pm6" ".t" + interpreters "perl6" "raku" "rakudo" + } + language name="Rascal" type="programming" color="#fffaa0" tm_scope="source.rascal" ace_mode="text" language_id=173616037 { + extensions ".rsc" + } + language name="Raw token data" type="data" tm_scope="none" ace_mode="text" language_id=318 { + aliases "raw" + extensions ".raw" + } + language name="ReScript" type="programming" color="#ed5051" tm_scope="source.rescript" ace_mode="rust" codemirror_mime_type="text/x-rustsrc" language_id=501875647 { + extensions ".res" + interpreters "ocaml" + } + language name="Readline Config" type="data" group="INI" tm_scope="source.inputrc" ace_mode="text" language_id=538732839 { + aliases "inputrc" "readline" + filenames ".inputrc" "inputrc" + } + language name="Reason" type="programming" color="#ff5847" tm_scope="source.reason" ace_mode="rust" codemirror_mime_type="text/x-rustsrc" language_id=869538413 { + extensions ".re" ".rei" + } + language name="Rebol" type="programming" color="#358a5b" tm_scope="source.rebol" ace_mode="text" language_id=319 { + extensions ".reb" ".r" ".r2" ".r3" ".rebol" + } + language name="Red" type="programming" color="#f50000" tm_scope="source.red" ace_mode="text" language_id=320 { + aliases "red/system" + extensions ".red" ".reds" + } + language name="Redcode" type="programming" tm_scope="none" ace_mode="text" language_id=321 { + extensions ".cw" + } + language name="Regular Expression" type="data" tm_scope="source.regexp" ace_mode="text" language_id=363378884 { + aliases "regexp" "regex" + extensions ".regexp" ".regex" + } + language name="Ren'Py" type="programming" color="#ff7f7f" tm_scope="source.renpy" ace_mode="python" language_id=322 { + aliases "renpy" + extensions ".rpy" + } + language name="RenderScript" type="programming" tm_scope="none" ace_mode="text" language_id=323 { + extensions ".rs" ".rsh" + } + language name="Rich Text Format" type="markup" tm_scope="text.rtf" ace_mode="text" language_id=51601661 { + extensions ".rtf" + } + language name="Ring" type="programming" color="#2D54CB" tm_scope="source.ring" ace_mode="text" language_id=431 { + extensions ".ring" + } + language name="Riot" type="markup" color="#A71E49" tm_scope="text.html.riot" ace_mode="html" language_id=878396783 { + extensions ".riot" + } + language name="RobotFramework" type="programming" tm_scope="text.robot" ace_mode="text" language_id=324 { + extensions ".robot" + } + language name="Roff" type="markup" color="#ecdebe" wrap="true" tm_scope="text.roff" ace_mode="text" codemirror_mime_type="text/troff" language_id=141 { + aliases "groff" "man" "manpage" "man page" "man-page" "mdoc" "nroff" "troff" + filenames "eqnrc" "mmn" "mmt" "troffrc" "troffrc-end" + extensions ".roff" ".1" ".1in" ".1m" ".1x" ".2" ".3" ".3in" ".3m" ".3p" ".3pm" ".3qt" ".3x" ".4" ".5" ".6" ".7" ".8" ".9" ".l" ".man" ".mdoc" ".me" ".ms" ".n" ".nr" ".rno" ".tmac" + } + language name="Roff Manpage" type="markup" group="Roff" wrap="true" tm_scope="text.roff" ace_mode="text" codemirror_mime_type="text/troff" language_id=612669833 { + extensions ".1" ".1in" ".1m" ".1x" ".2" ".3" ".3in" ".3m" ".3p" ".3pm" ".3qt" ".3x" ".4" ".5" ".6" ".7" ".8" ".9" ".man" ".mdoc" + } + language name="Rouge" type="programming" color="#cc0088" tm_scope="source.clojure" ace_mode="clojure" codemirror_mime_type="text/x-clojure" language_id=325 { + extensions ".rg" + } + language name="Ruby" type="programming" color="#701516" tm_scope="source.ruby" ace_mode="ruby" codemirror_mime_type="text/x-ruby" language_id=326 { + aliases "jruby" "macruby" "rake" "rb" "rbx" + filenames ".irbrc" ".pryrc" ".simplecov" "Appraisals" "Berksfile" "Brewfile" "Buildfile" "Capfile" "Dangerfile" "Deliverfile" "Fastfile" "Gemfile" "Gemfile.lock" "Guardfile" "Jarfile" "Mavenfile" "Podfile" "Puppetfile" "Rakefile" "Snapfile" "Thorfile" "Vagrantfile" "buildfile" + extensions ".rb" ".builder" ".eye" ".fcgi" ".gemspec" ".god" ".jbuilder" ".mspec" ".pluginspec" ".podspec" ".rabl" ".rake" ".rbi" ".rbuild" ".rbw" ".rbx" ".ru" ".ruby" ".spec" ".thor" ".watchr" + interpreters "ruby" "macruby" "rake" "jruby" "rbx" + } + language name="Rust" type="programming" color="#dea584" tm_scope="source.rust" ace_mode="rust" codemirror_mime_type="text/x-rustsrc" language_id=327 { + extensions ".rs" ".rs.in" + } + language name="SAS" type="programming" color="#B34936" tm_scope="source.sas" ace_mode="text" codemirror_mime_type="text/x-sas" language_id=328 { + extensions ".sas" + } + language name="SCSS" type="markup" color="#c6538c" tm_scope="source.css.scss" ace_mode="scss" codemirror_mime_type="text/x-scss" language_id=329 { + extensions ".scss" + } + language name="SMT" type="programming" tm_scope="source.smt" ace_mode="text" language_id=330 { + extensions ".smt2" ".smt" + interpreters "boolector" "cvc4" "mathsat5" "opensmt" "smtinterpol" "smt-rat" "stp" "verit" "yices2" "z3" + } + language name="SPARQL" type="data" tm_scope="source.sparql" ace_mode="text" codemirror_mime_type="application/sparql-query" language_id=331 { + extensions ".sparql" ".rq" + } + language name="SQF" type="programming" color="#3F3F3F" tm_scope="source.sqf" ace_mode="text" language_id=332 { + extensions ".sqf" ".hqf" + } + language name="SQL" type="data" tm_scope="source.sql" ace_mode="sql" codemirror_mime_type="text/x-sql" language_id=333 { + extensions ".sql" ".cql" ".ddl" ".inc" ".mysql" ".prc" ".tab" ".udf" ".viw" + } + language name="SQLPL" type="programming" tm_scope="source.sql" ace_mode="sql" codemirror_mime_type="text/x-sql" language_id=334 { + extensions ".sql" ".db2" + } + language name="SRecode Template" type="markup" color="#348a34" tm_scope="source.lisp" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=335 { + extensions ".srt" + } + language name="SSH Config" type="data" group="INI" tm_scope="source.ssh-config" ace_mode="text" language_id=554920715 { + filenames "ssh-config" "ssh_config" "sshconfig" "sshconfig.snip" "sshd-config" "sshd_config" + } + language name="STON" type="data" group="Smalltalk" tm_scope="source.smalltalk" ace_mode="text" language_id=336 { + extensions ".ston" + } + language name="SVG" type="data" color="#ff9900" tm_scope="text.xml.svg" ace_mode="xml" codemirror_mime_type="text/xml" language_id=337 { + extensions ".svg" + } + language name="SWIG" type="programming" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=1066250075 { + extensions ".i" + } + language name="Sage" type="programming" tm_scope="source.python" ace_mode="python" codemirror_mime_type="text/x-python" language_id=338 { + extensions ".sage" ".sagews" + } + language name="SaltStack" type="programming" color="#646464" tm_scope="source.yaml.salt" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=339 { + aliases "saltstate" "salt" + extensions ".sls" + } + language name="Sass" type="markup" color="#a53b70" tm_scope="source.sass" ace_mode="sass" codemirror_mime_type="text/x-sass" language_id=340 { + extensions ".sass" + } + language name="Scala" type="programming" color="#c22d40" tm_scope="source.scala" ace_mode="scala" codemirror_mime_type="text/x-scala" language_id=341 { + extensions ".scala" ".kojo" ".sbt" ".sc" + interpreters "scala" + } + language name="Scaml" type="markup" group="HTML" tm_scope="source.scaml" ace_mode="text" language_id=342 { + extensions ".scaml" + } + language name="Scheme" type="programming" color="#1e4aec" tm_scope="source.scheme" ace_mode="scheme" codemirror_mime_type="text/x-scheme" language_id=343 { + extensions ".scm" ".sch" ".sld" ".sls" ".sps" ".ss" + interpreters "scheme" "guile" "bigloo" "chicken" "csi" "gosh" "r6rs" + } + language name="Scilab" type="programming" tm_scope="source.scilab" ace_mode="text" language_id=344 { + extensions ".sci" ".sce" ".tst" + } + language name="Self" type="programming" color="#0579aa" tm_scope="none" ace_mode="text" language_id=345 { + extensions ".self" + } + language name="ShaderLab" type="programming" tm_scope="source.shaderlab" ace_mode="text" language_id=664257356 { + extensions ".shader" + } + language name="Shell" type="programming" color="#89e051" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=346 { + aliases "sh" "shell-script" "bash" "zsh" + filenames ".bash_aliases" ".bash_history" ".bash_logout" ".bash_profile" ".bashrc" ".cshrc" ".env" ".env.example" ".flaskenv" ".login" ".profile" ".zlogin" ".zlogout" ".zprofile" ".zshenv" ".zshrc" "9fs" "PKGBUILD" "bash_aliases" "bash_logout" "bash_profile" "bashrc" "cshrc" "gradlew" "login" "man" "profile" "zlogin" "zlogout" "zprofile" "zshenv" "zshrc" + extensions ".sh" ".bash" ".bats" ".cgi" ".command" ".env" ".fcgi" ".ksh" ".sh.in" ".tmux" ".tool" ".zsh" + interpreters "ash" "bash" "dash" "ksh" "mksh" "pdksh" "rc" "sh" "zsh" + } + language name="ShellSession" type="programming" tm_scope="text.shell-session" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=347 { + aliases "bash session" "console" + extensions ".sh-session" + } + language name="Shen" type="programming" color="#120F14" tm_scope="source.shen" ace_mode="text" language_id=348 { + extensions ".shen" + } + language name="Sieve" type="programming" tm_scope="source.sieve" ace_mode="text" codemirror_mime_type="application/sieve" language_id=208976687 { + extensions ".sieve" + } + language name="Slash" type="programming" color="#007eff" tm_scope="text.html.slash" ace_mode="text" language_id=349 { + extensions ".sl" + } + language name="Slice" type="programming" color="#003fa2" tm_scope="source.slice" ace_mode="text" language_id=894641667 { + extensions ".ice" + } + language name="Slim" type="markup" color="#2b2b2b" tm_scope="text.slim" ace_mode="text" codemirror_mime_type="text/x-slim" language_id=350 { + extensions ".slim" + } + language name="SmPL" type="programming" color="#c94949" tm_scope="source.smpl" ace_mode="text" language_id=164123055 { + aliases "coccinelle" + extensions ".cocci" + } + language name="Smali" type="programming" tm_scope="source.smali" ace_mode="text" language_id=351 { + extensions ".smali" + } + language name="Smalltalk" type="programming" color="#596706" tm_scope="source.smalltalk" ace_mode="text" codemirror_mime_type="text/x-stsrc" language_id=352 { + aliases "squeak" + extensions ".st" ".cs" + } + language name="Smarty" type="programming" tm_scope="text.html.smarty" ace_mode="smarty" codemirror_mime_type="text/x-smarty" language_id=353 { + extensions ".tpl" + } + language name="Solidity" type="programming" color="#AA6746" tm_scope="source.solidity" ace_mode="text" language_id=237469032 { + extensions ".sol" + } + language name="SourcePawn" type="programming" color="#f69e1d" tm_scope="source.sourcepawn" ace_mode="text" language_id=354 { + aliases "sourcemod" + extensions ".sp" ".inc" + } + language name="Spline Font Database" type="data" tm_scope="text.sfd" ace_mode="yaml" language_id=767169629 { + extensions ".sfd" + } + language name="Squirrel" type="programming" color="#800000" tm_scope="source.c++" ace_mode="c_cpp" codemirror_mime_type="text/x-c++src" language_id=355 { + extensions ".nut" + } + language name="Stan" type="programming" color="#b2011d" tm_scope="source.stan" ace_mode="text" language_id=356 { + extensions ".stan" + } + language name="Standard ML" type="programming" color="#dc566d" tm_scope="source.ml" ace_mode="text" codemirror_mime_type="text/x-ocaml" language_id=357 { + aliases "sml" + extensions ".ml" ".fun" ".sig" ".sml" + } + language name="Starlark" type="programming" color="#76d275" tm_scope="source.python" ace_mode="python" codemirror_mime_type="text/x-python" language_id=960266174 { + aliases "bazel" "bzl" + filenames "BUCK" "BUILD" "BUILD.bazel" "Tiltfile" "WORKSPACE" + extensions ".bzl" + } + language name="Stata" type="programming" tm_scope="source.stata" ace_mode="text" language_id=358 { + extensions ".do" ".ado" ".doh" ".ihlp" ".mata" ".matah" ".sthlp" + } + language name="Stylus" type="markup" color="#ff6347" tm_scope="source.stylus" ace_mode="stylus" language_id=359 { + extensions ".styl" + } + language name="SubRip Text" type="data" tm_scope="text.srt" ace_mode="text" language_id=360 { + extensions ".srt" + } + language name="SugarSS" type="markup" group="CSS" tm_scope="source.css.postcss.sugarss" ace_mode="text" language_id=826404698 { + extensions ".sss" + } + language name="SuperCollider" type="programming" color="#46390b" tm_scope="source.supercollider" ace_mode="text" language_id=361 { + extensions ".sc" ".scd" + interpreters "sclang" "scsynth" + } + language name="Svelte" type="markup" color="#ff3e00" tm_scope="source.svelte" ace_mode="html" codemirror_mime_type="text/html" language_id=928734530 { + extensions ".svelte" + } + language name="Swift" type="programming" color="#ffac45" tm_scope="source.swift" ace_mode="text" codemirror_mime_type="text/x-swift" language_id=362 { + extensions ".swift" + } + language name="SystemVerilog" type="programming" color="#DAE1C2" tm_scope="source.systemverilog" ace_mode="verilog" codemirror_mime_type="text/x-systemverilog" language_id=363 { + extensions ".sv" ".svh" ".vh" + } + language name="TI Program" type="programming" color="#A0AA87" tm_scope="none" ace_mode="text" language_id=422 { + extensions ".8xp" ".8xk" ".8xk.txt" ".8xp.txt" + } + language name="TLA" type="programming" tm_scope="source.tla" ace_mode="text" language_id=364 { + extensions ".tla" + } + language name="TOML" type="data" tm_scope="source.toml" ace_mode="toml" codemirror_mime_type="text/x-toml" language_id=365 { + filenames "Cargo.lock" "Gopkg.lock" "poetry.lock" + extensions ".toml" + } + language name="TSQL" type="programming" tm_scope="source.tsql" ace_mode="sql" language_id=918334941 { + extensions ".sql" + } + language name="TSV" type="data" tm_scope="source.generic-db" ace_mode="text" language_id=1035892117 { + extensions ".tsv" + } + language name="TSX" type="programming" group="TypeScript" tm_scope="source.tsx" ace_mode="javascript" codemirror_mime_type="text/jsx" language_id=94901924 { + extensions ".tsx" + } + language name="TXL" type="programming" tm_scope="source.txl" ace_mode="text" language_id=366 { + extensions ".txl" + } + language name="Tcl" type="programming" color="#e4cc98" tm_scope="source.tcl" ace_mode="tcl" codemirror_mime_type="text/x-tcl" language_id=367 { + filenames "owh" "starfield" + extensions ".tcl" ".adp" ".tm" + interpreters "tclsh" "wish" + } + language name="Tcsh" type="programming" group="Shell" tm_scope="source.shell" ace_mode="sh" codemirror_mime_type="text/x-sh" language_id=368 { + extensions ".tcsh" ".csh" + interpreters "tcsh" "csh" + } + language name="TeX" type="markup" color="#3D6117" wrap="true" tm_scope="text.tex.latex" ace_mode="tex" codemirror_mime_type="text/x-stex" language_id=369 { + aliases "latex" + extensions ".tex" ".aux" ".bbx" ".cbx" ".cls" ".dtx" ".ins" ".lbx" ".ltx" ".mkii" ".mkiv" ".mkvi" ".sty" ".toc" + } + language name="Tea" type="markup" tm_scope="source.tea" ace_mode="text" language_id=370 { + extensions ".tea" + } + language name="Terra" type="programming" color="#00004c" tm_scope="source.terra" ace_mode="lua" codemirror_mime_type="text/x-lua" language_id=371 { + extensions ".t" + interpreters "lua" + } + language name="Texinfo" type="prose" wrap="true" tm_scope="text.texinfo" ace_mode="text" language_id=988020015 { + extensions ".texinfo" ".texi" ".txi" + interpreters "makeinfo" + } + language name="Text" type="prose" wrap="true" tm_scope="none" ace_mode="text" language_id=372 { + aliases "fundamental" + filenames "COPYING" "COPYING.regex" "COPYRIGHT.regex" "FONTLOG" "INSTALL" "INSTALL.mysql" "LICENSE" "LICENSE.mysql" "NEWS" "README.1ST" "README.me" "README.mysql" "README.nss" "click.me" "delete.me" "go.mod" "go.sum" "keep.me" "package.mask" "package.use.mask" "package.use.stable.mask" "read.me" "readme.1st" "test.me" "use.mask" "use.stable.mask" + extensions ".txt" ".fr" ".nb" ".ncl" ".no" + } + language name="Textile" type="prose" wrap="true" tm_scope="none" ace_mode="textile" codemirror_mime_type="text/x-textile" language_id=373 { + extensions ".textile" + } + language name="Thrift" type="programming" tm_scope="source.thrift" ace_mode="text" language_id=374 { + extensions ".thrift" + } + language name="Turing" type="programming" color="#cf142b" tm_scope="source.turing" ace_mode="text" language_id=375 { + extensions ".t" ".tu" + } + language name="Turtle" type="data" tm_scope="source.turtle" ace_mode="text" codemirror_mime_type="text/turtle" language_id=376 { + extensions ".ttl" + } + language name="Twig" type="markup" color="#c1d026" tm_scope="text.html.twig" ace_mode="twig" codemirror_mime_type="text/x-twig" language_id=377 { + extensions ".twig" + } + language name="Type Language" type="data" tm_scope="source.tl" ace_mode="text" language_id=632765617 { + aliases "tl" + extensions ".tl" + } + language name="TypeScript" type="programming" color="#2b7489" tm_scope="source.ts" ace_mode="typescript" codemirror_mime_type="application/typescript" language_id=378 { + aliases "ts" + extensions ".ts" + interpreters "deno" "ts-node" + } + language name="Unified Parallel C" type="programming" group="C" color="#4e3617" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=379 { + extensions ".upc" + } + language name="Unity3D Asset" type="data" tm_scope="source.yaml" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=380 { + extensions ".anim" ".asset" ".mask" ".mat" ".meta" ".prefab" ".unity" + } + language name="Unix Assembly" type="programming" group="Assembly" tm_scope="source.x86" ace_mode="assembly_x86" language_id=120 { + extensions ".s" ".ms" + } + language name="Uno" type="programming" color="#9933cc" tm_scope="source.cs" ace_mode="csharp" codemirror_mime_type="text/x-csharp" language_id=381 { + extensions ".uno" + } + language name="UnrealScript" type="programming" color="#a54c4d" tm_scope="source.java" ace_mode="java" codemirror_mime_type="text/x-java" language_id=382 { + extensions ".uc" + } + language name="UrWeb" type="programming" tm_scope="source.ur" ace_mode="text" language_id=383 { + aliases "Ur/Web" "Ur" + extensions ".ur" ".urs" + } + language name="V" type="programming" color="#4f87c4" tm_scope="source.v" ace_mode="golang" codemirror_mime_type="text/x-go" language_id=603371597 { + aliases "vlang" + extensions ".v" + } + language name="VBA" type="programming" color="#867db1" tm_scope="source.vbnet" ace_mode="text" codemirror_mime_type="text/x-vb" language_id=399230729 { + aliases "vb6" "visual basic 6" "visual basic for applications" + extensions ".bas" ".cls" ".frm" ".frx" ".vba" + } + language name="VBScript" type="programming" color="#15dcdc" tm_scope="source.vbnet" ace_mode="text" codemirror_mime_type="text/vbscript" language_id=408016005 { + extensions ".vbs" + } + language name="VCL" type="programming" color="#148AA8" tm_scope="source.varnish.vcl" ace_mode="text" language_id=384 { + extensions ".vcl" + } + language name="VHDL" type="programming" color="#adb2cb" tm_scope="source.vhdl" ace_mode="vhdl" codemirror_mime_type="text/x-vhdl" language_id=385 { + extensions ".vhdl" ".vhd" ".vhf" ".vhi" ".vho" ".vhs" ".vht" ".vhw" + } + language name="Vala" type="programming" color="#fbe5cd" tm_scope="source.vala" ace_mode="vala" language_id=386 { + extensions ".vala" ".vapi" + } + language name="Verilog" type="programming" color="#b2b7f8" tm_scope="source.verilog" ace_mode="verilog" codemirror_mime_type="text/x-verilog" language_id=387 { + extensions ".v" ".veo" + } + language name="Vim Help File" type="prose" tm_scope="text.vim-help" ace_mode="text" language_id=508563686 { + aliases "vimhelp" + extensions ".txt" + } + language name="Vim Snippet" type="markup" tm_scope="source.vim-snippet" ace_mode="text" language_id=81265970 { + aliases "SnipMate" "UltiSnip" "UltiSnips" "NeoSnippet" + extensions ".snip" ".snippet" ".snippets" + } + language name="Vim script" type="programming" color="#199f4b" tm_scope="source.viml" ace_mode="text" language_id=388 { + aliases "vim" "viml" "nvim" + filenames ".exrc" ".gvimrc" ".nvimrc" ".vimrc" "_vimrc" "gvimrc" "nvimrc" "vimrc" + extensions ".vim" ".vba" ".vmb" + } + language name="Visual Basic .NET" type="programming" color="#945db7" tm_scope="source.vbnet" ace_mode="text" codemirror_mime_type="text/x-vb" language_id=389 { + aliases "visual basic" "vbnet" "vb .net" "vb.net" + extensions ".vb" ".vbhtml" + } + language name="Volt" type="programming" color="#1F1F1F" tm_scope="source.d" ace_mode="d" codemirror_mime_type="text/x-d" language_id=390 { + extensions ".volt" + } + language name="Vue" type="markup" color="#2c3e50" tm_scope="text.html.vue" ace_mode="html" language_id=391 { + extensions ".vue" + } + language name="Wavefront Material" type="data" tm_scope="source.wavefront.mtl" ace_mode="text" language_id=392 { + extensions ".mtl" + } + language name="Wavefront Object" type="data" tm_scope="source.wavefront.obj" ace_mode="text" language_id=393 { + extensions ".obj" + } + language name="Web Ontology Language" type="data" tm_scope="text.xml" ace_mode="xml" language_id=394 { + extensions ".owl" + } + language name="WebAssembly" type="programming" color="#04133b" tm_scope="source.webassembly" ace_mode="lisp" codemirror_mime_type="text/x-common-lisp" language_id=956556503 { + aliases "wast" "wasm" + extensions ".wast" ".wat" + } + language name="WebIDL" type="programming" tm_scope="source.webidl" ace_mode="text" codemirror_mime_type="text/x-webidl" language_id=395 { + extensions ".webidl" + } + language name="WebVTT" type="data" wrap="true" tm_scope="source.vtt" ace_mode="text" language_id=658679714 { + extensions ".vtt" + } + language name="Wget Config" type="data" group="INI" tm_scope="source.wgetrc" ace_mode="text" language_id=668457123 { + aliases "wgetrc" + filenames ".wgetrc" + } + language name="Windows Registry Entries" type="data" tm_scope="source.reg" ace_mode="ini" codemirror_mime_type="text/x-properties" language_id=969674868 { + extensions ".reg" + } + language name="Wollok" type="programming" color="#a23738" tm_scope="source.wollok" ace_mode="text" language_id=632745969 { + extensions ".wlk" + } + language name="World of Warcraft Addon Data" type="data" tm_scope="source.toc" ace_mode="text" language_id=396 { + extensions ".toc" + } + language name="X BitMap" type="data" group="C" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=782911107 { + aliases "xbm" + extensions ".xbm" + } + language name="X Font Directory Index" type="data" tm_scope="source.fontdir" ace_mode="text" language_id=208700028 { + filenames "encodings.dir" "fonts.alias" "fonts.dir" "fonts.scale" + } + language name="X PixMap" type="data" group="C" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=781846279 { + aliases "xpm" + extensions ".xpm" ".pm" + } + language name="X10" type="programming" color="#4B6BEF" tm_scope="source.x10" ace_mode="text" language_id=397 { + aliases "xten" + extensions ".x10" + } + language name="XC" type="programming" color="#99DA07" tm_scope="source.xc" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=398 { + extensions ".xc" + } + language name="XCompose" type="data" tm_scope="config.xcompose" ace_mode="text" language_id=225167241 { + filenames ".XCompose" "XCompose" "xcompose" + } + language name="XML" type="data" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=399 { + aliases "rss" "xsd" "wsdl" + filenames ".classpath" ".cproject" ".project" "App.config" "NuGet.config" "Settings.StyleCop" "Web.Debug.config" "Web.Release.config" "Web.config" "packages.config" + extensions ".xml" ".adml" ".admx" ".ant" ".axml" ".builds" ".ccproj" ".ccxml" ".clixml" ".cproject" ".cscfg" ".csdef" ".csl" ".csproj" ".ct" ".depproj" ".dita" ".ditamap" ".ditaval" ".dll.config" ".dotsettings" ".filters" ".fsproj" ".fxml" ".glade" ".gml" ".gmx" ".grxml" ".gst" ".iml" ".ivy" ".jelly" ".jsproj" ".kml" ".launch" ".mdpolicy" ".mjml" ".mm" ".mod" ".mxml" ".natvis" ".ncl" ".ndproj" ".nproj" ".nuspec" ".odd" ".osm" ".pkgproj" ".pluginspec" ".proj" ".props" ".ps1xml" ".psc1" ".pt" ".rdf" ".res" ".resx" ".rss" ".sch" ".scxml" ".sfproj" ".shproj" ".srdf" ".storyboard" ".sublime-snippet" ".targets" ".tml" ".ts" ".tsx" ".ui" ".urdf" ".ux" ".vbproj" ".vcxproj" ".vsixmanifest" ".vssettings" ".vstemplate" ".vxml" ".wixproj" ".workflow" ".wsdl" ".wsf" ".wxi" ".wxl" ".wxs" ".x3d" ".xacro" ".xaml" ".xib" ".xlf" ".xliff" ".xmi" ".xml.dist" ".xproj" ".xsd" ".xspec" ".xul" ".zcml" + } + language name="XML Property List" type="data" group="XML" tm_scope="text.xml.plist" ace_mode="xml" codemirror_mime_type="text/xml" language_id=75622871 { + extensions ".plist" ".stTheme" ".tmCommand" ".tmLanguage" ".tmPreferences" ".tmSnippet" ".tmTheme" + } + language name="XPages" type="data" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=400 { + extensions ".xsp-config" ".xsp.metadata" + } + language name="XProc" type="programming" tm_scope="text.xml" ace_mode="xml" codemirror_mime_type="text/xml" language_id=401 { + extensions ".xpl" ".xproc" + } + language name="XQuery" type="programming" color="#5232e7" tm_scope="source.xq" ace_mode="xquery" codemirror_mime_type="application/xquery" language_id=402 { + extensions ".xquery" ".xq" ".xql" ".xqm" ".xqy" + } + language name="XS" type="programming" tm_scope="source.c" ace_mode="c_cpp" codemirror_mime_type="text/x-csrc" language_id=403 { + extensions ".xs" + } + language name="XSLT" type="programming" color="#EB8CEB" tm_scope="text.xml.xsl" ace_mode="xml" codemirror_mime_type="text/xml" language_id=404 { + aliases "xsl" + extensions ".xslt" ".xsl" + } + language name="Xojo" type="programming" tm_scope="source.xojo" ace_mode="text" language_id=405 { + extensions ".xojo_code" ".xojo_menu" ".xojo_report" ".xojo_script" ".xojo_toolbar" ".xojo_window" + } + language name="Xtend" type="programming" tm_scope="source.xtend" ace_mode="text" language_id=406 { + extensions ".xtend" + } + language name="YAML" type="data" color="#cb171e" tm_scope="source.yaml" ace_mode="yaml" codemirror_mime_type="text/x-yaml" language_id=407 { + aliases "yml" + filenames ".clang-format" ".clang-tidy" ".gemrc" "glide.lock" "yarn.lock" + extensions ".yml" ".mir" ".reek" ".rviz" ".sublime-syntax" ".syntax" ".yaml" ".yaml-tmlanguage" ".yaml.sed" ".yml.mysql" + } + language name="YANG" type="data" tm_scope="source.yang" ace_mode="text" language_id=408 { + extensions ".yang" + } + language name="YARA" type="programming" color="#220000" tm_scope="source.yara" ace_mode="text" language_id=805122868 { + extensions ".yar" ".yara" + } + language name="YASnippet" type="markup" color="#32AB90" tm_scope="source.yasnippet" ace_mode="text" language_id=378760102 { + aliases "snippet" "yas" + extensions ".yasnippet" + } + language name="Yacc" type="programming" color="#4B6C4B" tm_scope="source.yacc" ace_mode="text" language_id=409 { + extensions ".y" ".yacc" ".yy" + } + language name="ZAP" type="programming" color="#0d665e" tm_scope="source.zap" ace_mode="text" language_id=952972794 { + extensions ".zap" ".xzap" + } + language name="ZIL" type="programming" color="#dc75e5" tm_scope="source.zil" ace_mode="text" language_id=973483626 { + extensions ".zil" ".mud" + } + language name="Zeek" type="programming" tm_scope="source.zeek" ace_mode="text" language_id=40 { + aliases "bro" + extensions ".zeek" ".bro" + } + language name="ZenScript" type="programming" color="#00BCD1" tm_scope="source.zenscript" ace_mode="text" language_id=494938890 { + extensions ".zs" + } + language name="Zephir" type="programming" color="#118f9e" tm_scope="source.php.zephir" ace_mode="php" language_id=410 { + extensions ".zep" + } + language name="Zig" type="programming" color="#ec915c" tm_scope="source.zig" ace_mode="text" language_id=646424281 { + extensions ".zig" + } + language name="Zimpl" type="programming" tm_scope="none" ace_mode="text" language_id=411 { + extensions ".zimpl" ".zmpl" ".zpl" + } + language name="cURL Config" type="data" group="INI" tm_scope="source.curlrc" ace_mode="text" language_id=992375436 { + aliases "curlrc" + filenames ".curlrc" "_curlrc" + } + language name="desktop" type="data" tm_scope="source.desktop" ace_mode="text" language_id=412 { + extensions ".desktop" ".desktop.in" + } + language name="dircolors" type="data" tm_scope="source.dircolors" ace_mode="text" language_id=691605112 { + filenames ".dir_colors" ".dircolors" "DIR_COLORS" "_dir_colors" "_dircolors" "dir_colors" + extensions ".dircolors" + } + language name="eC" type="programming" color="#913960" tm_scope="source.c.ec" ace_mode="text" language_id=413 { + extensions ".ec" ".eh" + } + language name="edn" type="data" tm_scope="source.clojure" ace_mode="clojure" codemirror_mime_type="text/x-clojure" language_id=414 { + extensions ".edn" + } + language name="fish" type="programming" group="Shell" tm_scope="source.fish" ace_mode="text" language_id=415 { + extensions ".fish" + interpreters "fish" + } + language name="mIRC Script" type="programming" color="#3d57c3" tm_scope="source.msl" ace_mode="text" language_id=517654727 { + extensions ".mrc" + } + language name="mcfunction" type="programming" color="#E22837" tm_scope="source.mcfunction" ace_mode="text" language_id=462488745 { + extensions ".mcfunction" + } + language name="mupad" type="programming" tm_scope="source.mupad" ace_mode="text" language_id=416 { + extensions ".mu" + } + language name="nanorc" type="data" group="INI" tm_scope="source.nanorc" ace_mode="text" language_id=775996197 { + filenames ".nanorc" "nanorc" + extensions ".nanorc" + } + language name="nesC" type="programming" color="#94B0C7" tm_scope="source.nesc" ace_mode="text" language_id=417 { + extensions ".nc" + } + language name="ooc" type="programming" color="#b0b77e" tm_scope="source.ooc" ace_mode="text" language_id=418 { + extensions ".ooc" + } + language name="q" type="programming" color="#0040cd" tm_scope="source.q" ace_mode="text" language_id=970539067 { + extensions ".q" + } + language name="reStructuredText" type="prose" wrap="true" tm_scope="text.restructuredtext" ace_mode="text" codemirror_mime_type="text/x-rst" language_id=419 { + aliases "rst" + extensions ".rst" ".rest" ".rest.txt" ".rst.txt" + } + language name="sed" type="programming" color="#64b970" tm_scope="source.sed" ace_mode="text" language_id=847830017 { + extensions ".sed" + interpreters "gsed" "minised" "sed" "ssed" + } + language name="wdl" type="programming" color="#42f1f4" tm_scope="source.wdl" ace_mode="text" language_id=374521672 { + extensions ".wdl" + } + language name="wisp" type="programming" color="#7582D1" tm_scope="source.clojure" ace_mode="clojure" codemirror_mime_type="text/x-clojure" language_id=420 { + extensions ".wisp" + } + language name="xBase" type="programming" color="#403a40" tm_scope="source.harbour" ace_mode="text" language_id=421 { + aliases "advpl" "clipper" "foxpro" + extensions ".prg" ".ch" ".prw" + } +} diff --git a/config/Typos.kdl b/config/Typos.kdl new file mode 100644 index 00000000..ab7d5738 --- /dev/null +++ b/config/Typos.kdl @@ -0,0 +1,11 @@ + +//############################################################################### +// Typos.kdl +// +// This configuration file defines information necessary to detect typos based +// on the package ecosystem being used. +//############################################################################### + +languages { + javascript "lodash" "chalk" "react" "request" "commander" "express" "moment" "react-dom" "prop-types" "debug" "fs-extra" "tslib" "async" "bluebird" "axios" "uuid" "underscore" "vue" "classnames" "mkdirp" "webpack" "yargs" "body-parser" "rxjs" "glob" "inquirer" "colors" "core-js" "babel-runtime" "jquery" "minimist" "dotenv" "aws-sdk" "babel-core" "typescript" "babel-loader" "cheerio" "rimraf" "q" "eslint" "css-loader" "shelljs" "dotenv" "typescript" "@types/node" "@angular/core" "js-yaml" "style-loader" "winston" "@angular/common" "redux" "object-assign" "zone.js" "babel-eslint" "gulp" "gulp-util" "file-loader" "ora" "node-fetch" "@angular/platform-browser" "@babel/runtime" "handlebars" "eslint-plugin-import" "@angular/compiler" "eslint-plugin-react" "aws-sdk" "yosay" "url-loader" "@angular/forms" "webpack-dev-server" "@angular/platform-browser-dynamic" "mocha" "html-webpack-plugin" "socket.io" "ws" "babel-preset-es2015" "postcss-loader" "node-sass" "ember-cli-babel" "babel-polyfill" "@angular/router" "ramda" "react-redux" "@babel/core" "@angular/http" "ejs" "coffee-script" "superagent" "request-promise" "autoprefixer" "path" "mongodb" "chai" "mongoose" "xml2js" "bootstrap" "jest" "sass-loader" "redis" "vue-router" "chokidar" "co" "eslint-plugin-jsx-a11y" "nan" "optimist" "promise" "@angular/animations" "postcss" "morgan" "less" "immutable" "qs" "loader-utils" "fs" "extract-text-webpack-plugin" "marked" "mime" "@alifd/next" "meow" "styled-components" "resolve" "reflect-metadata" "babel-preset-react" "jsonwebtoken" "react-router-dom" "extend" "cookie-parser" "whatwg-fetch" "babel-preset-env" "babel-jest" "mysql" "joi" "minimatch" "eslint-loader" "react-dev-utils" "node-uuid" "es6-promise" "cross-spawn" "case-sensitive-paths-webpack-plugin" "uglify-js" "cors" "eslint-plugin-flowtype" "react-router" "@babel/preset-env" "deepmerge" "socket.io-client" "npm" "webpack-manifest-plugin" "koa" "isomorphic-fetch" "babel-cli" "del" "postcss-flexbugs-fixes" "compression" "update-notifier" "babel-preset-react-app" "jade" "prompt" "gulp-rename" "angular" "underscore.string" "graphql" "execa" "browserify" "opn" "validator" "eslint-config-react-app" "vuex" "prettier" "invariant" "jsdom" "@types/react" "redux-thunk" "mini-css-extract-plugin" "globby" "pg" "got" "ajv" "xtend" "ember-cli-htmlbars" "babel-plugin-transform-runtime" "nodemailer" "source-map-support" "express-session" "d3" "less-loader" "fsevents" "babel-preset-stage-0" "download-git-repo" "query-string" "font-awesome" "open" "passport" "@types/lodash" "grunt" "path-to-regexp" "mustache" "inherits" "tmp" "md5" "dotenv-expand" "crypto-js" "request-promise-native" "through" "connect" "raf" "react-scripts" "readable-stream" "highlight.js" "@babel/polyfill" "progress" "optimize-css-assets-webpack-plugin" "iconv-lite" "bunyan" "gulp-uglify" "koa-router" "ncp" "lodash.merge" "lru-cache" "moment-timezone" "figlet" "history" "readline-sync" "pluralize" "url" "log4js" "cli-table" "webpack-merge" "archiver" "babel-register" "eslint-config-airbnb" "clone" "jsonfile" "puppeteer" "shortid" "@babel/plugin-proposal-class-properties" "querystring" "serve-static" "tslint" "pug" "config" "source-map" "antd" "concat-stream" "element-ui" "lodash.get" "@babel/preset-react" "serve-favicon" "stylus" "date-fns" "esprima" "sequelize" "babel-plugin-transform-object-rest-spread" "bindings" "events" "graceful-fs" "normalize.css" "crypto" "cross-env" "mime-types" "event-stream" "hoist-non-react-statics" "gulp-concat" "terser-webpack-plugin" "json-loader" "warning" "bignumber.js" "eventemitter3" "webpack-cli" "strip-ansi" "cli-color" "form-data" "web3" "gulp-sourcemaps" "webpack-dev-middleware" "ip" "camelcase" "sw-precache-webpack-plugin" "merge" "http-proxy" "react-transition-group" "multer" "deep-equal" "browser-sync" "babel" "dateformat" "postcss-preset-env" "uglifyjs-webpack-plugin" "@polymer/polymer" "sinon" "eslint-config-prettier" "gulp-sass" "identity-obj-proxy" "ts-loader" "react-hot-loader" "sqlite3" "popper.js" "which" "markdown-it" "tar" "vue-template-compiler" "babel-plugin-transform-class-properties" "js-beautify" "log-symbols" "webpack-hot-middleware" "rollup" "copy-webpack-plugin" "nodemon" "boom" "xmldom" "recompose" "util" "ini" "pify" "command-line-args" "vinyl" "mz" "lodash.debounce" "html-minifier" "ts-node" "nconf" "recursive-readdir" "vue-loader" "@types/express" "datafire" "@types/react-dom" "babel-plugin-transform-decorators-legacy" "clean-css" "hoek" "cookie" "@babel/plugin-transform-runtime" "when" "babel-plugin-named-asset-import" "postcss-safe-parser" "bcrypt" "@material-ui/core" "@babel/plugin-syntax-dynamic-import" "nunjucks" "eslint-plugin-promise" "react-native" "lodash.isequal" "workbox-webpack-plugin" "acorn" "amqplib" "@svgr/webpack" "color" "ms" "js-cookie" "temp" "simple-git" "cssnano" "reselect" "yamljs" "ioredis" "koa-static" "react-app-polyfill" "react-select" "escape-string-regex" "firebase" "bn.js" "escodegen" +} diff --git a/config/local.Hipcheck.kdl b/config/local.Hipcheck.kdl index a20e0445..2ea1190c 100644 --- a/config/local.Hipcheck.kdl +++ b/config/local.Hipcheck.kdl @@ -22,8 +22,8 @@ analyze { category "practices" { analysis "mitre/activity" policy="(lte $ P52w)" weight=3 analysis "mitre/binary" { - binary-file #rel("Binary.toml") - binary-file-threshold 0 + binary-file #rel("Binary.kdl") + binary-file-threshold 0 } analysis "mitre/fuzz" policy="(eq #t $)" analysis "mitre/review" policy="(lte (divz (count (filter (eq #f) $)) (count $)) 0.05)" @@ -31,7 +31,7 @@ analyze { category "attacks" { analysis "mitre/typo" { - typo-file #rel("Typos.toml") + typo-file #rel("Typos.kdl") count-threshold 0 } @@ -42,12 +42,12 @@ analyze { } analysis "mitre/entropy" policy="(eq 0 (count (filter (gt 8.0) $)))" { - langs-file #rel("Langs.toml") - entropy-threshold 10.0 - commit-percentage 0.0 + langs-file #rel("Langs.kdl") + entropy-threshold 10.0 + commit-percentage 0.0 } analysis "mitre/churn" policy="(lte (divz (count (filter (gt 3) $)) (count $)) 0.02)" { - langs-file #rel("Langs.toml") + langs-file #rel("Langs.kdl") } } } diff --git a/hipcheck/src/config.rs b/hipcheck/src/config.rs index f96efa6b..0cdfd709 100644 --- a/hipcheck/src/config.rs +++ b/hipcheck/src/config.rs @@ -205,7 +205,7 @@ pub struct AffiliationConfig { pub count_threshold: u64, /// An "orgs file" containing info for affiliation matching. - #[default = "plugins/affiliation/test/example_orgs.kdl"] + #[default = "Orgs.kdl"] pub orgs_file: String, } @@ -214,7 +214,7 @@ pub struct AffiliationConfig { #[serde(default)] pub struct BinaryConfig { /// Binary file extension configuration file. - #[default = "Binary.toml"] + #[default = "Binary.kdl"] pub binary_config_file: String, /// Whether the analysis is active. @@ -369,7 +369,7 @@ pub struct TypoConfig { pub count_threshold: u64, /// Path to a "typos file" containing necessary information for typo detection. - #[default = "Typos.toml"] + #[default = "Typos.kdl"] pub typo_file: String, } @@ -378,7 +378,7 @@ pub struct TypoConfig { #[serde(default)] pub struct LanguagesConfig { /// The file to pull language information from. - #[default = "Langs.toml"] + #[default = "Langs.kdl"] pub langs_file: String, } diff --git a/hipcheck/src/policy/config_to_policy.rs b/hipcheck/src/policy/config_to_policy.rs index ffc5b9d8..90f90f3c 100644 --- a/hipcheck/src/policy/config_to_policy.rs +++ b/hipcheck/src/policy/config_to_policy.rs @@ -358,8 +358,10 @@ fn parse_affiliation( let file = affiliation.orgs_file.clone(); let mut config = PolicyConfig::new(); config - // Our working .kdl orgs file is not in `config` currently - .insert("orgs-file".to_string(), Value::String(file)) + .insert( + "orgs-file".to_string(), + Value::String(format!("./config/{}", file)), + ) .unwrap(); // Add the plugin diff --git a/plugins/binary/Cargo.toml b/plugins/binary/Cargo.toml index 1e1637b8..2beb1961 100644 --- a/plugins/binary/Cargo.toml +++ b/plugins/binary/Cargo.toml @@ -12,6 +12,7 @@ content_inspector = "0.2.4" hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ "macros", ] } +kdl = "4.7.1" log = "0.4.22" pathbuf = "1.0.0" schemars = "0.8.21" diff --git a/plugins/binary/src/binary_detector.rs b/plugins/binary/src/binary_detector.rs index a43ee886..558eb0bc 100644 --- a/plugins/binary/src/binary_detector.rs +++ b/plugins/binary/src/binary_detector.rs @@ -1,9 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 -use crate::{ - error::{Context, Result}, - fs::read_toml, -}; +use crate::error::{Context, Result}; +use crate::util::fs::read_kdl; +use crate::util::kdl::ParseKdlNode; use content_inspector::{inspect, ContentType}; use serde::{de::Visitor, Deserialize, Deserializer}; use std::{ @@ -22,11 +21,11 @@ pub struct BinaryFileDetector { } impl BinaryFileDetector { - /// Constructs a new `BinaryFileDetector` from the `Binary.toml` file. + /// Constructs a new `BinaryFileDetector` from the `Binary.kdl` file. pub fn load>(binary_config_file: P) -> crate::error::Result { fn inner(binary_config_file: &Path) -> crate::error::Result { - let extensions_file: ExtensionsFile = read_toml(binary_config_file) - .context("failed to read binary type defintions from Binary config file")?; + let extensions_file: ExtensionsFile = read_kdl(binary_config_file) + .context("failed to read binary type definitions from Binary config file: ")?; let extensions = extensions_file.into_extensions(); @@ -61,15 +60,27 @@ struct ExtensionsFile { formats: Vec, } -#[derive(Debug, Deserialize)] -struct BinaryExtensions { - #[serde(default = "missing_bin_type")] - r#type: BinaryType, - extensions: Option>, +impl ParseKdlNode for ExtensionsFile { + fn kdl_key() -> &'static str { + "format" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let mut formats = Vec::new(); + for node in node.children()?.nodes() { + formats.push(BinaryExtensions::parse_node(node)?); + } + + Some(Self { formats }) + } } impl ExtensionsFile { - /// Collects the known file extensions from Binary.toml + /// Collects the known file extensions from Binary.kdl fn into_extensions(self) -> Vec { let mut result = Vec::new(); for file_format in self.formats { @@ -87,6 +98,51 @@ impl ExtensionsFile { } } +#[derive(Debug, Deserialize)] +struct BinaryExtensions { + #[serde(default = "missing_bin_type")] + r#type: BinaryType, + extensions: Option>, +} + +impl ParseKdlNode for BinaryExtensions { + fn kdl_key() -> &'static str { + "format" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let binary_type = node.get("type")?.value().as_string()?; + + let r#type = + match binary_type { + "object" => Some(BinaryType::Object), + "executable" => Some(BinaryType::Executable), + "combination" => Some(BinaryType::Combination), + _ => None, + }?; + + + + let mut extensions = Vec::new(); + for node in node.children()?.nodes() { + if node.name().to_string().as_str() == "extensions" { + for entry in node.entries() { + extensions.push(entry.value().as_string()?.to_string()); + } + } + } + + Some(Self { + r#type, + extensions: Some(extensions), + }) + } +} + #[derive(Debug)] enum BinaryType { Object, diff --git a/plugins/binary/src/fs.rs b/plugins/binary/src/fs.rs deleted file mode 100644 index abf05af2..00000000 --- a/plugins/binary/src/fs.rs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -use crate::error::*; - -use serde::de::DeserializeOwned; -use std::{fs, path::Path}; - -/// Read a file to a string. -pub fn read_string>(path: P) -> Result { - fn inner(path: &Path) -> Result { - fs::read_to_string(path) - .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) - } - - inner(path.as_ref()) -} - -/// Read file to a struct that can be deserialized from TOML format. -pub fn read_toml, T: DeserializeOwned>(path: P) -> Result { - let path = path.as_ref(); - let contents = read_string(path)?; - toml::de::from_str(&contents) - .with_context(|| format!("failed to read as TOML '{}'", path.display())) -} diff --git a/plugins/binary/src/main.rs b/plugins/binary/src/main.rs index 0fdfd72a..1e8ed440 100644 --- a/plugins/binary/src/main.rs +++ b/plugins/binary/src/main.rs @@ -2,7 +2,7 @@ mod binary_detector; mod error; -mod fs; +mod util; use crate::binary_detector::{detect_binary_files, BinaryFileDetector}; use clap::Parser; diff --git a/plugins/binary/src/util/fs.rs b/plugins/binary/src/util/fs.rs new file mode 100644 index 00000000..1d04a0b1 --- /dev/null +++ b/plugins/binary/src/util/fs.rs @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::kdl::{extract_data, ParseKdlNode}; +use crate::error::*; +use kdl::KdlDocument; +use std::{fs, path::Path, str::FromStr}; + +/// Read a file to a string. +pub fn read_string>(path: P) -> Result { + fn inner(path: &Path) -> Result { + fs::read_to_string(path) + .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) + } + + inner(path.as_ref()) +} + +/// Read file to a struct that can be deserialized from kdl format. +pub fn read_kdl, T: ParseKdlNode>(path: P) -> Result { + let path = path.as_ref(); + let contents = read_string(path)?; + let document = KdlDocument::from_str(&contents).map_err(|e| Error::new(e))?; + let nodes = document.nodes(); + extract_data(nodes).ok_or(Error::msg("Could not parse binary KDL 'format'")) +} diff --git a/plugins/binary/src/util/kdl.rs b/plugins/binary/src/util/kdl.rs new file mode 100644 index 00000000..095c0d34 --- /dev/null +++ b/plugins/binary/src/util/kdl.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! General shared types and functions for KDL files + +use kdl::KdlNode; + +// Helper trait to make it easier to parse KdlNodes into our own types +pub trait ParseKdlNode +where + Self: Sized, +{ + /// Return the name of the attribute used to identify the node pertaining to this struct + fn kdl_key() -> &'static str; + + /// Attempt to convert a `kdl::KdlNode` into Self + fn parse_node(node: &KdlNode) -> Option; +} + +/// Returns the first successful node that can be parsed into T, if there is one +pub fn extract_data(nodes: &[KdlNode]) -> Option +where + T: ParseKdlNode, +{ + for node in nodes { + if let Some(val) = T::parse_node(node) { + return Some(val); + } + } + None +} + +/// Use this macro to generate the code needed to parse a KDL node that is a single string, as the +/// code is quite repetitive for this simple task. +/// +/// As a bonus, the following code is also generated: +/// - AsRef +/// - new(value: String) -> Self +/// +/// NOTE: This only works with newtype wrappers around String! +/// +/// Example: +/// publisher "mitre" can be generated by this macro! +/// +/// ```rust +/// struct Publisher(pub String) +/// ``` +#[macro_export] +macro_rules! string_newtype_parse_kdl_node { + ($type:ty, $identifier:expr) => { + impl $type { + #[allow(dead_code)] + pub fn new(value: String) -> Self { + Self(value) + } + } + + impl ParseKdlNode for $type { + fn kdl_key() -> &'static str { + $identifier + } + + fn parse_node(node: &KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + // NOTE: this macro currently assumes that the first positional argument is the + // correct value to be parsing, which is true for newtype String wrappers! + let entry = node.entries().first()?.value().as_string()?.to_string(); + Some(Self(entry)) + } + } + + impl AsRef for $type { + fn as_ref(&self) -> &String { + &self.0 + } + } + }; +} diff --git a/plugins/binary/src/util/mod.rs b/plugins/binary/src/util/mod.rs new file mode 100644 index 00000000..e7db251a --- /dev/null +++ b/plugins/binary/src/util/mod.rs @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod fs; +pub mod kdl; diff --git a/plugins/churn/Cargo.toml b/plugins/churn/Cargo.toml index ff556bea..16205bbe 100644 --- a/plugins/churn/Cargo.toml +++ b/plugins/churn/Cargo.toml @@ -12,12 +12,14 @@ hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ "macros", ] } log = "0.4.22" +anyhow = "1.0.95" salsa = "0.16.1" schemars = "0.8.21" serde = "1.0.215" serde_json = "1.0.134" tokio = { version = "1.42.0", features = ["rt"] } toml = "0.8.19" +kdl = "4.7.1" [dev-dependencies] hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ diff --git a/plugins/churn/src/linguist/fs.rs b/plugins/churn/src/linguist/fs.rs index abf05af2..2af1a8ae 100644 --- a/plugins/churn/src/linguist/fs.rs +++ b/plugins/churn/src/linguist/fs.rs @@ -1,9 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 -use crate::error::*; - -use serde::de::DeserializeOwned; -use std::{fs, path::Path}; +use super::kdl_util::{extract_data, ParseKdlNode}; +use anyhow::{anyhow, Context as _, Result}; +use kdl::KdlDocument; +use std::{fs, path::Path, str::FromStr}; /// Read a file to a string. pub fn read_string>(path: P) -> Result { @@ -15,10 +15,11 @@ pub fn read_string>(path: P) -> Result { inner(path.as_ref()) } -/// Read file to a struct that can be deserialized from TOML format. -pub fn read_toml, T: DeserializeOwned>(path: P) -> Result { +/// Read file to a struct that can be deserialized from kdl format. +pub fn read_kdl, T: ParseKdlNode>(path: P) -> Result { let path = path.as_ref(); let contents = read_string(path)?; - toml::de::from_str(&contents) - .with_context(|| format!("failed to read as TOML '{}'", path.display())) + let document = KdlDocument::from_str(&contents).map_err(|e| anyhow!(e))?; + let nodes = document.nodes(); + extract_data(nodes).ok_or(anyhow!("Could not parse langs KDL 'format'")) } diff --git a/plugins/churn/src/linguist/kdl_util.rs b/plugins/churn/src/linguist/kdl_util.rs new file mode 100644 index 00000000..095c0d34 --- /dev/null +++ b/plugins/churn/src/linguist/kdl_util.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! General shared types and functions for KDL files + +use kdl::KdlNode; + +// Helper trait to make it easier to parse KdlNodes into our own types +pub trait ParseKdlNode +where + Self: Sized, +{ + /// Return the name of the attribute used to identify the node pertaining to this struct + fn kdl_key() -> &'static str; + + /// Attempt to convert a `kdl::KdlNode` into Self + fn parse_node(node: &KdlNode) -> Option; +} + +/// Returns the first successful node that can be parsed into T, if there is one +pub fn extract_data(nodes: &[KdlNode]) -> Option +where + T: ParseKdlNode, +{ + for node in nodes { + if let Some(val) = T::parse_node(node) { + return Some(val); + } + } + None +} + +/// Use this macro to generate the code needed to parse a KDL node that is a single string, as the +/// code is quite repetitive for this simple task. +/// +/// As a bonus, the following code is also generated: +/// - AsRef +/// - new(value: String) -> Self +/// +/// NOTE: This only works with newtype wrappers around String! +/// +/// Example: +/// publisher "mitre" can be generated by this macro! +/// +/// ```rust +/// struct Publisher(pub String) +/// ``` +#[macro_export] +macro_rules! string_newtype_parse_kdl_node { + ($type:ty, $identifier:expr) => { + impl $type { + #[allow(dead_code)] + pub fn new(value: String) -> Self { + Self(value) + } + } + + impl ParseKdlNode for $type { + fn kdl_key() -> &'static str { + $identifier + } + + fn parse_node(node: &KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + // NOTE: this macro currently assumes that the first positional argument is the + // correct value to be parsing, which is true for newtype String wrappers! + let entry = node.entries().first()?.value().as_string()?.to_string(); + Some(Self(entry)) + } + } + + impl AsRef for $type { + fn as_ref(&self) -> &String { + &self.0 + } + } + }; +} diff --git a/plugins/churn/src/linguist/mod.rs b/plugins/churn/src/linguist/mod.rs index 82e718b1..277fc0ea 100644 --- a/plugins/churn/src/linguist/mod.rs +++ b/plugins/churn/src/linguist/mod.rs @@ -2,12 +2,13 @@ mod db; mod fs; +mod kdl_util; pub use db::{Linguist, LinguistSource}; -use crate::error::*; - -use fs::read_toml; +use anyhow::{Context as _, Result}; +use fs::read_kdl; +use kdl_util::ParseKdlNode; use serde::{de::Visitor, Deserialize, Deserializer}; use std::{convert::AsRef, fmt, fmt::Formatter, path::Path, result::Result as StdResult}; @@ -28,7 +29,7 @@ impl SourceFileDetector { pub fn load>(langs_file: P) -> Result { fn inner(langs_file: &Path) -> Result { // Load the file and parse it. - let language_file: LanguageFile = read_toml(langs_file) + let language_file: LanguageFile = read_kdl(langs_file) .context("failed to read language definitions from langs file")?; // Get the list of extensions from it. @@ -70,11 +71,23 @@ struct LanguageFile { languages: Vec, } -#[derive(Debug, Deserialize)] -struct LanguageExtensions { - #[serde(default = "missing_lang_type")] - r#type: LanguageType, - extensions: Option>, +impl ParseKdlNode for LanguageFile { + fn kdl_key() -> &'static str { + "languages" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let mut languages = Vec::new(); + for node in node.children()?.nodes() { + languages.push(LanguageExtensions::parse_node(node)?); + } + + Some(Self { languages }) + } } impl LanguageFile { @@ -84,8 +97,7 @@ impl LanguageFile { for language in self.languages { if matches!(language.r#type, LanguageType::Programming) { match language.extensions { - None => continue, - Some(mut extensions) => result.extend(extensions.drain(0..)), + mut extensions => result.extend(extensions.drain(0..)), } } } @@ -94,6 +106,54 @@ impl LanguageFile { } } +#[derive(Debug, Deserialize)] +struct LanguageExtensions { + #[serde(default = "missing_lang_type")] + r#type: LanguageType, + extensions: Vec, +} + +impl ParseKdlNode for LanguageExtensions { + fn kdl_key() -> &'static str { + "language" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let lanugage_type = node.get("type")?.value().as_string()?; + + let r#type = match { + match lanugage_type { + "data" => Some(LanguageType::Data), + "programming" => Some(LanguageType::Programming), + "markup" => Some(LanguageType::Markup), + "prose" => Some(LanguageType::Prose), + _ => None, + } + } { + Some(t) => t, + None => return None, + }; + + let mut extensions = Vec::new(); + for node in node.children()?.nodes() { + if node.name().to_string().as_str() == "extensions" { + for entry in node.entries() { + extensions.push(entry.value().as_string()?.to_string()); + } + } + } + + Some(Self { + r#type, + extensions: extensions, + }) + } +} + #[derive(Debug)] enum LanguageType { Data, diff --git a/plugins/entropy/Cargo.toml b/plugins/entropy/Cargo.toml index f941d6c3..716bda05 100644 --- a/plugins/entropy/Cargo.toml +++ b/plugins/entropy/Cargo.toml @@ -25,6 +25,7 @@ serde_json = "1.0.134" tokio = { version = "1.42.0", features = ["rt"] } toml = "0.8.19" unicode-normalization = "0.1.24" +kdl = "4.7.1" [dev-dependencies] hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ diff --git a/plugins/entropy/src/linguist/mod.rs b/plugins/entropy/src/linguist.rs similarity index 69% rename from plugins/entropy/src/linguist/mod.rs rename to plugins/entropy/src/linguist.rs index dd031d44..b698506a 100644 --- a/plugins/entropy/src/linguist/mod.rs +++ b/plugins/entropy/src/linguist.rs @@ -1,12 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 -mod db; -mod fs; - -pub use db::{Linguist, LinguistSource}; - +use crate::util::fs::read_kdl; +use crate::util::kdl::ParseKdlNode; use anyhow::{Context as _, Result}; -use fs::read_toml; use serde::{de::Visitor, Deserialize, Deserializer}; use std::{convert::AsRef, fmt, fmt::Formatter, path::Path, result::Result as StdResult}; @@ -27,7 +23,7 @@ impl SourceFileDetector { pub fn load>(langs_file: P) -> Result { fn inner(langs_file: &Path) -> Result { // Load the file and parse it. - let language_file: LanguageFile = read_toml(langs_file) + let language_file: LanguageFile = read_kdl(langs_file) .context("failed to read language definitions from langs file")?; // Get the list of extensions from it. @@ -69,11 +65,23 @@ struct LanguageFile { languages: Vec, } -#[derive(Debug, Deserialize)] -struct LanguageExtensions { - #[serde(default = "missing_lang_type")] - r#type: LanguageType, - extensions: Option>, +impl ParseKdlNode for LanguageFile { + fn kdl_key() -> &'static str { + "languages" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let mut languages = Vec::new(); + for node in node.children()?.nodes() { + languages.push(LanguageExtensions::parse_node(node)?); + } + + Some(Self { languages }) + } } impl LanguageFile { @@ -93,6 +101,54 @@ impl LanguageFile { } } +#[derive(Debug, Deserialize)] +struct LanguageExtensions { + #[serde(default = "missing_lang_type")] + r#type: LanguageType, + extensions: Option>, +} + +impl ParseKdlNode for LanguageExtensions { + fn kdl_key() -> &'static str { + "language" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let lanugage_type = node.get("type")?.value().as_string()?; + + let r#type = match { + match lanugage_type { + "data" => Some(LanguageType::Data), + "programming" => Some(LanguageType::Programming), + "markup" => Some(LanguageType::Markup), + "prose" => Some(LanguageType::Prose), + _ => None, + } + } { + Some(t) => t, + None => return None, + }; + + let mut extensions = Vec::new(); + for node in node.children()?.nodes() { + if node.name().to_string().as_str() == "extensions" { + for entry in node.entries() { + extensions.push(entry.value().as_string()?.to_string()); + } + } + } + + Some(Self { + r#type, + extensions: Some(extensions), + }) + } +} + #[derive(Debug)] enum LanguageType { Data, diff --git a/plugins/entropy/src/linguist/fs.rs b/plugins/entropy/src/linguist/fs.rs deleted file mode 100644 index ca9a2fb7..00000000 --- a/plugins/entropy/src/linguist/fs.rs +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::{Context as _, Result}; -use serde::de::DeserializeOwned; -use std::{fs, path::Path}; - -/// Read a file to a string. -pub fn read_string>(path: P) -> Result { - fn inner(path: &Path) -> Result { - fs::read_to_string(path) - .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) - } - - inner(path.as_ref()) -} - -/// Read file to a struct that can be deserialized from TOML format. -pub fn read_toml, T: DeserializeOwned>(path: P) -> Result { - let path = path.as_ref(); - let contents = read_string(path)?; - toml::de::from_str(&contents) - .with_context(|| format!("failed to read as TOML '{}'", path.display())) -} diff --git a/plugins/entropy/src/main.rs b/plugins/entropy/src/main.rs index 26d87722..d94baeb8 100644 --- a/plugins/entropy/src/main.rs +++ b/plugins/entropy/src/main.rs @@ -1,16 +1,18 @@ // SPDX-License-Identifier: Apache-2.0 mod error; -mod linguist; +mod util; mod metric; mod types; +mod linguist; -use crate::{linguist::*, metric::*, types::*}; +use crate::{util::db::*, metric::*, types::*}; use clap::Parser; use hipcheck_sdk::{prelude::*, types::Target}; use serde::Deserialize; use tokio::sync::Mutex; +use linguist::SourceFileDetector; use std::{ path::PathBuf, diff --git a/plugins/entropy/src/metric.rs b/plugins/entropy/src/metric.rs index 732276dd..bc5644ad 100644 --- a/plugins/entropy/src/metric.rs +++ b/plugins/entropy/src/metric.rs @@ -3,7 +3,7 @@ use crate::{ error::*, hc_error, - linguist::{Linguist, LinguistSource}, + util::db::{Linguist, LinguistSource}, types::*, }; use dashmap::DashMap; diff --git a/plugins/entropy/src/linguist/db.rs b/plugins/entropy/src/util/db.rs similarity index 100% rename from plugins/entropy/src/linguist/db.rs rename to plugins/entropy/src/util/db.rs diff --git a/plugins/entropy/src/util/fs.rs b/plugins/entropy/src/util/fs.rs new file mode 100644 index 00000000..71b53bf8 --- /dev/null +++ b/plugins/entropy/src/util/fs.rs @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::kdl::{extract_data, ParseKdlNode}; +use anyhow::{anyhow, Context as _, Result}; +use kdl::KdlDocument; +use std::{fs, path::Path, str::FromStr}; + +/// Read a file to a string. +pub fn read_string>(path: P) -> Result { + fn inner(path: &Path) -> Result { + fs::read_to_string(path) + .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) + } + + inner(path.as_ref()) +} + +/// Read file to a struct that can be deserialized from kdl format. +pub fn read_kdl, T: ParseKdlNode>(path: P) -> Result { + let path = path.as_ref(); + let contents = read_string(path)?; + let document = KdlDocument::from_str(&contents).map_err(|e| anyhow!(e))?; + let nodes = document.nodes(); + extract_data(nodes).ok_or(anyhow!("Could not parse langs KDL 'format'")) +} diff --git a/plugins/entropy/src/util/kdl.rs b/plugins/entropy/src/util/kdl.rs new file mode 100644 index 00000000..095c0d34 --- /dev/null +++ b/plugins/entropy/src/util/kdl.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! General shared types and functions for KDL files + +use kdl::KdlNode; + +// Helper trait to make it easier to parse KdlNodes into our own types +pub trait ParseKdlNode +where + Self: Sized, +{ + /// Return the name of the attribute used to identify the node pertaining to this struct + fn kdl_key() -> &'static str; + + /// Attempt to convert a `kdl::KdlNode` into Self + fn parse_node(node: &KdlNode) -> Option; +} + +/// Returns the first successful node that can be parsed into T, if there is one +pub fn extract_data(nodes: &[KdlNode]) -> Option +where + T: ParseKdlNode, +{ + for node in nodes { + if let Some(val) = T::parse_node(node) { + return Some(val); + } + } + None +} + +/// Use this macro to generate the code needed to parse a KDL node that is a single string, as the +/// code is quite repetitive for this simple task. +/// +/// As a bonus, the following code is also generated: +/// - AsRef +/// - new(value: String) -> Self +/// +/// NOTE: This only works with newtype wrappers around String! +/// +/// Example: +/// publisher "mitre" can be generated by this macro! +/// +/// ```rust +/// struct Publisher(pub String) +/// ``` +#[macro_export] +macro_rules! string_newtype_parse_kdl_node { + ($type:ty, $identifier:expr) => { + impl $type { + #[allow(dead_code)] + pub fn new(value: String) -> Self { + Self(value) + } + } + + impl ParseKdlNode for $type { + fn kdl_key() -> &'static str { + $identifier + } + + fn parse_node(node: &KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + // NOTE: this macro currently assumes that the first positional argument is the + // correct value to be parsing, which is true for newtype String wrappers! + let entry = node.entries().first()?.value().as_string()?.to_string(); + Some(Self(entry)) + } + } + + impl AsRef for $type { + fn as_ref(&self) -> &String { + &self.0 + } + } + }; +} diff --git a/plugins/entropy/src/util/mod.rs b/plugins/entropy/src/util/mod.rs new file mode 100644 index 00000000..f662d6cc --- /dev/null +++ b/plugins/entropy/src/util/mod.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + +pub mod db; +pub mod fs; +pub mod kdl; diff --git a/plugins/linguist/Cargo.toml b/plugins/linguist/Cargo.toml index d11f6b8f..afa4e9a0 100644 --- a/plugins/linguist/Cargo.toml +++ b/plugins/linguist/Cargo.toml @@ -18,6 +18,7 @@ serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.134" tokio = { version = "1.42.0", features = ["rt"] } toml = "0.8.19" +kdl = "4.7.1" [dev-dependencies] hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ diff --git a/plugins/linguist/src/fs.rs b/plugins/linguist/src/fs.rs deleted file mode 100644 index ca9a2fb7..00000000 --- a/plugins/linguist/src/fs.rs +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::{Context as _, Result}; -use serde::de::DeserializeOwned; -use std::{fs, path::Path}; - -/// Read a file to a string. -pub fn read_string>(path: P) -> Result { - fn inner(path: &Path) -> Result { - fs::read_to_string(path) - .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) - } - - inner(path.as_ref()) -} - -/// Read file to a struct that can be deserialized from TOML format. -pub fn read_toml, T: DeserializeOwned>(path: P) -> Result { - let path = path.as_ref(); - let contents = read_string(path)?; - toml::de::from_str(&contents) - .with_context(|| format!("failed to read as TOML '{}'", path.display())) -} diff --git a/plugins/linguist/src/linguist.rs b/plugins/linguist/src/linguist.rs index 5ffd9305..a5803276 100644 --- a/plugins/linguist/src/linguist.rs +++ b/plugins/linguist/src/linguist.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -use crate::fs::read_toml; +use crate::util::fs::read_kdl; +use crate::util::kdl::ParseKdlNode; use anyhow::{Context as _, Result}; use serde::{de::Visitor, Deserialize, Deserializer}; use std::{convert::AsRef, fmt, fmt::Formatter, path::Path, result::Result as StdResult}; @@ -22,9 +23,11 @@ impl SourceFileDetector { pub fn load>(langs_file: P) -> Result { fn inner(langs_file: &Path) -> Result { // Load the file and parse it. - let language_file: LanguageFile = read_toml(langs_file) + let language_file: LanguageFile = read_kdl(langs_file) .context("failed to read language definitions from langs file")?; + println!("{:?}", language_file); + // Get the list of extensions from it. let extensions = language_file.into_extensions(); @@ -64,6 +67,25 @@ struct LanguageFile { languages: Vec, } +impl ParseKdlNode for LanguageFile { + fn kdl_key() -> &'static str { + "languages" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let mut languages = Vec::new(); + for node in node.children()?.nodes() { + languages.push(LanguageExtensions::parse_node(node)?); + } + + Some(Self { languages }) + } +} + #[derive(Debug, Deserialize)] struct LanguageExtensions { #[serde(default = "missing_lang_type")] @@ -90,6 +112,47 @@ impl LanguageFile { } } +impl ParseKdlNode for LanguageExtensions { + fn kdl_key() -> &'static str { + "language" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let lanugage_type = node.get("type")?.value().as_string()?; + + let r#type = match { + match lanugage_type { + "data" => Some(LanguageType::Data), + "programming" => Some(LanguageType::Programming), + "markup" => Some(LanguageType::Markup), + "prose" => Some(LanguageType::Prose), + _ => None, + } + } { + Some(t) => t, + None => return None, + }; + + let mut extensions = Vec::new(); + for node in node.children()?.nodes() { + if node.name().to_string().as_str() == "extensions" { + for entry in node.entries() { + extensions.push(entry.value().as_string()?.to_string()); + } + } + } + + Some(Self { + r#type, + extensions: Some(extensions), + }) + } +} + #[derive(Debug)] enum LanguageType { Data, diff --git a/plugins/linguist/src/main.rs b/plugins/linguist/src/main.rs index d14af1a2..29592891 100644 --- a/plugins/linguist/src/main.rs +++ b/plugins/linguist/src/main.rs @@ -2,8 +2,8 @@ //! Plugin for determining if a particular path is a source file -mod fs; mod linguist; +mod util; use clap::Parser; use hipcheck_sdk::prelude::*; diff --git a/plugins/linguist/src/util/fs.rs b/plugins/linguist/src/util/fs.rs new file mode 100644 index 00000000..71b53bf8 --- /dev/null +++ b/plugins/linguist/src/util/fs.rs @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +use super::kdl::{extract_data, ParseKdlNode}; +use anyhow::{anyhow, Context as _, Result}; +use kdl::KdlDocument; +use std::{fs, path::Path, str::FromStr}; + +/// Read a file to a string. +pub fn read_string>(path: P) -> Result { + fn inner(path: &Path) -> Result { + fs::read_to_string(path) + .with_context(|| format!("failed to read as UTF-8 string '{}'", path.display())) + } + + inner(path.as_ref()) +} + +/// Read file to a struct that can be deserialized from kdl format. +pub fn read_kdl, T: ParseKdlNode>(path: P) -> Result { + let path = path.as_ref(); + let contents = read_string(path)?; + let document = KdlDocument::from_str(&contents).map_err(|e| anyhow!(e))?; + let nodes = document.nodes(); + extract_data(nodes).ok_or(anyhow!("Could not parse langs KDL 'format'")) +} diff --git a/plugins/linguist/src/util/kdl.rs b/plugins/linguist/src/util/kdl.rs new file mode 100644 index 00000000..095c0d34 --- /dev/null +++ b/plugins/linguist/src/util/kdl.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! General shared types and functions for KDL files + +use kdl::KdlNode; + +// Helper trait to make it easier to parse KdlNodes into our own types +pub trait ParseKdlNode +where + Self: Sized, +{ + /// Return the name of the attribute used to identify the node pertaining to this struct + fn kdl_key() -> &'static str; + + /// Attempt to convert a `kdl::KdlNode` into Self + fn parse_node(node: &KdlNode) -> Option; +} + +/// Returns the first successful node that can be parsed into T, if there is one +pub fn extract_data(nodes: &[KdlNode]) -> Option +where + T: ParseKdlNode, +{ + for node in nodes { + if let Some(val) = T::parse_node(node) { + return Some(val); + } + } + None +} + +/// Use this macro to generate the code needed to parse a KDL node that is a single string, as the +/// code is quite repetitive for this simple task. +/// +/// As a bonus, the following code is also generated: +/// - AsRef +/// - new(value: String) -> Self +/// +/// NOTE: This only works with newtype wrappers around String! +/// +/// Example: +/// publisher "mitre" can be generated by this macro! +/// +/// ```rust +/// struct Publisher(pub String) +/// ``` +#[macro_export] +macro_rules! string_newtype_parse_kdl_node { + ($type:ty, $identifier:expr) => { + impl $type { + #[allow(dead_code)] + pub fn new(value: String) -> Self { + Self(value) + } + } + + impl ParseKdlNode for $type { + fn kdl_key() -> &'static str { + $identifier + } + + fn parse_node(node: &KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + // NOTE: this macro currently assumes that the first positional argument is the + // correct value to be parsing, which is true for newtype String wrappers! + let entry = node.entries().first()?.value().as_string()?.to_string(); + Some(Self(entry)) + } + } + + impl AsRef for $type { + fn as_ref(&self) -> &String { + &self.0 + } + } + }; +} diff --git a/plugins/linguist/src/util/mod.rs b/plugins/linguist/src/util/mod.rs new file mode 100644 index 00000000..970e3a13 --- /dev/null +++ b/plugins/linguist/src/util/mod.rs @@ -0,0 +1,2 @@ +pub mod fs; +pub mod kdl; diff --git a/plugins/typo/Cargo.toml b/plugins/typo/Cargo.toml index 2c497670..83c3be87 100644 --- a/plugins/typo/Cargo.toml +++ b/plugins/typo/Cargo.toml @@ -12,6 +12,7 @@ clap = { version = "4.5.23", features = ["derive"] } hipcheck-sdk = { version = "0.3.0", path = "../../sdk/rust", features = [ "macros", ] } +kdl = "4.7.1" log = "0.4.22" maplit = "1.0.2" pathbuf = "1.0.0" diff --git a/plugins/typo/src/languages.rs b/plugins/typo/src/languages.rs index e409a14d..9b2825c9 100644 --- a/plugins/typo/src/languages.rs +++ b/plugins/typo/src/languages.rs @@ -3,30 +3,71 @@ use crate::{ types::{Homoglyphs, KeyboardLayout, NpmDependencies, Typo}, util::fs as file, + util::kdl::ParseKdlNode, }; use anyhow::{Context as _, Result}; -use serde::Deserialize; use std::{collections::HashMap, path::Path}; -#[derive(Debug, Deserialize)] +#[derive(Debug)] pub struct TypoFile { - languages: Languages, + languages: Vec, } -#[derive(Debug, Deserialize)] -struct Languages { - javascript: Vec, +impl ParseKdlNode for TypoFile { + fn kdl_key() -> &'static str { + "languages" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + + let mut languages = Vec::new(); + for node in node.children()?.nodes() { + languages.push(Language::parse_node(node)?); + } + Some(Self { languages }) + } } impl TypoFile { pub fn load_from(typo_path: &Path) -> Result { file::exists(typo_path).context("typo file does not exist")?; - let typo_file = file::read_toml(typo_path).context("failed to open typo file")?; + let typo_file = file::read_kdl(typo_path).context("failed to open typo file")?; Ok(typo_file) } } +#[derive(Debug)] +struct Language { + language: LanguageType, + packages: Vec, +} + +impl ParseKdlNode for Language { + fn kdl_key() -> &'static str { + "" + } + + fn parse_node(node: &kdl::KdlNode) -> Option { + let language = match node.name().to_string().as_str() { + "javascript" => LanguageType::Javascript, + _ => return None, + }; + let mut packages = Vec::new(); + for package in node.entries() { + packages.push(package.value().as_string()?.to_string()); + } + Some(Self { language, packages }) + } +} + +#[derive(Debug, PartialEq)] +enum LanguageType { + Javascript, +} #[derive(Debug, Clone)] pub struct NameFuzzer<'t> { // A map of strings which may be typos to the notes for what they may be @@ -83,8 +124,13 @@ pub(crate) fn typos_for_javascript( dependencies: NpmDependencies, ) -> Result> { let mut typos = Vec::new(); - - for legit_name in &typo_file.languages.javascript { + let mut javascript_packages = &Vec::new(); + for language in &typo_file.languages { + if LanguageType::Javascript == language.language { + javascript_packages = &language.packages; + } + } + for legit_name in javascript_packages { let fuzzer = NameFuzzer::new(legit_name); // Add a dependency name to the list of typos if the list of possible typos for that name is non-empty diff --git a/plugins/typo/src/util/fs.rs b/plugins/typo/src/util/fs.rs index bcbb2692..638ae936 100644 --- a/plugins/typo/src/util/fs.rs +++ b/plugins/typo/src/util/fs.rs @@ -1,8 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 +use super::kdl::{extract_data, ParseKdlNode}; use anyhow::{anyhow, Context as _, Result}; -use serde::de::DeserializeOwned; -use std::{fs, path::Path}; +use kdl::KdlDocument; +use std::{fs, path::Path, str::FromStr}; /// Read a file to a string. pub fn read_string>(path: P) -> Result { @@ -14,12 +15,13 @@ pub fn read_string>(path: P) -> Result { inner(path.as_ref()) } -/// Read file to a struct that can be deserialized from TOML format. -pub fn read_toml, T: DeserializeOwned>(path: P) -> Result { +/// Read file to a struct that can be deserialized from kdl format. +pub fn read_kdl, T: ParseKdlNode>(path: P) -> Result { let path = path.as_ref(); let contents = read_string(path)?; - toml::de::from_str(&contents) - .with_context(|| format!("failed to read as TOML '{}'", path.display())) + let document = KdlDocument::from_str(&contents).map_err(|e| anyhow!(e))?; + let nodes = document.nodes(); + extract_data(nodes).ok_or(anyhow!("Could not parse typo KDL 'format'")) } /// Check that a given path exists. diff --git a/plugins/typo/src/util/kdl.rs b/plugins/typo/src/util/kdl.rs new file mode 100644 index 00000000..095c0d34 --- /dev/null +++ b/plugins/typo/src/util/kdl.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! General shared types and functions for KDL files + +use kdl::KdlNode; + +// Helper trait to make it easier to parse KdlNodes into our own types +pub trait ParseKdlNode +where + Self: Sized, +{ + /// Return the name of the attribute used to identify the node pertaining to this struct + fn kdl_key() -> &'static str; + + /// Attempt to convert a `kdl::KdlNode` into Self + fn parse_node(node: &KdlNode) -> Option; +} + +/// Returns the first successful node that can be parsed into T, if there is one +pub fn extract_data(nodes: &[KdlNode]) -> Option +where + T: ParseKdlNode, +{ + for node in nodes { + if let Some(val) = T::parse_node(node) { + return Some(val); + } + } + None +} + +/// Use this macro to generate the code needed to parse a KDL node that is a single string, as the +/// code is quite repetitive for this simple task. +/// +/// As a bonus, the following code is also generated: +/// - AsRef +/// - new(value: String) -> Self +/// +/// NOTE: This only works with newtype wrappers around String! +/// +/// Example: +/// publisher "mitre" can be generated by this macro! +/// +/// ```rust +/// struct Publisher(pub String) +/// ``` +#[macro_export] +macro_rules! string_newtype_parse_kdl_node { + ($type:ty, $identifier:expr) => { + impl $type { + #[allow(dead_code)] + pub fn new(value: String) -> Self { + Self(value) + } + } + + impl ParseKdlNode for $type { + fn kdl_key() -> &'static str { + $identifier + } + + fn parse_node(node: &KdlNode) -> Option { + if node.name().to_string().as_str() != Self::kdl_key() { + return None; + } + // NOTE: this macro currently assumes that the first positional argument is the + // correct value to be parsing, which is true for newtype String wrappers! + let entry = node.entries().first()?.value().as_string()?.to_string(); + Some(Self(entry)) + } + } + + impl AsRef for $type { + fn as_ref(&self) -> &String { + &self.0 + } + } + }; +} diff --git a/plugins/typo/src/util/mod.rs b/plugins/typo/src/util/mod.rs index a2bb7363..e7db251a 100644 --- a/plugins/typo/src/util/mod.rs +++ b/plugins/typo/src/util/mod.rs @@ -1,3 +1,4 @@ // SPDX-License-Identifier: Apache-2.0 pub mod fs; +pub mod kdl;