Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a guide for adding new languages to Topiary #630

Open
ErinvanderVeen opened this issue Sep 19, 2023 Discussed in #620 · 1 comment
Open

Create a guide for adding new languages to Topiary #630

ErinvanderVeen opened this issue Sep 19, 2023 Discussed in #620 · 1 comment
Assignees
Labels
epic: contributability Relates to how easy it is for external contributors to contribute to Topiary (engine and queries) type: documentation

Comments

@ErinvanderVeen
Copy link
Member

Discussed in #620

Originally posted by aca September 8, 2023
Hi, thanks for the great project.
If I understand the project correctly, this project would be helpful to build formatter (for the language that really small people are using)
Hope there is some beginner guide to add the language.

Obviously, a lot will change with the coming changes to loading grammar and separation of concerns. Regardless, I think it is better to create a guide now and continuously update it rather than waiting for too long.

@ErinvanderVeen ErinvanderVeen self-assigned this Sep 19, 2023
@ErinvanderVeen ErinvanderVeen added the epic: contributability Relates to how easy it is for external contributors to contribute to Topiary (engine and queries) label Sep 28, 2023
@josharian
Copy link

While proper docs are in progress, in case it helps anyone, here's the minimal diff I used to add a new language (as of 8cc9aa4):

commit 2ef08665d5da9bbb79c362309323756ce62ab469
Author: Josh Bleecher Snyder <josharian@gmail.com>
Date:   Wed Dec 20 13:41:45 2023 -0800

    scaffolding

diff --git a/Cargo.toml b/Cargo.toml
index bb7e0ab..52452a7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -61,6 +61,7 @@ tokio-test = "0.4"
 toml = "0.7"
 tree-sitter-bash = { git = "https://github.com/tree-sitter/tree-sitter-bash" }
 tree-sitter-facade = { git = "https://github.com/tweag/tree-sitter-facade" }
+tree-sitter-go-template = { git = "https://github.com/josharian/tree-sitter-go-template", rev = "7dc31f43beb18709d30c60de28f04e4424067214" }
 tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json.git" }
 tree-sitter-nickel = { git = "https://github.com/nickel-lang/tree-sitter-nickel", rev = "b1a4718601ebd29a62bf3a7fd1069a99ccf48093" }
 tree-sitter-ocaml = { git = "https://github.com/tree-sitter/tree-sitter-ocaml.git" }
diff --git a/topiary-cli/Cargo.toml b/topiary-cli/Cargo.toml
index 85a5d37..c307015 100644
--- a/topiary-cli/Cargo.toml
+++ b/topiary-cli/Cargo.toml
@@ -44,6 +44,7 @@ topiary-queries = { path = "../topiary-queries" }
 tree-sitter-facade = { workspace = true }
 
 tree-sitter-json = { workspace = true }
+tree-sitter-go-template = { workspace = true }
 tree-sitter-rust = { workspace = true }
 tree-sitter-toml = { workspace = true }
 tree-sitter-bash = { workspace = true }
