62 Commits

Author SHA1 Message Date
Jen-Chieh Shen
a89ae451d9 ci: Test Emacs 29.4 2024-09-15 02:30:50 -07:00
Nathan Lovato
32086df833 Merge pull request #138 from xiliuya/add-macos-config-support
Set darwin's eglot config dir
2024-05-09 17:23:16 +02:00
Nathan Lovato
4ae8760e19 Merge pull request #148 from godotengine/ci/exl
ci: Exclude macos tests below 27.x
2024-05-09 17:21:47 +02:00
Jen-Chieh Shen
ab6aae89aa ci: Exclude macos tests below 27.x 2024-05-07 23:38:50 -07:00
Jen-Chieh Shen
2737f1c68c Merge pull request #145 from NicolasPetton/master 2024-04-24 14:57:35 -07:00
Jen-Chieh Shen
cd92e12084 Merge pull request #146 from NicolasPetton/fix-142
Fix #142: Add missing function `gdscript-mark-defun'
2024-04-19 13:59:22 -07:00
Nicolas Petton
becce1a4ba Fix #142: Add missing function `gdscript-mark-defun' 2024-04-18 01:14:58 +02:00
Nicolas Petton
718267511f Fix file path completion when projectile is used
When projectile is being used, `projectile-project-files' already returns file
paths relative to the project root directory.
2024-04-17 15:28:06 +02:00
Nicolas Petton
d25f778f02 Use when-let in gdscript-completion-insert-file-path-at-point 2024-04-17 15:26:05 +02:00
Jen-Chieh Shen
b8a840448a Merge pull request #143 from jcs-PR/ci/29.3 2024-03-28 10:39:37 -07:00
Jen-Chieh Shen
e0a8dc9f0b ci: Test Emacs 29.3 2024-03-27 14:53:39 -07:00
Samuel D
8a28276daa fix: Follow indent cleaning (#141)
`(line-beginning-position)` and `(point)` work with character (tab = 1
character)
but `(current-indenantion)` give the column number of the
indenantion (tab = 4 columns)
Using `(current-indentation)` and `(current-indentation)` is cleaner
and use the same convention of "column numbering"

Co-authored-by: Samuel D <samueld@mailo.com>
2023-10-24 13:50:57 +02:00
xiliuya
a6efb8713d - Using unless to change eglot-server-program 2023-09-24 11:56:49 +08:00
xiliuya
9b26d25aa3 - Make sure `eglot-server-programs only have one 'gdscript-mode key 2023-09-23 12:21:05 +08:00
xiliuya
bcb50cfe2c - add Windows-nt eglot config dir 2023-09-22 00:30:30 +08:00
xiliuya
0938403561 - set darwin's eglot config dir 2023-09-22 00:02:31 +08:00
xiliuya
3e2ae19f03 Merge pull request #133 from xiliuya/add-gdscript-ts-mode
Add treesit Major mode `gdscript-ts-mode
2023-05-28 07:44:33 +08:00
xiliuya
812da6aa3c - fix toc indent 2023-05-25 16:34:36 +08:00
xiliuya
4946aff35a - remove trailing lines 2023-05-25 14:51:00 +08:00
xiliuya
0692056e95 - README.md : remove the root level. 2023-05-25 14:45:09 +08:00
xiliuya
b7188197a5 - fix imenu local variable 2023-05-25 13:23:04 +08:00
xiliuya
44fc361bd7 - trims extra spaces 2023-05-25 13:07:52 +08:00
xiliuya
268abf778b - fix 'No such file or directory, treesit' 2023-05-25 12:43:03 +08:00
xiliuya
13a3e00e6c - Add imenu support 2023-05-25 12:35:37 +08:00
xiliuya
45e05fd58b - gdscript-ts-mode: Add treesit support for emacs 29+ 2023-05-23 18:20:13 +08:00
Jen-Chieh Shen
cee6d61591 Merge pull request #131 from xiliuya/eglot-tmp-buffer-fix 2023-05-15 04:39:34 +08:00
xiliuya
3995a7b2ae gdscript-eglot: Add goto-char to 0 ,and kill the res file buffer 2023-05-14 19:21:18 +08:00
xiliuya
70a243278a Merge pull request #130 from MenacingMecha/patch-1
Update LSP section of README.md. Fixes #129.
2023-05-11 09:23:38 +08:00
MenacingMecha
a5a25f07ac Update LSP section of README.md
- Includes `eglot`
- Lists `elgot` first, as it is (soon to be) in-built, and requires less config to set up
- Includes steps to get `eglot` working with Godot 3
2023-05-11 00:16:38 +01:00
xiliuya
a48ad04502 gdscript-comint.el: add `gdscript-godot-executable' support flatpak (#127)
* gdscript-comint.el: add `gdscript-godot-executable' support flatpak command

* can use when and remove trailing space after arguments

* (+ space) more accurate
2023-04-26 21:23:56 +02:00
xiliuya
73dac51758 docs: add Godot 4 debugger description (#126)
* docs: add Godot 4 debugger description

* Apply suggestions from code review

---------

Co-authored-by: Nathan Lovato <12694995+NathanLovato@users.noreply.github.com>
2023-04-23 10:13:46 +02:00
xiliuya
68f18932a4 Merge pull request #125 from jcs-PR/docs/eask
docs: Use Eask for contributing
2023-04-23 12:22:23 +08:00
JenChieh
586d957650 docs: Use Eask for contributing 2023-04-22 13:20:24 -07:00
Jen-Chieh Shen
72ddbec953 tests: Avoid actions' warnings (#118)
* chore(Eask): Add package metadata

* tests: Avoid actions' warnings

* chore(Eask): Update eask's commands

* Remove extra package-file DSL
2023-04-22 10:06:11 +02:00
Jen-Chieh Shen
c8c22a6884 ci: Add experimental flag (#124) 2023-04-22 10:05:36 +02:00
Ruijie Yu
30c4d48f81 Added integration with eglot (#122)
Fixes #121.

* gdscript-eglot.el gdscript-eglot-version: added customizable option for
the godot version in use.
(gdscript-eglot-contact): added function to allow `eglot' to find the godot LSP
port.
* gdscript-mode.el Commmentary: double space after period.
(require 'gdscript-eglot): require this new file.
(with-eval-after-load 'eglot): tell eglot how to find godot LSP.
2023-04-21 08:20:10 +02:00
Jen-Chieh Shen
f071667776 tests: Setup node is no longer required (#117)
* tests: Setup node is no longer required

* chore(Eask): Add package's metadata
2023-04-20 13:34:31 +02:00
Benjamin
d392e8aa7e Fix docs open wrong number of args err (#116) 2022-07-21 07:47:42 +02:00
Jen-Chieh Shen
d9e1f7f766 Add CI 2022-05-10 11:44:47 +02:00
Nathan Lovato
4badcf6a0c Remove outdated command from the README
fix #110
2021-10-04 06:19:37 -06:00
Hugo Locurcio
b7bfa6a3b2 Merge pull request #106 from bkaestner/patch-1
Replace old repository path
2021-03-28 22:37:43 +02:00
Benjamin Kästner
9043e1a6b6 Replace old repository path
The repository was moved from GDQuest to godotengine on GitHub.
2021-03-28 20:59:54 +02:00
Nathan Lovato
16c631cd6f Merge pull request #104 from VlachJosef/master
Create hydra only when requested so we can detect missing hydra.el
2021-01-31 09:51:18 -06:00
Josef Vlach
4a1175f467 Create hydra only when requested so we can detect missing hydra.el
Also this avoids explicit reference to `gdscript-hydra--menu/body` which
is not know on compile time, which results in warning.
2021-01-31 14:41:14 +00:00
Nathan Lovato
bdce2da794 Add ability to toggle breakpoints on current line 2021-01-24 22:14:35 -06:00
Nathan Lovato
fe59b77c3f Add keybindings to run the game, add breakpoints, and continue execution 2021-01-24 22:14:35 -06:00
Nathan Lovato
e54edf94b8 Merge pull request #102 from VlachJosef/master
Change code snippets in README.md from lisp to elisp
2021-01-23 17:22:15 -06:00
Josef Vlach
d751ce6249 Change code snippets in README.md from lisp to elisp 2021-01-23 21:38:36 +00:00
Nathan Lovato
fa9ec1fead Correct typos in the README 2021-01-23 15:08:42 -06:00
Nathan Lovato
287acb7c76 Add screenshots of the editor when working in gdscript mode 2021-01-22 07:52:51 -06:00
Nathan Lovato
b53d56e467 Update changelog 2021-01-04 13:21:13 -06:00
Nathan Lovato
4e5bb877e3 Merge pull request #100 from clangdo/feature_double_hanging_indent
Add double hanging indent
2021-01-04 13:19:08 -06:00
Caelan
4edc27ee7c Change default scale for backwards compatibility 2020-12-28 19:11:00 -08:00
Caelan
9b1e313e2c Add configurable extra line continuation indentation 2020-12-28 16:15:37 -08:00
Caelan
f6c7bb5bb4 Add hanging indent width customization
* Clean up customization file
2020-12-28 15:58:19 -08:00
Nathan Lovato
20fc7e4381 Update Doom Emacs install instructions, format README 2020-12-13 12:46:25 -06:00
Nathan Lovato
75fe658ab8 Merge pull request #97 from VlachJosef/master
Simplify gdscript-project--get-all-scripts by using call-process
2020-10-26 07:19:19 -06:00
Josef Vlach
0aa2e8f52f Simplify gdscript-project--get-all-scripts by using call-process
rather than ag-project-regexp from ag.el
2020-10-24 21:19:43 +01:00
Nathan Lovato
95fdf3aa23 Merge pull request #96 from VlachJosef/master
gdscript-docs-browse-api - online browsing fix
2020-10-24 08:26:15 -06:00
Josef Vlach
163a1340e5 gdscript-docs-browse-api - online browsing fix 2020-10-24 14:50:47 +01:00
Nathan Lovato
1d6d707144 Update TOC, document auto-completion with LSP in README
Closes #42
2020-10-15 09:37:02 -06:00
Nathan Lovato
f87cc3e1c2 Update changelog for 1.4.0 2020-10-15 09:34:06 -06:00
32 changed files with 779 additions and 1265 deletions

56
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: CI
on:
push:
branches:
- master
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
emacs-version:
- 26.3
- 27.2
- 28.2
- 29.4
experimental: [false]
include:
- os: ubuntu-latest
emacs-version: snapshot
experimental: true
- os: macos-latest
emacs-version: snapshot
experimental: true
- os: windows-latest
emacs-version: snapshot
experimental: true
exclude:
- os: macos-latest
emacs-version: 26.3
- os: macos-latest
emacs-version: 27.2
steps:
- uses: actions/checkout@v3
- uses: jcs090218/setup-emacs@master
with:
version: ${{ matrix.emacs-version }}
- uses: emacs-eask/setup-eask@master
with:
version: 'snapshot'
- name: Run tests
run:
make ci

3
.gitignore vendored
View File

@@ -2,7 +2,8 @@
*.elc
# Packaging
.cask
.eask
dist/
# Backup files
*~

View File

@@ -2,6 +2,29 @@
This document lists new features, improvements, changes, and bug fixes in each release of the package.
## GDScript mode 1.5.0
- Added the ability to toggle breakpoint on the current line instead of either adding or removing them.
- Added keybindings matching Godot to run the project (<kbd>f5</kbd>), current scene (<kbd>f6</kbd>), continue execution (<kbd>f7</kbd>), and toggle breakpoints <kbd>F9</kbd>.
## GDScript mode 1.4.1
Thanks to @clangdo for the contribution!
- Fixed indent functions preventing double hanging indent in parentheses or after a `\`.
## GDScript mode 1.4.0
Big thanks to @VlachJosef and @rileyrg for their work on this release.
### New features
- Debugger support with breakpoints, code stepping, stack frames, remote scene tree, and more. See the [README](https://github.com/godotengine/emacs-gdscript-mode/blob/master/README.md) for more information.
### Bug fixes
- Fix scene and script selection not aborting when pressing <kbd>C-g</kbd>.
## GDScript mode 1.3.0
This release brings many quality-of-life improvements to work more productively with Godot and Emacs.

17
Eask Normal file
View File

@@ -0,0 +1,17 @@
(package "gdscript-mode"
"0.1.0"
"Major mode for Godot's GDScript language")
(website-url "https://github.com/godotengine/emacs-gdscript-mode/")
(keywords "languages")
(package-file "gdscript-mode.el")
(files "*.el")
(script "test" "echo \"Error: no test specified\" && exit 1")
(source "gnu")
(depends-on "emacs" "26.3")
(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432

36
Makefile Normal file
View File

@@ -0,0 +1,36 @@
SHELL := /usr/bin/env bash
EMACS ?= emacs
EASK ?= eask
.PHONY: clean checkdoc lint package install compile test
# TODO: add `lint` if we can?
ci: clean package install compile checkdoc
package:
@echo "Packaging..."
$(EASK) package
install:
@echo "Installing..."
$(EASK) install
compile:
@echo "Compiling..."
$(EASK) compile
test:
@echo "Testing..."
$(EASK) ert ./test/*.el
checkdoc:
@echo "Run checkdoc..."
$(EASK) lint checkdoc
lint:
@echo "Run package-lint..."
$(EASK) lint package
clean:
$(EASK) clean all

203
README.md
View File

@@ -7,34 +7,46 @@ This package adds support for the GDScript programming language from the Godot
game engine in Emacs. It gives syntax highlighting and indentations.
[Contributors](#contributing) are welcome!
![](assets/emacs-gdscript-imenu.png)
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**
- [Features](#features)
- [Contributing](#contributing)
- [How to install](#how-to-install)
- [Installing in Spacemacs](#installing-in-spacemacs)
- [Installing in Doom Emacs](#installing-in-doom-emacs)
- [Installing with `use-package` + `straight.el`](#installing-with-use-package--straightel)
- [Installing manually](#installing-manually)
- [Auto-completion with the Language Server Protocol (LSP)](#auto-completion-with-the-language-server-protocol-lsp)
- [Known issues](#known-issues)
- [Major mode with Treesit](#major-mode-with-treesit)
- [Install treesit](#install-treesit)
- [Install grammar](#install-grammar)
- [How to use](#how-to-use)
- [Opening the project in the editor](#opening-the-project-in-the-editor)
- [Running Godot with visual debug options](#running-godot-with-visual-debug-options)
- [Using Hydra](#using-hydra)
- [Formatting code with gdformat](#formatting-code-with-gdformat)
- [Browsing the Godot API with eww](#browsing-the-godot-api-with-eww)
- [Opening the project in the editor](#opening-the-project-in-the-editor)
- [Running Godot with visual debug options](#running-godot-with-visual-debug-options)
- [Using Hydra](#using-hydra)
- [Formatting code with gdformat](#formatting-code-with-gdformat)
- [Browsing the Godot API with eww](#browsing-the-godot-api-with-eww)
- [Using a local copy of the Godot docs](#using-a-local-copy-of-the-godot-docs)
- [Keyboard shortcuts](#keyboard-shortcuts)
- [Customization](#customization)
- [Using the debugger](#using-the-debugger)
- [Adding and removing breakpoints](#adding-and-removing-breakpoints)
- [Running the project with the debugger active](#running-the-project-with-the-debugger-active)
- [Fetching an object's details](#fetching-an-objects-details)
- [Debug Hydra](#debug-hydra)
- [The `* Stack frame vars *` buffer](#the--stack-frame-vars--buffer)
- [`* Inspector *` buffer](#-inspector--buffer)
- [`* Stack dump *` buffer](#-stack-dump--buffer)
- [`* Breakpoints *` buffer](#-breakpoints--buffer)
- [`* Scene tree *` buffer](#-scene-tree--buffer)
- [Adding and removing breakpoints](#adding-and-removing-breakpoints)
- [Running the project with the debugger active](#running-the-project-with-the-debugger-active)
- [Multi-line display](#multi-line-display)
- [Fetching an object's details](#fetching-an-objects-details)
- [Debug Hydra](#debug-hydra)
- [The `* Stack frame vars *` buffer](#the--stack-frame-vars--buffer)
- [`* Inspector *` buffer](#-inspector--buffer)
- [`* Stack dump *` buffer](#-stack-dump--buffer)
- [`* Breakpoints *` buffer](#-breakpoints--buffer)
- [`* Scene tree *` buffer](#-scene-tree--buffer)
<!-- markdown-toc end -->
## Features
This mode features all the essentials:
@@ -52,12 +64,17 @@ This mode features all the essentials:
- Auto-completion for all the keywords in the `gdscript-keywords.el` file.
- Run or open the project and files with Godot.
- Browsing the API reference in Emacs.
- Add treesit major mode support `gdscript-ts-mode` .
![](assets/emacs-gdscript-code-folding.png)
_Code folding in action._
## Contributing
Contributors are welcome! Check the [issues tab](issues) for tasks to work on and open a PR anytime.
If you find a bug, or would like to suggest an improvement, [open a new
If you find a bug or would like to suggest an improvement, [open a new
issue](issues/new).
For code style, we follow the [Emacs lisp style
@@ -66,29 +83,31 @@ and the [tips and
conventions](https://www.gnu.org/software/emacs/manual/html_node/elisp/Tips.html)
from the Emacs manual.
You should also check for errors and linter warnings in your code. You can do so in Emacs with flymake or flycheck but we recommend running the tool `makem.sh` provided with the repository:
You should also check for errors and linter warnings in your code. You can do so in Emacs with flymake or flycheck, but we recommend running the tool `Eask` provided with the repository:
This assumes you have [Eask](https://github.com/emacs-eask/cli) installed.
```sh
./makem.sh lint-compile
eask compile
```
This program will tell you if there is any problem with your code. If there's no output, everything is fine. You can run all tests like so, but note it might give you spelling errors that aren't relevant in this project:
```sh
./makem.sh all
eask lint checkdoc && eask lint package
```
## How to install
The package is available in the [MELPA](https://melpa.org/#/) package archive. Once you [set up MELPA](https://melpa.org/#/getting-started) you can install the package from Emacs:
```lisp
```elisp
M-x package-install gdscript-mode
```
Then, in your init.el file, you can require the package:
```lisp
```elisp
(require 'gdscript-mode)
```
@@ -96,7 +115,7 @@ Then, in your init.el file, you can require the package:
1. Add the package to the `dotspacemacs-additional-packages`. You can find it under the dotspacemacs/layers function:
```lisp
```elisp
(defun dotspacemacs/layers ()
"Configuration Layers declaration..."
(setq-default
@@ -108,60 +127,132 @@ Then, in your init.el file, you can require the package:
2. In your `dotspacemacs/user-config` function, require the package.
```lisp
```elisp
(defun dotspacemacs/user-config ()
(require 'gdscript-mode))
```
### Installing in Doom Emacs
Add the following package definition to your `.doom.d/packages.el` file:
Doom Emacs comes with a Godot GDScript module.
```lisp
(package! gdscript-mode
:recipe (:host github
:repo "GDQuest/emacs-gdscript-mode"))
You just need to add the "lang: gdscript" keyword to your `.doom.d/init.el` file.
```elisp
:lang
(gdscript +lsp) ; the language you waited for
```
Require the package in your `.doom.d/config.el` file:
The `+lsp` flag adds language server support for game development with Godot.
```lisp
(require 'gdscript-mode)
```
To see the module's documentation in Emacs, place your cursor over the word `gdscript` and press <kbd>k</kbd>.
### Installing with `use-package` + `straight.el`
Add the call to use-package to your Emacs configuration:
```lisp
```elisp
(use-package gdscript-mode
:straight (gdscript-mode
:type git
:host github
:repo "GDQuest/emacs-gdscript-mode"))
:repo "godotengine/emacs-gdscript-mode"))
```
### Installing manually
1. Clone the repository or download a [stable release](https://github.com/GDQuest/emacs-gdscript-mode/releases) to your computer.
1. Clone the repository or download a [stable release](https://github.com/godotengine/emacs-gdscript-mode/releases) to your computer.
1. In your init.el file, add a call to load and require the package.
```lisp
```elisp
(add-to-list 'load-path "/path/to/gdscript-mode")
(require 'gdscript-mode)
```
## Auto-completion with the Language Server Protocol (LSP)
For auto-completion, we rely on either the [eglot](https://github.com/joaotavora/eglot) or [lsp-mode](https://emacs-lsp.github.io/lsp-mode/) packages, and the GDScript language server which is built into Godot.
To use the LSP with `eglot`, you need to install `eglot` on top of `gdscript-mode`, if using an Emacs version earlier than 29.
After installation, `eglot` can be connected on startup by adding `eglot-ensure` as a hook on `gdscript-mode-hook`.
Note that, due to language server changes made in Godot 4, usage with Godot 3 requires `gdscript-eglot-version` to be customized to 3.
An example configuration for Godot 3 usage with `use-package`:
```elisp
(use-package gdscript-mode
:hook (gdscript-mode . eglot-ensure)
:custom (gdscript-eglot-version 3))
```
To use the LSP with `lsp-mode`, you need to install `lsp-mode` on top of `gdscript-mode` and configure it. To install and configure `lsp-mode`, see the [lsp-mode documentation](https://emacs-lsp.github.io/lsp-mode/page/installation/).
### Known issues
There are some known issues with the GDScript language server in Godot 3.2 due to the server being a bit young and not following the specification strictly. This mainly causes some `unknown notification` errors in lsp-mode at the moment. You can suppress them by adding the following code to your Emacs configuration (thanks to Franco Garcia for sharing this workaround):
```elisp
(defun lsp--gdscript-ignore-errors (original-function &rest args)
"Ignore the error message resulting from Godot not replying to the `JSONRPC' request."
(if (string-equal major-mode "gdscript-mode")
(let ((json-data (nth 0 args)))
(if (and (string= (gethash "jsonrpc" json-data "") "2.0")
(not (gethash "id" json-data nil))
(not (gethash "method" json-data nil)))
nil ; (message "Method not found")
(apply original-function args)))
(apply original-function args)))
;; Runs the function `lsp--gdscript-ignore-errors` around `lsp--get-message-type` to suppress unknown notification errors.
(advice-add #'lsp--get-message-type :around #'lsp--gdscript-ignore-errors)
```
## Major mode with Treesit
[Treesit](https://github.com/tree-sitter/tree-sitter) is an incremental parsing system for programming tools.
This package has a major mode (gdscript-ts-mode). That supports the use tree-sitter for font-lock, imenu, indentation, and navigation of `gdscript` files.
Emacs version 29 or higher is required to use this mode.
### Install treesit
We need to install tree-sitter library, When under Arch Linux :
```sh
sudo pacman -S tree-sitter
```
### Install grammar
To support Gdscript, we must install [gdscript-grammar](https://github.com/PrestonKnopp/tree-sitter-gdscript.git):
```sh
git clone https://github.com/PrestonKnopp/tree-sitter-gdscript.git
cd tree-sitter-gdscript/src
cc -std=c99 -c parser.c
cc -c scanner.cc
cc -shared parser.o scanner.o -o libtree-sitter-gdscript.so
```
Additional directories to look for tree-sitter language definitions. ( DIR is your working path )
```emacs-lisp
(setq treesit-extra-load-path '("DIR/tree-sitter-gdscript/src/"))
```
enjoy.
## How to use
### Opening the project in the editor
You can open the project in the Godot editor with `M-x gdscript-godot-open-project-in-editor`, or open files and more in Godot with the `M-x gdscript-godot-*` commands.
You can open the Godot editor with `M-x gdscript-godot-open-project-in-editor`, or open files and more in Godot with the `M-x gdscript-godot-*` commands.
By default, these commands try to use an executable named `godot` on the system [PATH environment variable](<https://en.wikipedia.org/wiki/PATH_(variable)>).
If you don't have `godot` available there, you can set a custom executable name or path to use instead:
```lisp
```elisp
(setq gdscript-godot-executable "/path/to/godot")
```
@@ -178,24 +269,20 @@ Here are the available options:
3. `--debug-navigation`
4. `--debug-collisions --debug-navigation`
The last selected option is saved for the next time you call `gdscript-godot-run-project-debug`. To remove debug options, you need to call the command with the universal argument again.
The last selected option is saved for the next time you call `gdscript-godot-run-project-debug`. To turn off debug options, you need to call the command with the universal argument again.
### Using Hydra
Running `gdscript-hydra-show` (<kbd>C-c r</kbd>) opens a [hydra](https://github.com/abo-abo/hydra) popup with options to open the editor or run the project, a scene, or a script, including with visual debug options.
```
d ( ) Debug p run project t run script h run from history a format all q quit
e ( ) Editor s run scene r run last g switch to *godot* b format buffer
![](assets/emacs-gdscript-hydra.png)
c [ ] Visible collisions shapes
n [ ] Visible navigation
```
_Hydra interactive menu to run the project and set debug options on the fly._
### Formatting code with gdformat
You can call the `gdscript-format` function to format the current buffer with
`gdformat`. Alternatively `gdscript-format-all` will reformat all gdscripts in
`gdformat`. Alternatively, `gdscript-format-all` will reformat all GDScript files in
the project. This feature requires the python package `gdtoolkit` to be installed
and available on the system's PATH variable.
@@ -208,7 +295,7 @@ pip3 install gdtoolkit
### Browsing the Godot API with eww
With the point on a built-in class you can press `C-c C-b o` to open the code reference for that class in the text browser [eww](https://www.gnu.org/software/emacs/manual/html_node/emacs/EWW.html).
With the point on a built-in class, you can press `C-c C-b o` to open the code reference for that class in the text browser [eww](https://www.gnu.org/software/emacs/manual/html_node/emacs/EWW.html).
To open the main API reference page and browse it, press `C-c C-b a`.
@@ -221,7 +308,7 @@ You can browse the API reference offline with `eww`. To do so:
For example:
```lisp
```elisp
(setq gdscript-docs-local-path "/home/gdquest/Documents/docs/godot")
```
@@ -255,7 +342,7 @@ To find all GDScript-mode settings, press `M-x customize` and search for "gdscri
Code example:
```lisp
```elisp
(setq gdscript-use-tab-indents t) ;; If true, use tabs for indents. Default: t
(setq gdscript-indent-offset 4) ;; Controls the width of tab-based indents
(setq gdscript-godot-executable "/path/to/godot") ;; Use this executable instead of 'godot' to open the Godot editor.
@@ -264,13 +351,17 @@ Code example:
## Using the debugger
Emacs GDScript mode includes support for the GDScript debugger. You can use breakpoints, use code stepping functions, see your nodes' state at runtime, and more.
Emacs GDScript mode includes support for the GDScript debugger.
*The debugger in this package is only for Godot 3. Godot 4 supports the Debugger Adapter Procol (DAP), which you can use with the [dap-mode](https://github.com/emacs-lsp/dap-mode) package.*
You can use the debugger tools to manage breakpoints, step through code, and more.
To get started with this feature, you need to add a least one breakpoint.
### Adding and removing breakpoints
You can add a breakpoint on the current line with `gdscript-debug-add-breakpoint` (<kbd>C-c C-d b</kbd>). A red dot should appear in the left fringe. Use `gdscript-debug-remove-breakpoint` (<kbd>C-c C-d r</kbd>) to remove a breakpoint on the current line.
Like in Godot's editor, you can toggle a breakpoint on the current line with `gdscript-debug-toggle-breakpoint` (<kbd>F9</kbd>).
After adding at least one breakpoint to the project, a buffer named `* Breakpoints *` is created. This buffer displays all existing breakpoints in a project. In that buffer, pressing <kbd>D</kbd> on a breakpoint line deletes the breakpoint. Pressing <kbd>RET</kbd> opens the corresponding GDScript file in another buffer.
@@ -282,7 +373,7 @@ The debugger's server runs on `localhost` through port `6010` by default. You ca
Once Godot hits a breakpoint, Emacs displays two new buffers:
- `* Stack frame vars *` displays the locals, members, and globals variables for the current stack point. It show variable name, its type and its value.
- `* Stack frame vars *` displays the locals, members, and globals variables for the current stack point. It shows the variable name, its type, and its value.
- `* Inspector *` displays detailed information about the selected object. By default, it shows the properties of `self`.
You can inspect any object in those two buffers by pressing <kbd>RET</kbd> on the corresponding line.
@@ -323,7 +414,7 @@ o pin u unpin q quit
### The `* Stack frame vars *` buffer
The stack frame buffer displays the locals, members, and globals variables for the current stack point. Here are available keyboard shortcuts:
The stack frame buffer displays the locals, members, and global variables for the current stack point. Here are available keyboard shortcuts:
- <kbd>TAB</kbd> toggles multi-line display for selected types.
- <kbd>RET</kbd> on an object line to display its details in the `* Inspector *`buffer.
@@ -337,12 +428,12 @@ The stack frame buffer displays the locals, members, and globals variables for t
### `* Inspector *` buffer
Contains information about inspected object. By default `self` variable from `* Stack frame vars *` is displayed. Inspected object is kept to be focused until other object is inspected or until inspected object cease to exists, in which case current `self` is displayed instead.
Contains information about inspected object. By default `self` variable from `* Stack frame vars *` is displayed. The inspected object is kept in focus until you inspect another object or until the active object ceases to exists, in which case the current `self` is displayed instead.
- Press <kbd>TAB</kbd> to toggle multi-line display for selected typess.
- Press <kbd>RET</kbd> on object line to display its detailss.
- Press <kbd>RET</kbd> on `Node/path` line (second line from the top) to show given object in `* Scene Tree *` buffers.
- Press <kbd>l</kbd> deep in nested object to navigate one level up in the structure (ie. back). Pressing `l` while on top level object displays `* Stack frame vars *` buffers.
- Press <kbd>l</kbd> deep in nested object to navigate one level up in the structure (ie. back). Pressing `l` while on top-level object displays `* Stack frame vars *` buffers.
- Press <kbd>d</kbd> to display additional details for object variabless.
- Press <kbd>p</kbd> to go to the previous lines.
- Press <kbd>n</kbd> to go to the next lines.
@@ -355,7 +446,7 @@ Contains information about inspected object. By default `self` variable from `*
Contains stack dump information.
- Press <kbd>SPC</kbd> to jump to gdscript file where stack frame points to.
- Press <kbd>RET</kbd> to jump to gdscript file and to show `* Stack frame vars *`, `* Inspector *` buffers and a debug hydra.
- Press <kbd>RET</kbd> to jump to the gdscript file and show `* Stack frame vars *`, `* Inspector *` buffers, and a debug hydra.
- Press <kbd>l</kbd> to display the `* Stack frame vars *` buffer.
- Press <kbd>p</kbd> to go to the previous line.
- Press <kbd>n</kbd> to go to the next line.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -58,8 +58,17 @@
ARGUMENTS are command line arguments for godot executable.
When run it will kill existing process if one exists."
(let ((buffer-name (gdscript-util--get-godot-buffer-name (member "-e" arguments)))
(inhibit-read-only t))
(if (not (or (file-executable-p gdscript-godot-executable) (executable-find gdscript-godot-executable)))
(inhibit-read-only t)
(godot-command gdscript-godot-executable))
;; support flatpak
(when (string-match-p (rx "run" (+ space) "org.godotengine.Godot") godot-command)
(let ((exec-split (split-string godot-command)))
(setq godot-command (car exec-split))
(setq arguments (append (cdr exec-split) arguments))))
(if (not (or (file-executable-p godot-command)
(executable-find godot-command)))
(error "Error: Could not execute '%s'. Please customize the `gdscript-godot-executable variable'" gdscript-godot-executable)
(with-current-buffer (get-buffer-create buffer-name)
(when gdscript-gdformat-save-and-format
@@ -68,7 +77,7 @@ When run it will kill existing process if one exists."
(godot-mode)
(buffer-disable-undo))
(erase-buffer)
(comint-exec (current-buffer) buffer-name gdscript-godot-executable nil arguments)
(comint-exec (current-buffer) buffer-name godot-command nil arguments)
(set-process-sentinel (get-buffer-process (current-buffer)) 'gdscript-comint--sentinel)
(pop-to-buffer (current-buffer))))))

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -63,23 +63,24 @@ first."
(let ((has-projectile (featurep 'projectile)))
(when has-projectile
(projectile-maybe-invalidate-cache arg))
(let* ((project-root
(if has-projectile
(projectile-ensure-project (projectile-project-root))
(gdscript-util--find-project-configuration-file)))
(file
(if has-projectile
(projectile-completing-read
"Find file: "
(projectile-project-files project-root))
(read-file-name
"Find file: "
project-root))))
(when file
(insert
(concat "\"res://"
(gdscript-util--get-godot-project-file-path-relative file)
"." (file-name-extension file) "\""))))))
(when-let* ((project-root
(if has-projectile
(projectile-ensure-project (projectile-project-root))
(gdscript-util--find-project-configuration-file)))
(file
(if has-projectile
(projectile-completing-read
"Find file: "
(projectile-project-files project-root))
(read-file-name
"Find file: "
project-root)))
(resource-path
(if has-projectile
file
(concat (gdscript-util--get-godot-project-file-path-relative file)
"." (file-name-extension file)))))
(insert (concat "\"res://" resource-path "\"")))))
(provide 'gdscript-completion)

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -41,8 +41,8 @@
(defcustom gdscript-use-type-hints t
"If t, inserted snippets contain type hints."
:group 'gdscript
:type 'boolean)
:type 'boolean
:group 'gdscript)
;; gdscript-indent
(defcustom gdscript-use-tab-indents t "Use tabs (t) or spaces (nil)."
@@ -54,30 +54,31 @@
:group 'gdscript)
(defcustom gdscript-indent-offset 4 "Default indentation offset for Gdscript."
:group 'gdscript
:type 'integer
:safe 'integerp)
:safe 'integerp
:group 'gdscript)
(defcustom gdscript-indent-trigger-commands '(indent-for-tab-command yas-expand yas/expand)
"Commands that might trigger a `gdscript-indent-line' call."
:type '(repeat symbol):group'gdscript)
:type '(repeat symbol)
:group'gdscript)
;; gdscript-fill-paragraph.el
(defcustom gdscript-fill-comment-function 'gdscript-fill-paragraph-fill-comment
(defcustom gdscript-fill-comment-function 'gdscript-fill-paragraph-fill-comment
"Function to fill comments.
This is the function used by `gdscript-fill-paragraph' to
fill comments."
:type 'symbol
:group 'gdscript)
(defcustom gdscript-fill-string-function 'gdscript-fill-paragraph-fill-string
"Function to fill strings.
This is the function used by `gdscript-fill-paragraph' to
fill strings."
:type 'symbol
:group 'gdscript)
:group 'gdscript)
(defcustom gdscript-fill-paren-function 'gdscript-fill-paragraph-fill-paren
"Function to fill parens.
This is the function used by `gdscript-fill-paragraph' to
fill parens."
@@ -88,7 +89,15 @@ fill parens."
"Multiplier applied to indentation inside multi-line def blocks."
:version "26.1"
:type 'integer
"Multiplier applied to indentation inside multi-line def blocks."
:safe 'natnump
:group 'gdscript)
(defcustom gdscript-indent-line-continuation-scale 1
"Multiplier applied to indentation of line continuation in
general (inside parentheses and after backslash)."
:type 'integer
:options '(1 2)
:group 'gdscript)
(defcustom gdscript-godot-executable "godot"
"The godot executable which is either a full path such as '~/bin/godot2.2'
@@ -116,12 +125,17 @@ so it is not slowing down Godot execution."
:group 'gdscript)
(defcustom gdscript-docs-force-online-lookup nil
:group 'gdscript)
"If true, calling commands like gdscript-docs-browse-api
browses the online API reference, even if a local copy is
available."
:type 'boolean
:group 'gdscript)
(defcustom gdscript-docs-use-eww t
:group 'gdscript)
"If set to false use the emacs configurable `browse-url'
function rather than `eww' directly. `browse-url' can be
configured to open the desktop default GUI browser, for example,
via the variable `browse-url-browser-function'"
:type 'boolean
:group 'gdscript)

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.0.1
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: vlach.josef@gmail.com
@@ -1868,13 +1868,35 @@ calling `gdscript-debug--table-string'."
(setq buffer-read-only t)
(buffer-disable-undo))
(defun gdscript-debug-add-breakpoint ()
(defun gdscript-debug-toggle-breakpoint ()
"Add or remove a breakpoint on the line at POINT."
(interactive)
(let* ((breakpoint (gdscript-debug--construct-breakpoint-at-point)))
(if (gdscript-debug--is-existing-breakpoint-p breakpoint)
(gdscript-debug--remove-breakpoint breakpoint)
(gdscript-debug--add-breakpoint-to-line breakpoint))))
(defun gdscript-debug--construct-breakpoint-at-point ()
"Construct a breakpoint object for the line at POINT and return it.
May match an existing breakpoint."
(gdscript-debug--with-gdscript-file file-info
(let* ((line (line-number-at-pos))
(let* ((start (line-beginning-position))
(end (line-end-position))
(line (line-number-at-pos))
(file (car file-info))
(file-absolute (cdr file-info))
(breakpoint (gdscript-breakpoint-create :file file :file-absolute file-absolute :line line)))
breakpoint)))
(defun gdscript-debug--is-existing-breakpoint-p (breakpoint)
"Return t if `BREAKPOINT' is an existing breakpoint in the project."
(member breakpoint gdscript-debug--breakpoints))
(defun gdscript-debug--add-breakpoint-to-line (breakpoint)
"Register `BREAKPOINT' to the current line in a GDScript buffer."
(gdscript-debug--with-gdscript-file file-info
(let* ((line (line-number-at-pos))
(file (car file-info)))
(if (member breakpoint gdscript-debug--breakpoints)
(message "Breakpoint already present at %s:%s" file line)
(gdscript-debug--add-fringe (line-beginning-position) (not gdscript-debug--skip-breakpoints) 'gdb-bptno 1)
@@ -1884,15 +1906,13 @@ calling `gdscript-debug--table-string'."
(gdscript-debug--send-command
(gdscript-debug--breakpoint-command file line t)))))))
(defun gdscript-debug-remove-breakpoint ()
(interactive)
(defun gdscript-debug--remove-breakpoint (breakpoint)
"Remove `BREAKPOINT' to the current line in a GDScript buffer."
(gdscript-debug--with-gdscript-file file-info
(let* ((start (line-beginning-position))
(end (line-end-position))
(line (line-number-at-pos))
(file (car file-info))
(file-absolute (cdr file-info))
(breakpoint (gdscript-breakpoint-create :file file :file-absolute file-absolute :line line)))
(file (car file-info)))
(if (not (member breakpoint gdscript-debug--breakpoints))
(message "No breakpoint at %s:%s" file line)
(gdscript-debug--remove-strings start end)
@@ -1920,7 +1940,9 @@ calling `gdscript-debug--table-string'."
(prop `(left-fringe breakpoint ,(if (not enabled) 'breakpoint-enabled 'breakpoint-disabled))))
(put-text-property 0 1 'display prop string))))))))))))
(defun gdscript-debug-toggle-breakpoint ()
(defun gdscript-debug-toggle-skip-breakpoints ()
"Toggle the execution of all breakpoints without removing them.
Like Godot's Skip Breakpoints button."
(interactive)
(setq gdscript-debug--skip-breakpoints (not gdscript-debug--skip-breakpoints))
(gdscript-debug--set-left-fringe-breakpoints gdscript-debug--skip-breakpoints)
@@ -1937,7 +1959,7 @@ calling `gdscript-debug--table-string'."
(with-current-buffer buffer
(goto-char (point-min))
(forward-line (1- line))
(gdscript-debug-remove-breakpoint)))))
(gdscript-debug--remove-breakpoint breakpoint)))))
(message "Not recognized as breakpoint line")))
(defun gdscript-debug-goto-breakpoint ()
@@ -2048,7 +2070,7 @@ calling `gdscript-debug--table-string'."
(defvar gdscript-debug--breakpoints-mode-map
(let ((map (make-sparse-keymap)))
(suppress-keymap map)
(define-key map " " 'gdscript-debug-toggle-breakpoint)
(define-key map " " 'gdscript-debug-toggle-skip-breakpoints)
(define-key map "q" 'kill-current-buffer)
(define-key map "D" 'gdscript-debug-delete-breakpoint)
(define-key map "\r" 'gdscript-debug-goto-breakpoint)

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -34,7 +34,7 @@
(require 'eww)
(require 'gdscript-customization)
(defun gdscript-docs-open (url &optional)
(defun gdscript-docs-open (url &rest _)
"when `gdscript-docs-use-eww' is true use `eww' else use `browse-url'"
(if gdscript-docs-use-eww
(if (file-exists-p url) (eww-open-file url) (eww-browse-url url t))
@@ -44,7 +44,7 @@
(defun gdscript-docs-browse-api (&optional force-online)
"Open the main page of Godot API. Use the universal prefix (C-u) to force browsing the online API."
(interactive)
(if (and (or gdscript-docs-force-online-lookup current-prefix-arg force-online) (not (string= gdscript-docs-local-path "")))
(if (and (or gdscript-docs-force-online-lookup current-prefix-arg force-online) (string= gdscript-docs-local-path ""))
(gdscript-docs-open "https://docs.godotengine.org/en/stable/classes/index.html?#godot-api")
(let ((file (concat (file-name-as-directory gdscript-docs-local-path) "classes/index.html")))
(if (file-exists-p file)
@@ -63,12 +63,12 @@ If a page is already open, switch to its buffer. Use local docs if gdscripts-doc
(lambda (current-buffer)
(with-current-buffer current-buffer
(when (derived-mode-p 'eww-mode)
(string-suffix-p symbol(string-remove-suffix ".html" (plist-get eww-data :url)) t)
))) (buffer-list)))))
(string-suffix-p symbol (string-remove-suffix ".html" (plist-get eww-data :url)) t))))
(buffer-list)))))
(if buffer (pop-to-buffer-same-window buffer)
(if (string= "" symbol)
(message "No symbol at point or open API reference buffers.")
(if (and (not gdscript-docs-force-online-lookup)(not (or current-prefix-arg force-online)) (not (string= gdscript-docs-local-path "")))
(if (and (not gdscript-docs-force-online-lookup) (not (or current-prefix-arg force-online)) (not (string= gdscript-docs-local-path "")))
(let ((file (concat (file-name-as-directory gdscript-docs-local-path) (file-name-as-directory "classes") "class_" symbol ".html")))
(if (file-exists-p file)
(gdscript-docs-open file)

81
gdscript-eglot.el Normal file
View File

@@ -0,0 +1,81 @@
;;; gdscript-eglot.el --- Integration with eglot -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2023 GDQuest and contributors
;;
;; Author: Ruijie Yu <ruijie@netyu.xyz>
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
;; Created: June 2020
;; Keywords: languages
;;
;; This file is not part of GNU Emacs.
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;
;; Handles the configuraiton of eglot.
;; This supports `gdscript-mode' using `eglot'.
;;
;;; Code:
;;;###autoload
(defgroup gdscript-eglot nil
"Configurations in gdscript related to `eglot'."
:group 'gdscript)
;;;###autoload
(defcustom gdscript-eglot-version 4
"The version of godot in use."
:type 'integer)
;;;###autoload
(defun gdscript-eglot-contact (_interactive)
"Attempt to help `eglot' contact the running gdscript LSP.
Returns a list (HOST PORT) if successful, nil otherwise. See the
last definition of CONTACT in `eglot-server-programs' for
definitions of HOST, PORT, and INTERACTIVE.
For more context, see
https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-04/msg01070.html."
(save-excursion
(let* ((cfg-dir (or (getenv "XDG_CONFIG_HOME")
(pcase system-type
('darwin "~/Library/Application Support/Godot/")
('windows-nt "%APPDATA%\\Godot\\")
('gnu/linux "~/.config/"))))
(cfg-buffer
(find-file-noselect
(expand-file-name
(format "godot/editor_settings-%d.tres"
gdscript-eglot-version)
cfg-dir)))
(port
(with-current-buffer cfg-buffer
(goto-char 0)
(and
(re-search-forward
(rx "network/language_server/remote_port"
(* space) ?= (* space)
(group (+ digit)))
nil t)
(string-to-number (match-string 1))))))
(kill-buffer cfg-buffer)
;; then return the host-port list when found
(and port (list "localhost" port)))))
(provide 'gdscript-eglot)
;;; gdscript-eglot.el ends here.

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest, Pawel Lampe
;; Author: Pawel Lampe <pawel.lampe@gmail.com>, Nathan Lovato <nathan@gdquest.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Franco Eusébio Garcia <francoegarcia@outlook.com>, Nathan Lovato <nathan@gdquest.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -47,11 +47,15 @@
(defvar gdscript-hydra--editor nil)
(defvar gdscript-hydra--debug-collisions nil)
(defvar gdscript-hydra--debug-navigation nil)
(defvar gdscript-hydra--hydra nil)
(defun gdscript-hydra-show ()
"Show gdcript hydra."
(interactive)
(gdscript-util--with-available-hydra (gdscript-hydra--menu/body)))
(gdscript-util--with-available-hydra
(unless gdscript-hydra--hydra
(setq gdscript-hydra--hydra (gdscript-hydra--create)))
(funcall gdscript-hydra--hydra)))
(defun gdscript-hydra--selected (selected)
"Visual representation for (non)SELECTED checkboxes."
@@ -110,11 +114,10 @@ on hydra checkboxes."
"Choose command to run from history of commands."
(gdscript-godot--run-command (gdscript-history--select-from-history)))
(ignore-errors
;; Don't signal an error when hydra.el is not present
(defun gdscript-hydra--create ()
(defhydra gdscript-hydra--menu (:hint none
:body-pre (setq gdscript-hydra--open t)
:before-exit (setq gdscript-hydra--open nil))
:body-pre (setq gdscript-hydra--open t)
:before-exit (setq gdscript-hydra--open nil))
"
_d_ (?d?) Debug _p_ run project _t_ run script _h_ run from history _a_ format all _q_ quit
_e_ (?e?) Editor _s_ run scene _r_ run last _g_ switch to *godot* _b_ format buffer

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -273,17 +273,19 @@ possibilities can be narrowed to specific indentation points."
(current-column)))
(`(,(or :after-block-start
:after-backslash-first-line
:after-backslash-assignment-continuation
:inside-paren-newline-start) . ,start)
;; Add one indentation level.
(goto-char start)
(+ (current-indentation) gdscript-indent-offset))
(`(,(or :inside-paren
:after-backslash-block-continuation
:after-backslash-dotted-continuation) . ,start)
;; Use the column given by the context.
:after-backslash-dotted-continuation
:after-backslash-assignment-continuation) . ,start)
;; Use (possibly extra) indentation given by the configuration
(goto-char start)
(current-column))
(+ (current-indentation)
(* gdscript-indent-offset
gdscript-indent-line-continuation-scale)))
(`(:after-block-end . ,start)
;; Subtract one indentation level.
(goto-char start)
@@ -345,11 +347,7 @@ to the maximum available level. When indentation is the minimum
possible and PREVIOUS is non-nil, cycle back to the maximum
level."
(let ((follow-indentation-p
;; Check if point is within indentation.
(and (<= (line-beginning-position) (point))
(>= (+ (line-beginning-position)
(current-indentation))
(point)))))
(<= (current-column) (current-indentation))))
(save-excursion
(indent-line-to
(gdscript-indent-calculate-indentation previous))

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -26,7 +26,7 @@
;;; Commentary:
;; Adds support for the GDScript programming language from the Godot game
;; engine. This is a domain-specific language dedicated to game programming.
;; engine. This is a domain-specific language dedicated to game programming.
;;; Code:
@@ -42,6 +42,10 @@
(require 'gdscript-godot)
(require 'gdscript-hydra)
(require 'gdscript-debug)
(require 'gdscript-eglot)
(when (version< "29" emacs-version)
(require 'gdscript-ts-mode))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.gd\\'" . gdscript-mode))
@@ -49,6 +53,13 @@
(add-to-list 'auto-mode-alist '("\\.tscn\\'" . conf-toml-mode))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.tres\\'" . conf-toml-mode))
;;;###autoload
(with-eval-after-load 'eglot
(defvar eglot-server-programs)
(unless (equal (alist-get 'gdscript-mode eglot-server-programs)
#'gdscript-eglot-contact)
(push (cons 'gdscript-mode #'gdscript-eglot-contact)
eglot-server-programs)))
(defvar gdscript-mode-map (let ((map (make-sparse-keymap)))
;; Movement
@@ -69,8 +80,10 @@
;; Run in Godot.
(define-key map (kbd "C-c C-r p") 'gdscript-godot-open-project-in-editor)
(define-key map (kbd "C-c C-r r") 'gdscript-godot-run-project)
(define-key map (kbd "<f5>") 'gdscript-godot-run-project)
(define-key map (kbd "C-c C-r d") 'gdscript-godot-run-project-debug)
(define-key map (kbd "C-c C-r s") 'gdscript-godot-run-current-scene)
(define-key map (kbd "<f6>") 'gdscript-godot-run-current-scene)
(define-key map (kbd "C-c C-r q") 'gdscript-godot-run-current-scene-debug)
(define-key map (kbd "C-c C-r e") 'gdscript-godot-edit-current-scene)
(define-key map (kbd "C-c C-r x") 'gdscript-godot-run-current-script)
@@ -85,11 +98,11 @@
(define-key map (kbd "C-c C-d C-d d") 'gdscript-debug-display-stack-dump-buffer)
(define-key map (kbd "C-c C-d C-d b") 'gdscript-debug-display-breakpoint-buffer)
(define-key map (kbd "C-c C-d C-d i") 'gdscript-debug-display-inspector-buffer)
(define-key map (kbd "C-c C-d b") 'gdscript-debug-add-breakpoint)
(define-key map (kbd "C-c C-d r") 'gdscript-debug-remove-breakpoint)
(define-key map (kbd "<f9>") 'gdscript-debug-toggle-breakpoint)
(define-key map (kbd "C-c C-d q") 'gdscript-debug-make-server)
(define-key map (kbd "C-c C-d n") 'gdscript-debug-next)
(define-key map (kbd "C-c C-d c") 'gdscript-debug-continue)
(define-key map (kbd "<f7>") 'gdscript-debug-continue)
(define-key map (kbd "C-c C-d s") 'gdscript-debug-step)
;; Debugger Hydra
(define-key map (kbd "C-c n") 'gdscript-debug-hydra)
@@ -119,6 +132,22 @@ the last command event was a string delimiter."
(save-excursion
(insert (make-string 2 last-command-event)))))
(defun gdscript-mark-defun ()
"GDScript-specific version of `mark-defun'.
Put mark at end of this defun, point at beginning.
The defun marked is the one that contains point or follows point.
If the mark is active, it marks the next defun after the one
already marked."
(interactive)
(if (use-region-p)
(gdscript-nav-forward-defun)
(save-excursion
(gdscript-nav-backward-defun)
(set-mark (point))))
(gdscript-nav-end-of-defun))
;;;###autoload
(define-derived-mode gdscript-mode prog-mode "gdscript"
"Major mode for editing Godot GDScript files."

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com
@@ -33,8 +33,6 @@
(require 'gdscript-utils)
(defvar gdscript-project--script-list nil)
(defun gdscript-project--current-buffer-scene ()
"Return the name of current scene.
@@ -64,51 +62,32 @@ If current buffer is not visiting script file return nil."
(when (re-search-forward "^extends SceneTree\\|^extends MainLoop" nil t)
(file-relative-name buffer-file-name (gdscript-util--find-project-configuration-file))))))
(defun gdscript-project--select-script ()
(defun gdscript-project--select-script (script-list)
"Find all script files and let user choose one."
(let ((hydra-open gdscript-hydra--open))
(when hydra-open (gdscript-hydra--menu/nil))
(unwind-protect
(let* ((prompt (format "Buffer %s is not script file, select script to run" (buffer-name)))
(script-name (gdscript-util--read gdscript-project--script-list prompt)))
(when script-name (gdscript-godot--run-script script-name)))
(script-name (gdscript-util--read script-list prompt)))
(when script-name
(string-match "^\\(.*.gd\\):" script-name)
(gdscript-godot--run-script (match-string 1 script-name))))
(when hydra-open (gdscript-hydra--menu/body)))))
(defun gdscript-project--ag-cleanup ()
"Clean after ag search.
Try to leave Emacs as it was before ag search was launched."
(remove-hook 'ag-search-finished-hook #'gdscript-project--ag-find-next-script)
(let* ((ag-buffer (current-buffer))
(ag-window (get-buffer-window ag-buffer))
(prev-buffer (window-prev-buffers ag-window)))
(if prev-buffer (kill-buffer ag-buffer)
(delete-window ag-window)
(kill-buffer ag-buffer))))
(defun gdscript-project--ag-find-next-script ()
"Find next script file in ag buffer."
(let ((pos (next-single-property-change (point) 'compilation-message))
(comp-mes (get-text-property (point) 'compilation-message)))
(when comp-mes
(let ((file-name (caar (compilation--loc->file-struct (compilation--message->loc comp-mes)))))
(push file-name gdscript-project--script-list)))
(if pos (progn (goto-char pos)
(gdscript-project--ag-find-next-script))
(gdscript-project--ag-cleanup)
(with-current-buffer (window-buffer (selected-window))
(gdscript-project--select-script)))))
(defun gdscript-project--get-all-scripts ()
"Find all script files and let user choose one.
Since detection of script files require inspection of file contents,
this use ag for performance."
(if (not (featurep 'ag))
(error (format "Buffer %s is no script file. To see all available scripts in current project install package 'ag'." (buffer-name)))
(ag-project-regexp "^extends SceneTree|^extends MainLoop")
(setq gdscript-project--script-list nil)
(add-hook 'ag-search-finished-hook #'gdscript-project--ag-find-next-script)))
(if (executable-find "ag")
(let ((default-directory (vc-git-root default-directory)))
(with-temp-buffer
(call-process "ag" nil (current-buffer) nil "--vimgrep" "-s" "^extends SceneTree|^extends MainLoop")
(let ((available-standalone-scripts (split-string (buffer-string) "\n" t)))
(if (null available-standalone-scripts)
(message "No standalone script found. Look at https://docs.godotengine.org/en/stable/getting_started/editor/command_line_tutorial.html#running-a-script for details.")
(gdscript-project--select-script available-standalone-scripts)))))
(error (format "Buffer %s is no script file. To see all available scripts install 'ag' executable." (buffer-name)))))
(provide 'gdscript-project)

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest and contributors
;;
;; Author: Josef Vlach <vlach.josef@gmail.com>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 1.0.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

244
gdscript-ts-mode.el Normal file
View File

@@ -0,0 +1,244 @@
;;; gdscript-ts-mode.el --- Summary -*- lexical-binding: t -*-
;; Copyright (C) 2023 GDQuest and contributors
;; Author: xiliuya <xiliuya@aliyun.com>
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Maintainer: xiliuya <xiliuya@aliyun.com>
;; Created: 2023-05-22 19:14:43
;; Keywords: languages
;; Package-Requires: ((emacs "26.3"))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Tree-sitter mode for Gdscript.(Refer to python-ts-mode)
;; That supports the use tree-sitter for font-lock, imenu, indentation,
;; and navigation of Gdscript files.
;;
;;; Code:
(when (version< "29" emacs-version)
(require 'treesit))
;;; Imenu
(defvar gdscript-ts-imenu-format-item-label-function
'gdscript-ts-imenu-format-item-label
"Imenu function used to format an item label.
It must be a function with two arguments: TYPE and NAME.")
(defvar gdscript-ts-imenu-format-parent-item-label-function
'gdscript-ts-imenu-format-parent-item-label
"Imenu function used to format a parent item label.
It must be a function with two arguments: TYPE and NAME.")
(defvar gdscript-ts-imenu-format-parent-item-jump-label-function
'gdscript-ts-imenu-format-parent-item-jump-label
"Imenu function used to format a parent jump item label.
It must be a function with two arguments: TYPE and NAME.")
(defun gdscript-ts-imenu-format-item-label (type name)
"Return Imenu label for single node using TYPE and NAME."
(format "%s (%s)" name type))
(defun gdscript-ts-imenu-format-parent-item-label (type name)
"Return Imenu label for parent node using TYPE and NAME."
(format "%s..." (gdscript-ts-imenu-format-item-label type name)))
(defun gdscript-ts-imenu-format-parent-item-jump-label (type _name)
"Return Imenu label for parent node jump using TYPE and NAME."
(if (string= type "class")
"*class definition*"
"*function definition*"))
;;; Keywords
(defvar gdscript-ts--treesit-keywords '("and" "as" "break" "class" "class_name"
"const" "continue" "elif" "else" "enum" "export" "extends" "for" "func" "if" "in" "is"
"master" "match" "not" "onready" "or" "pass" "puppet" "remote" "remotesync" "return" "setget" "signal"
"var" "while"))
;;; Setting
(defvar gdscript-ts--treesit-settings
(treesit-font-lock-rules
:language 'gdscript
:feature 'comment
'((comment) @font-lock-comment-face)
:language 'gdscript
:feature 'definition
'((function_definition (name) @font-lock-function-name-face)
(class_definition
(name) @font-lock-function-name-face)
(parameters (identifier) @font-lock-variable-name-face))
:language 'gdscript
:feature 'keyword
`(([,@gdscript-ts--treesit-keywords] @font-lock-keyword-face)
([(false) (true)] @font-lock-keyword-face))
:language 'gdscript
:feature 'string
'((string) @font-lock-string-face)
:language 'gdscript
:feature 'type
'(((type) @font-lock-type-face)
(get_node) @font-lock-type-face)
:feature 'function
:language 'gdscript
'((call (identifier) @font-lock-function-call-face)
(attribute_call (identifier) @font-lock-function-call-face))
:language 'gdscript
:feature 'variable
'((_ (name) @font-lock-variable-name-face))
:feature 'number
:language 'gdscript
'(([(integer) (float)] @font-lock-number-face))
:feature 'property
:language 'gdscript
'((attribute (identifier) (identifier) @font-lock-property-use-face))
:feature 'operator
:language 'gdscript
`(["+" "-" "*" "/" "^" ">" "<" "="] @font-lock-operator-face)))
;;; Funtion
(defun gdscript-ts--treesit-defun-name (node)
"Return the defun name of NODE."
(treesit-node-text (treesit-search-subtree node "^name$" nil t) t))
(defun gdscript-ts--imenu-treesit-create-index-1 (node)
"Given a sparse tree, create an imenu alist.
NODE is the root node of the tree returned by
`treesit-induce-sparse-tree' (not a tree-sitter node, its car is
a tree-sitter node). Walk that tree and return an imenu alist.
Return a list of ENTRY where
ENTRY := (NAME . MARKER)
| (NAME . ((JUMP-LABEL . MARKER)
ENTRY
...)
NAME is the function/class's name, JUMP-LABEL is like \"*function
definition*\"."
(let* ((ts-node (car node))
(children (cdr node))
(subtrees (mapcan #'gdscript-ts--imenu-treesit-create-index-1
children))
(type (pcase (treesit-node-type ts-node)
("function_definition" 'def)
("export_variable_statement" 'e-var)
("onready_variable_statement" 'o-var)
("variable_statement" 'var)
("class_definition" 'class)))
;; The root of the tree could have a nil ts-node.
(name (when ts-node
(or (treesit-defun-name ts-node)
"Anonymous")))
(marker (when ts-node
(set-marker (make-marker)
(treesit-node-start ts-node)))))
(cond
((null ts-node)
subtrees)
(subtrees
(let ((parent-label
(funcall gdscript-ts-imenu-format-parent-item-label-function
type name))
(jump-label
(funcall
gdscript-ts-imenu-format-parent-item-jump-label-function
type name)))
`((,parent-label
,(cons jump-label marker)
,@subtrees))))
(t (let ((label
(funcall gdscript-ts-imenu-format-item-label-function
type name)))
(list (cons label marker)))))))
(defun gdscript-ts-imenu-treesit-create-index (&optional node)
"Return tree Imenu alist for the current Gdscript buffer.
Change `gdscript-ts-imenu-format-item-label-function',
`gdscript-ts-imenu-format-parent-item-label-function',
`gdscript-ts-imenu-format-parent-item-jump-label-function' to
customize how labels are formatted.
NODE is the root node of the subtree you want to build an index
of. If nil, use the root node of the whole parse tree.
Similar to `gdscript-imenu-create-index' but use tree-sitter."
(let* ((node (or node (treesit-buffer-root-node 'gdscript)))
(tree (treesit-induce-sparse-tree
node
(rx (or (seq bol
(or "onready_" "export_" "")
"variable_statement"
eol)
(seq bol
(or "function" "class")
"_definition"
eol)))
nil 1000)))
(gdscript-ts--imenu-treesit-create-index-1 tree)))
;;;###autoload
(define-derived-mode gdscript-ts-mode gdscript-mode "Gdscript"
"Major mode for editing gdscript files, using tree-sitter library.
\\{gdscript-ts-mode-map}"
:syntax-table gdscript-mode-syntax-table
(when (treesit-ready-p 'gdscript)
(treesit-parser-create 'gdscript)
(setq-local treesit-font-lock-feature-list
'(( comment definition)
( keyword string type)
( function variable number property operator)))
(setq-local treesit-font-lock-settings gdscript-ts--treesit-settings)
;;; TODO: create-imenu
(setq-local imenu-create-index-function
#'gdscript-ts-imenu-treesit-create-index)
(setq-local treesit-defun-type-regexp (rx (seq bol
(or "function" "class")
"_definition"
eol)))
(setq-local treesit-defun-name-function
#'gdscript-ts--treesit-defun-name)
(treesit-major-mode-setup)
(add-to-list 'auto-mode-alist '("\\.gd\\'" . gdscript-ts-mode))
(add-to-list 'interpreter-mode-alist '("gdscript[0-9.]*" . gdscript-ts-mode))))
(provide 'gdscript-ts-mode)
;;; gdscript-ts-mode.el ends here

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2020 GDQuest
;; Author: Nathan Lovato <nathan@gdquest.com>, Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/GDQuest/emacs-gdscript-mode/
;; URL: https://github.com/godotengine/emacs-gdscript-mode/
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.3"))
;; Maintainer: nathan@gdquest.com

1090
makem.sh

File diff suppressed because it is too large Load Diff