Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/syntax.rs')
-rw-r--r--helix-core/src/syntax.rs418
1 files changed, 3 insertions, 415 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 255c9a63..73ea7ea8 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -84,421 +84,8 @@ pub struct Configuration {
impl Default for Configuration {
fn default() -> Self {
- crate::config::default_syntax_loader()
- }
-}
-
-// largely based on tree-sitter/cli/src/loader.rs
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case", deny_unknown_fields)]
-pub struct LanguageConfiguration {
- #[serde(rename = "name")]
- pub language_id: String, // c-sharp, rust, tsx
- #[serde(rename = "language-id")]
- // see the table under https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem
- pub language_server_language_id: Option<String>, // csharp, rust, typescriptreact, for the language-server
- pub file_types: Vec<FileType>, // filename extension or ends_with? <Gemfile, rb, etc>
- #[serde(default)]
- pub shebangs: Vec<String>, // interpreter(s) associated with language
- #[serde(default)]
- pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
- pub comment_token: Option<String>,
- pub text_width: Option<usize>,
- pub soft_wrap: Option<SoftWrap>,
-
- #[serde(default)]
- pub auto_format: bool,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub formatter: Option<FormatterConfiguration>,
-
- #[serde(default)]
- pub diagnostic_severity: Severity,
-
- pub grammar: Option<String>, // tree-sitter grammar name, defaults to language_id
-
- // content_regex
- #[serde(default, skip_serializing, deserialize_with = "deserialize_regex")]
- pub injection_regex: Option<Regex>,
- // first_line_regex
- //
- #[serde(skip)]
- pub(crate) highlight_config: OnceCell<Option<Arc<HighlightConfiguration>>>,
- // tags_config OnceCell<> https://github.com/tree-sitter/tree-sitter/pull/583
- #[serde(
- default,
- skip_serializing_if = "Vec::is_empty",
- serialize_with = "serialize_lang_features",
- deserialize_with = "deserialize_lang_features"
- )]
- pub language_servers: Vec<LanguageServerFeatures>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub indent: Option<IndentationConfiguration>,
-
- #[serde(skip)]
- pub(crate) indent_query: OnceCell<Option<Query>>,
- #[serde(skip)]
- pub(crate) textobject_query: OnceCell<Option<TextObjectQuery>>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub debugger: Option<DebugAdapterConfig>,
-
- /// Automatic insertion of pairs to parentheses, brackets,
- /// etc. Defaults to true. Optionally, this can be a list of 2-tuples
- /// to specify a list of characters to pair. This overrides the
- /// global setting.
- #[serde(default, skip_serializing, deserialize_with = "deserialize_auto_pairs")]
- pub auto_pairs: Option<AutoPairs>,
-
- pub rulers: Option<Vec<u16>>, // if set, override editor's rulers
-
- /// Hardcoded LSP root directories relative to the workspace root, like `examples` or `tools/fuzz`.
- /// Falling back to the current working directory if none are configured.
- pub workspace_lsp_roots: Option<Vec<PathBuf>>,
- #[serde(default)]
- pub persistent_diagnostic_sources: Vec<String>,
-}
-
-#[derive(Debug, PartialEq, Eq, Hash)]
-pub enum FileType {
- /// The extension of the file, either the `Path::extension` or the full
- /// filename if the file does not have an extension.
- Extension(String),
- /// The suffix of a file. This is compared to a given file's absolute
- /// path, so it can be used to detect files based on their directories.
- Suffix(String),
-}
-
-impl Serialize for FileType {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- use serde::ser::SerializeMap;
-
- match self {
- FileType::Extension(extension) => serializer.serialize_str(extension),
- FileType::Suffix(suffix) => {
- let mut map = serializer.serialize_map(Some(1))?;
- map.serialize_entry("suffix", &suffix.replace(std::path::MAIN_SEPARATOR, "/"))?;
- map.end()
- }
- }
- }
-}
-
-impl<'de> Deserialize<'de> for FileType {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::de::Deserializer<'de>,
- {
- struct FileTypeVisitor;
-
- impl<'de> serde::de::Visitor<'de> for FileTypeVisitor {
- type Value = FileType;
-
- fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
- formatter.write_str("string or table")
- }
-
- fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
- where
- E: serde::de::Error,
- {
- Ok(FileType::Extension(value.to_string()))
- }
-
- fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
- where
- M: serde::de::MapAccess<'de>,
- {
- match map.next_entry::<String, String>()? {
- Some((key, suffix)) if key == "suffix" => Ok(FileType::Suffix({
- suffix.replace('/', std::path::MAIN_SEPARATOR_STR)
- })),
- Some((key, _value)) => Err(serde::de::Error::custom(format!(
- "unknown key in `file-types` list: {}",
- key
- ))),
- None => Err(serde::de::Error::custom(
- "expected a `suffix` key in the `file-types` entry",
- )),
- }
- }
- }
-
- deserializer.deserialize_any(FileTypeVisitor)
- }
-}
-
-#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
-#[serde(rename_all = "kebab-case")]
-pub enum LanguageServerFeature {
- Format,
- GotoDeclaration,
- GotoDefinition,
- GotoTypeDefinition,
- GotoReference,
- GotoImplementation,
- // Goto, use bitflags, combining previous Goto members?
- SignatureHelp,
- Hover,
- DocumentHighlight,
- Completion,
- CodeAction,
- WorkspaceCommand,
- DocumentSymbols,
- WorkspaceSymbols,
- // Symbols, use bitflags, see above?
- Diagnostics,
- RenameSymbol,
- InlayHints,
-}
-
-impl Display for LanguageServerFeature {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use LanguageServerFeature::*;
- let feature = match self {
- Format => "format",
- GotoDeclaration => "goto-declaration",
- GotoDefinition => "goto-definition",
- GotoTypeDefinition => "goto-type-definition",
- GotoReference => "goto-type-definition",
- GotoImplementation => "goto-implementation",
- SignatureHelp => "signature-help",
- Hover => "hover",
- DocumentHighlight => "document-highlight",
- Completion => "completion",
- CodeAction => "code-action",
- WorkspaceCommand => "workspace-command",
- DocumentSymbols => "document-symbols",
- WorkspaceSymbols => "workspace-symbols",
- Diagnostics => "diagnostics",
- RenameSymbol => "rename-symbol",
- InlayHints => "inlay-hints",
- };
- write!(f, "{feature}",)
- }
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(untagged, rename_all = "kebab-case", deny_unknown_fields)]
-enum LanguageServerFeatureConfiguration {
- #[serde(rename_all = "kebab-case")]
- Features {
- #[serde(default, skip_serializing_if = "HashSet::is_empty")]
- only_features: HashSet<LanguageServerFeature>,
- #[serde(default, skip_serializing_if = "HashSet::is_empty")]
- except_features: HashSet<LanguageServerFeature>,
- name: String,
- },
- Simple(String),
-}
-
-#[derive(Debug, Default)]
-pub struct LanguageServerFeatures {
- pub name: String,
- pub only: HashSet<LanguageServerFeature>,
- pub excluded: HashSet<LanguageServerFeature>,
-}
-
-impl LanguageServerFeatures {
- pub fn has_feature(&self, feature: LanguageServerFeature) -> bool {
- (self.only.is_empty() || self.only.contains(&feature)) && !self.excluded.contains(&feature)
- }
-}
-
-fn deserialize_lang_features<'de, D>(
- deserializer: D,
-) -> Result<Vec<LanguageServerFeatures>, D::Error>
-where
- D: serde::Deserializer<'de>,
-{
- let raw: Vec<LanguageServerFeatureConfiguration> = Deserialize::deserialize(deserializer)?;
- let res = raw
- .into_iter()
- .map(|config| match config {
- LanguageServerFeatureConfiguration::Simple(name) => LanguageServerFeatures {
- name,
- ..Default::default()
- },
- LanguageServerFeatureConfiguration::Features {
- only_features,
- except_features,
- name,
- } => LanguageServerFeatures {
- name,
- only: only_features,
- excluded: except_features,
- },
- })
- .collect();
- Ok(res)
-}
-fn serialize_lang_features<S>(
- map: &Vec<LanguageServerFeatures>,
- serializer: S,
-) -> Result<S::Ok, S::Error>
-where
- S: serde::Serializer,
-{
- let mut serializer = serializer.serialize_seq(Some(map.len()))?;
- for features in map {
- let features = if features.only.is_empty() && features.excluded.is_empty() {
- LanguageServerFeatureConfiguration::Simple(features.name.to_owned())
- } else {
- LanguageServerFeatureConfiguration::Features {
- only_features: features.only.clone(),
- except_features: features.excluded.clone(),
- name: features.name.to_owned(),
- }
- };
- serializer.serialize_element(&features)?;
- }
- serializer.end()
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct LanguageServerConfiguration {
- pub command: String,
- #[serde(default)]
- #[serde(skip_serializing_if = "Vec::is_empty")]
- pub args: Vec<String>,
- #[serde(default, skip_serializing_if = "HashMap::is_empty")]
- pub environment: HashMap<String, String>,
- #[serde(default, skip_serializing, deserialize_with = "deserialize_lsp_config")]
- pub config: Option<serde_json::Value>,
- #[serde(default = "default_timeout")]
- pub timeout: u64,
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct FormatterConfiguration {
- pub command: String,
- #[serde(default)]
- #[serde(skip_serializing_if = "Vec::is_empty")]
- pub args: Vec<String>,
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct AdvancedCompletion {
- pub name: Option<String>,
- pub completion: Option<String>,
- pub default: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case", untagged)]
-pub enum DebugConfigCompletion {
- Named(String),
- Advanced(AdvancedCompletion),
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum DebugArgumentValue {
- String(String),
- Array(Vec<String>),
- Boolean(bool),
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct DebugTemplate {
- pub name: String,
- pub request: String,
- pub completion: Vec<DebugConfigCompletion>,
- pub args: HashMap<String, DebugArgumentValue>,
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct DebugAdapterConfig {
- pub name: String,
- pub transport: String,
- #[serde(default)]
- pub command: String,
- #[serde(default)]
- pub args: Vec<String>,
- pub port_arg: Option<String>,
- pub templates: Vec<DebugTemplate>,
- #[serde(default)]
- pub quirks: DebuggerQuirks,
-}
-
-// Different workarounds for adapters' differences
-#[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)]
-pub struct DebuggerQuirks {
- #[serde(default)]
- pub absolute_paths: bool,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-pub struct IndentationConfiguration {
- #[serde(deserialize_with = "deserialize_tab_width")]
- pub tab_width: usize,
- pub unit: String,
-}
-
-/// How the indentation for a newly inserted line should be determined.
-/// If the selected heuristic is not available (e.g. because the current
-/// language has no tree-sitter indent queries), a simpler one will be used.
-#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-pub enum IndentationHeuristic {
- /// Just copy the indentation of the line that the cursor is currently on.
- Simple,
- /// Use tree-sitter indent queries to compute the expected absolute indentation level of the new line.
- TreeSitter,
- /// Use tree-sitter indent queries to compute the expected difference in indentation between the new line
- /// and the line before. Add this to the actual indentation level of the line before.
- #[default]
- Hybrid,
-}
-
-/// Configuration for auto pairs
-#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case", deny_unknown_fields, untagged)]
-pub enum AutoPairConfig {
- /// Enables or disables auto pairing. False means disabled. True means to use the default pairs.
- Enable(bool),
-
- /// The mappings of pairs.
- Pairs(HashMap<char, char>),
-}
-
-impl Default for AutoPairConfig {
- fn default() -> Self {
- AutoPairConfig::Enable(true)
- }
-}
-
-impl From<&AutoPairConfig> for Option<AutoPairs> {
- fn from(auto_pair_config: &AutoPairConfig) -> Self {
- match auto_pair_config {
- AutoPairConfig::Enable(false) => None,
- AutoPairConfig::Enable(true) => Some(AutoPairs::default()),
- AutoPairConfig::Pairs(pairs) => Some(AutoPairs::new(pairs.iter())),
- }
- }
-}
-
-impl From<AutoPairConfig> for Option<AutoPairs> {
- fn from(auto_pairs_config: AutoPairConfig) -> Self {
- (&auto_pairs_config).into()
- }
-}
-
-impl FromStr for AutoPairConfig {
- type Err = std::str::ParseBoolError;
-
- // only do bool parsing for runtime setting
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- let enable: bool = s.parse()?;
- Ok(AutoPairConfig::Enable(enable))
+ todo!()
+ // crate::config::default_syntax_loader()
}
}
@@ -717,6 +304,7 @@ impl LanguageConfiguration {
.ok()
}
}
+
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct SoftWrap {