diff --git a/topiary-cli/src/io.rs b/topiary-cli/src/io.rs
index e204d08..ebc9117 100644
--- a/topiary-cli/src/io.rs
+++ b/topiary-cli/src/io.rs
@@ -320,6 +320,7 @@ impl<'cfg> TryFrom<&InputFile<'cfg>> for OutputFile {
 fn to_query(language: &Language) -> CLIResult<QuerySource> {
     match language.name.as_str() {
         "bash" => Ok(topiary_queries::bash().into()),
+        "gohtml" => Ok(topiary_queries::gohtml().into()),
         "json" => Ok(topiary_queries::json().into()),
         "nickel" => Ok(topiary_queries::nickel().into()),
         "ocaml" => Ok(topiary_queries::ocaml().into()),
diff --git a/topiary-queries/Cargo.toml b/topiary-queries/Cargo.toml
index 45712a3..a9493c3 100644
--- a/topiary-queries/Cargo.toml
+++ b/topiary-queries/Cargo.toml
@@ -15,6 +15,7 @@ license.workspace = true
 [features]
 default = [
   "bash",
+  "gohtml",
   "json",
   "nickel",
   "ocaml",
@@ -25,6 +26,7 @@ default = [
   "tree_sitter_query",
 ]
 bash = []
+gohtml = []
 json = []
 nickel = []
 ocaml = []
diff --git a/topiary-queries/queries/gohtml.scm b/topiary-queries/queries/gohtml.scm
new file mode 100644
index 0000000..633eb3f
--- /dev/null
+++ b/topiary-queries/queries/gohtml.scm
@@ -0,0 +1,7 @@
+;; Sometimes we want to indicate that certain parts of our source text should
+;; not be formatted, but taken as is. We use the leaf capture name to inform the
+;; tool of this.
+[
+  (text)
+  (interpreted_string_literal)
+] @leaf
diff --git a/topiary-queries/src/lib.rs b/topiary-queries/src/lib.rs
index a909a51..0e3b873 100644
--- a/topiary-queries/src/lib.rs
+++ b/topiary-queries/src/lib.rs
@@ -4,6 +4,12 @@ pub fn bash() -> &'static str {
     include_str!("../queries/bash.scm")
 }
 
+/// Returns the Topiary-compatible query file for Bash.
+#[cfg(feature = "gohtml")]
+pub fn gohtml() -> &'static str {
+    include_str!("../queries/gohtml.scm")
+}
+
 /// Returns the Topiary-compatible query file for Json.
 #[cfg(feature = "json")]
 pub fn json() -> &'static str {
diff --git a/topiary/Cargo.toml b/topiary/Cargo.toml
index ba7e93b..9010486 100644
--- a/topiary/Cargo.toml
+++ b/topiary/Cargo.toml
@@ -30,6 +30,7 @@ unescape = { workspace = true }
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
 tokio = { workspace = true }
 tree-sitter-json = { workspace = true }
+tree-sitter-go-template = { workspace = true }
 tree-sitter-rust = { workspace = true }
 tree-sitter-toml = { workspace = true }
 tree-sitter-bash = { workspace = true }
diff --git a/topiary/languages.toml b/topiary/languages.toml
index f8ba027..7ba1696 100644
--- a/topiary/languages.toml
+++ b/topiary/languages.toml
@@ -35,3 +35,6 @@ extensions = ["toml"]
 name = "tree_sitter_query"
 extensions = ["scm"]
 
+[[language]]
+name = "gohtml"
+extensions = ["gohtml"]
diff --git a/topiary/src/language.rs b/topiary/src/language.rs
index 5f8adca..964b3b2 100644
--- a/topiary/src/language.rs
+++ b/topiary/src/language.rs
@@ -65,6 +65,7 @@ impl Language {
     pub async fn grammar(&self) -> FormatterResult<tree_sitter_facade::Language> {
         Ok(match self.name.as_str() {
             "bash" => tree_sitter_bash::language(),
+            "gohtml" => tree_sitter_go_template::language(),
             "json" => tree_sitter_json::language(),
             "nickel" => tree_sitter_nickel::language(),
             "ocaml" => tree_sitter_ocaml::language_ocaml(),
@@ -82,6 +83,7 @@ impl Language {
     pub async fn grammar_wasm(&self) -> FormatterResult<tree_sitter_facade::Language> {
         let language_name = match self.name.as_str() {
             "bash" => "bash",
+            "gohtml" => "gotmpl",
             "json" => "json",
             "nickel" => "nickel",
             "ocaml" => "ocaml",
@@ -129,6 +131,7 @@ impl TryFrom<&Language> for PathBuf {
     fn try_from(language: &Language) -> FormatterResult<Self> {
         let basename = Self::from(match language.name.as_str() {
             "bash" => "bash",
+            "gohtml" => "gohtml",
             "json" => "json",
             "nickel" => "nickel",
             "ocaml" | "ocaml_interface" => "ocaml",

The formatting is terrible, but the scaffolding is all there, and functional.

See #663 for how to invoke topiary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
epic: contributability Relates to how easy it is for external contributors to contribute to Topiary (engine and queries) type: documentation
Projects
None yet
Development

No branches or pull requests

2 participants