Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
use std::path::{Path, PathBuf};

use crate::path;
use helix_core::syntax::Configuration as LangConfig;
use helix_term::health::TsFeature;

/// Get the list of languages that support a particular tree-sitter
/// based feature.
pub fn ts_lang_support(feat: TsFeature) -> Vec<String> {
    let queries_dir = path::ts_queries();

    find_files(&queries_dir, feat.runtime_filename())
        .iter()
        .map(|f| {
            // .../helix/runtime/queries/python/highlights.scm
            let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm
            let lang = tail.components().next().unwrap(); // python
            lang.as_os_str().to_string_lossy().to_string()
        })
        .collect()
}

// naive implementation, but suffices for our needs
pub fn find_files(dir: &Path, filename: &str) -> Vec<PathBuf> {
    std::fs::read_dir(dir)
        .unwrap()
        .filter_map(|entry| {
            let path = entry.ok()?.path();
            if path.is_dir() {
                Some(find_files(&path, filename))
            } else if path.file_name()?.to_string_lossy() == filename {
                Some(vec![path])
            } else {
                None
            }
        })
        .flatten()
        .collect()
}

pub fn lang_config() -> LangConfig {
    let bytes = std::fs::read(path::lang_config()).unwrap();
    toml::from_slice(&bytes).unwrap()
}
n129' href='#n129'>129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
;;; Highlighting for lua

;;; Builtins
(self) @variable.builtin

;; Keywords

(if_statement
[
  "if"
  "then"
  "end"
] @keyword.control.conditional)

[
  "else"
  "elseif"
  "then"
] @keyword.control.conditional

(for_statement
[
  "for"
  "do"
  "end"
] @keyword.control.repeat)

(for_in_statement
[
  "for"
  "do"
  "end"
] @keyword.control.repeat)

(while_statement
[
  "while"
  "do"
  "end"
] @keyword.control.repeat)

(repeat_statement
[
  "repeat"
  "until"
] @keyword.control.repeat)

(do_statement
[
  "do"
  "end"
] @keyword)

[
 "in"
 "local"
 (break_statement)
 "goto"
 "return"
] @keyword

;; Operators

[
 "not"
 "and"
 "or"
] @operator

[
"="
"~="
"=="
"<="
">="
"<"
">"
"+"
"-"
"%"
"/"
"//"
"*"
"^"
"&"
"~"
"|"
">>"
"<<"
".."
"#"
 ] @operator

;; Punctuation
["," "." ":" ";"] @punctuation.delimiter

;; Brackets
[
 "("
 ")"
 "["
 "]"
 "{"
 "}"
] @punctuation.bracket

; ;; Constants
[
(false)
(true)
] @constant.builtin.boolean
(nil) @constant.builtin
(spread) @constant ;; "..."
((identifier) @constant
 (#match? @constant "^[A-Z][A-Z_0-9]*$"))

;; Parameters
(parameters
  (identifier) @variable.parameter)

; ;; Functions
(function [(function_name) (identifier)] @function)
(function ["function" "end"] @keyword.function)

(function
  (function_name
   (function_name_field
    (property_identifier) @function .)))

(local_function (identifier) @function)
(local_function ["function" "end"] @keyword.function)

(variable_declaration
 (variable_declarator (identifier) @function) (function_definition))
(local_variable_declaration
 (variable_declarator (identifier) @function) (function_definition))

(function_definition ["function" "end"] @keyword.function)

(function_call
  [
   ((identifier) @variable (method) @function.method)
   ((_) (method) @function.method)
   (identifier) @function
   (field_expression (property_identifier) @function)
  ]
  . (arguments))

;; Nodes
(table ["{" "}"] @constructor)
(comment) @comment
(string) @string
(number) @constant.numeric.integer
(label_statement) @label
; A bit of a tricky one, this will only match field names
(field . (identifier) @variable.other.member (_))
(shebang) @comment

;; Property
(property_identifier) @variable.other.member

;; Variable
(identifier) @variable

;; Error
(ERROR) @error