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

Adding support for gleam programming language #2280

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions data/playground/gleam/gleam.gleam
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also plan to tidy up this file -- right now I've just put some random stuff in for testing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, tho fwiw the standard for these playground files is quite low; they're mainly just a nice-to-have. Tbh the only thing that jumps out at me here is lack of final trailing newline

Copy link
Member

@pokey pokey Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nvm re trailing newline; looks like our pre-commit bot just took care of that one for you 🤖😊

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const another_variable: SchoolPerson = 5

const b = "allow_world"

type SchoolPerson {
Teacher(name: String, subject: String)
Student(String)
}

fn main(hello: String, bre, a) {
io.debug("hello", bre, a)
let a = 3
}

pub fn main(a, bre) {
io.debug("hello")
let a = 3
case a, b {
3, "a" -> "a"
_, _ -> "a"
}
let bar = fn(a, b) { 3 }
fn hello() -> Nil {
todo
}
let result = hello()
}

fn foo() {
use foo <- 3
}

type Food = Int
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { javascriptScopeSupport } from "./javascript";
import { jsonScopeSupport } from "./json";
import { pythonScopeSupport } from "./python";
import { luaScopeSupport } from "./lua";
import { gleamScopeSupport } from "./gleam";
import { LanguageScopeSupportFacetMap } from "./scopeSupportFacets.types";
import { talonScopeSupport } from "./talon";
import { typescriptScopeSupport } from "./typescript";
Expand All @@ -28,6 +29,8 @@ export function getLanguageScopeSupport(
return typescriptScopeSupport;
case "lua":
return luaScopeSupport;
case "gleam":
return gleamScopeSupport;
}
throw Error(`Unsupported language: '${languageId}'`);
}
34 changes: 34 additions & 0 deletions packages/common/src/scopeSupportFacets/gleam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* eslint-disable @typescript-eslint/naming-convention */

import {
LanguageScopeSupportFacetMap,
ScopeSupportFacetLevel,
} from "./scopeSupportFacets.types";

const { supported } = ScopeSupportFacetLevel;

export const gleamScopeSupport: LanguageScopeSupportFacetMap = {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through the list of all of these scopes support facets and chose all the ones that I think apply to gleam. Not all of them are implemented in the queries or in the tests yet though

"name.variable": supported,
"value.variable": supported,
functionCallee: supported,
functionCall: supported,
anonymousFunction: supported,
"type.alias": supported,
"type.formalParameter": supported,
"type.variable": supported,
"type.return": supported,
"branch.switchCase": supported,
statement: supported,
"statement.iteration.document": supported,
namedFunction: supported,
list: supported,
functionName: supported,
"argument.actual": supported,
"argument.actual.iteration": supported,
"argument.formal": supported,
"argument.formal.iteration": supported,
"comment.line": supported,
"string.singleLine": supported,
"condition.switchCase": supported,
"name.function": supported,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn(a,b) { c }

---

[Content] =
[Removal] =
[Domain] = 0:0-0:13
>-------------<
0| fn(a,b) { c }

[Interior] = 0:10-0:11
>-<
0| fn(a,b) { c }

[Insertion delimiter] = "\n"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
aaa(bbb)

---

[Content] =
[Removal] =
[Domain] = 0:0-0:8
>--------<
0| aaa(bbb)

[Insertion delimiter] = " "
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
aaa(bbb)

---

[Content] =
[Removal] = 0:0-0:3
>---<
0| aaa(bbb)

[Domain] = 0:0-0:8
>--------<
0| aaa(bbb)

[Insertion delimiter] = " "
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
let a = 1
---

[Content] = 0:4-0:5
>-<
0| let a = 1

[Removal] = 0:4-0:6
>--<
Comment on lines +8 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually prefer

Suggested change
[Removal] = 0:4-0:6
>--<
[Removal] = 0:0-0:9
>--------<

0| let a = 1

[Leading delimiter] = 0:3-0:4
>-<
0| let a = 1

[Trailing delimiter] = 0:5-0:6
>-<
0| let a = 1

[Domain] = 0:0-0:9
>---------<
0| let a = 1

[Insertion delimiter] = " "
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
type Aaa = Int

---

[#1 Content] =
[#1 Removal] =
[#1 Domain] = 0:0-0:14
>--------------<
0| type Aaa = Int

[#1 Insertion delimiter] = " "


[#2 Content] =
[#2 Domain] = 0:11-0:14
>---<
0| type Aaa = Int
Comment on lines +14 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I don't think this is usually supported in Cursorless, but I could go either way on it? cc/ @AndreasArvidsson


[#2 Removal] = 0:10-0:14
>----<
0| type Aaa = Int

[#2 Leading delimiter] = 0:10-0:11
>-<
0| type Aaa = Int

[#2 Insertion delimiter] = " "
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
let a = 3

---

[Content] = 0:8-0:9
>-<
0| let a = 3

[Removal] = 0:7-0:9
>--<
0| let a = 3
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this removal range include the equals?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes that's what we usually do, esp if declaring a variable without assigning a value is supported in the language


[Leading delimiter] = 0:7-0:8
>-<
0| let a = 3

[Domain] = 0:0-0:9
>---------<
0| let a = 3

[Insertion delimiter] = " "
136 changes: 136 additions & 0 deletions queries/gleam.scm
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to add comments for each of these queries to explain what they're doing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great; I'll wait to review this file in too much detail until there are more tests / comments, as that makes it easier for me to see what's going on. Lmk if there's anything in particular here that you want some feedback on in the meantime though!

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
;; Statements
[
(let)
(constant)
(function)
(type_definition)
(function_call)
(case)
(todo)
] @statement

(constant
value: (_) @value
) @_.domain

(constant
name: (_) @name @type.leading.endOf
type: (_) @type
) @_.domain

(let
value: (_) @value
) @_.domain

(let
pattern: (_) @name
) @_.domain

(list) @list
(list_pattern) @list

(data_constructor
name: (_) @name
arguments: (data_constructor_arguments
[
;; if there is a key
(data_constructor_argument
label: (_) @argumentOrParameter @value.leading.endOf
value: (_) @value @argumentOrParameter.trailing.startOf
) @argumentOrParameter.domain

;; if there's no key
(data_constructor_argument
value: (_) @argumentOrParameter
)
]
) @type.iteration
) @type

(type_definition
(type_name) @name
) @type
(type) @type

(type_alias
(type_name) @name
(type) @value
) @type

(function
name: (_) @functionName @name
body: (function_body) @namedFunction.interior
) @namedFunction @functionName.domain

(anonymous_function
body: (_) @anonymousFunction.interior
) @anonymousFunction

(
(function_parameters
(_)? @argumentOrParameter.leading.endOf
.
(function_parameter) @argumentOrParameter
.
(_)? @argumentOrParameter.trailing.startOf
) @argumentOrParameter.iteration @_dummy
(#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n")
)

(function_parameter
name: (_) @type.leading.endOf @name
type: (_) @type
) @name.domain

(
(function_call
function: (_) @functionCallee
arguments: (arguments)
) @functionCall @functionCallee.domain
)

(
(arguments
(_)? @_.leading.endOf
.
(argument) @argumentOrParameter
.
(_)? @_.trailing.startOf
) @argumentOrParameter.iteration @_dummy
(#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n")
)

(case_clause
value: (_) @branch.interior
) @branch

(case_clause
patterns: (case_clause_patterns
(case_clause_pattern
(_) @condition
)
)
) @condition.domain

(
(case_clause
(case_clause_patterns
(_)? @condition.leading.endOf
.
(case_clause_pattern
(_) @condition
)
.
(_)? @condition.trailing.startOf
) @_dummy
) @condition.domain @condition.iteration
(#single-or-multi-line-delimiter! @condition @_dummy ", " ",\n")
)

(use
value: (_) @value
) @value.domain

(use
assignments: (use_assignments) @name
)
Loading