mirror of
https://github.com/godotengine/emacs-gdscript-mode.git
synced 2025-12-31 21:48:34 +03:00
gdformat current/all buffers, save/gdformat all modified buffers
This commit is contained in:
@@ -156,8 +156,8 @@ The last selected option is saved for the next time you call `gdscript-godot-run
|
||||
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 q quit
|
||||
e ( ) Editor s run scene r run last g switch to *godot*
|
||||
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
|
||||
|
||||
c [ ] Visible collisions shapes
|
||||
n [ ] Visible navigation
|
||||
@@ -166,7 +166,8 @@ n [ ] Visible navigation
|
||||
### Formatting code with gdformat
|
||||
|
||||
You can call the `gdscript-format` function to format the current buffer with
|
||||
`gdformat`. This feature requires the python package `gdtoolkit` to be installed
|
||||
`gdformat`. Alternatively `gdscript-format-all` will reformat all gdscripts in
|
||||
the project. This feature requires the python package `gdtoolkit` to be installed
|
||||
and available on the system's PATH variable.
|
||||
|
||||
You can install gdtoolkit using the pip package manager from Python 3. Run this
|
||||
@@ -228,4 +229,5 @@ Code example:
|
||||
(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.
|
||||
(setq gdscript-gdformat-save-and-format t) ;; Save all buffers and format them with gdformat anytime Godot executable is run.
|
||||
```
|
||||
|
||||
111
gdscript-comint-gdformat.el
Normal file
111
gdscript-comint-gdformat.el
Normal file
@@ -0,0 +1,111 @@
|
||||
;;; gdscript-comint-gdformat.el --- gdformat mode based on comint mode -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2020 GDQuest and contributors
|
||||
;;
|
||||
;; Author: Josef Vlach <vlach.josef@gmail.com>
|
||||
;; URL: https://github.com/GDQuest/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:
|
||||
;;
|
||||
;; gdformat-mode for handling stdout and stderr from gdformat executable.
|
||||
;;
|
||||
;; It supports quick navigation from errors to file location.
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(require 'ansi-color)
|
||||
(require 'comint)
|
||||
(require 'compile)
|
||||
(require 'gdscript-customization)
|
||||
(require 'gdscript-utils)
|
||||
|
||||
(defvar gdscript-comint-gdformat--mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map
|
||||
(make-composed-keymap compilation-shell-minor-mode-map
|
||||
comint-mode-map))
|
||||
(define-key map (kbd "C-c r") 'gdscript-hydra-show)
|
||||
map)
|
||||
"Basic mode map for `gdformat-mode'.")
|
||||
|
||||
(defun gdscript-comint-gdformat--sentinel (process event)
|
||||
"Display result of formatting if gdformat PROCESS exited abnormal EVENT."
|
||||
(when (string-match "exited abnormally" event)
|
||||
(pop-to-buffer (process-buffer process))))
|
||||
|
||||
(defun gdscript-comint-gdformat--run (arguments)
|
||||
"Run gdformat in comint mode.
|
||||
|
||||
ARGUMENTS are command line arguments for gdformat executable.
|
||||
When run it will kill existing process if one exists."
|
||||
(let ((buffer-name (gdscript-util--get-gdformat-buffer-name))
|
||||
(inhibit-read-only t))
|
||||
|
||||
(when (not (executable-find gdscript-gdformat-executable))
|
||||
(error "Error: Could not find %s on PATH. Please customize the gdscript-gdformat-executable variable" gdscript-gdformat-executable))
|
||||
|
||||
(with-current-buffer (get-buffer-create buffer-name)
|
||||
(unless (derived-mode-p 'gdformat-mode)
|
||||
(gdformat-mode)
|
||||
(buffer-disable-undo))
|
||||
(erase-buffer)
|
||||
(let* ((line-length (list (format "--line-length=%s" gdscript-gdformat-line-length)))
|
||||
(buffer (comint-exec (current-buffer) buffer-name gdscript-gdformat-executable nil (append line-length arguments))))
|
||||
(set-process-sentinel (get-buffer-process buffer) 'gdscript-comint-gdformat--sentinel)
|
||||
buffer))))
|
||||
|
||||
(define-derived-mode gdformat-mode comint-mode "gdformat"
|
||||
"Major mode for gdformat.
|
||||
|
||||
\\{gdscript-comint-gdformat--mode-map}"
|
||||
(use-local-map gdscript-comint-gdformat--mode-map)
|
||||
(add-hook 'gdformat-mode-hook 'gdscript-comint-gdformat--initialize-for-comint-mode)
|
||||
(add-hook 'gdformat-mode-hook 'gdscript-comint-gdformat--initialize-for-compilation-mode))
|
||||
|
||||
(defun gdscript-comint-gdformat--initialize-for-comint-mode ()
|
||||
"Initialize buffer for comint mode support."
|
||||
(when (derived-mode-p 'comint-mode)
|
||||
(setq comint-process-echoes nil)
|
||||
(setq-local comint-buffer-maximum-size 4096)
|
||||
(setq-local comint-output-filter-functions '(ansi-color-process-output comint-postoutput-scroll-to-bottom))
|
||||
(setq ansi-color-for-comint-mode t)))
|
||||
|
||||
(defun gdscript-comint-gdformat--failed-file-name()
|
||||
"Find corresponding buffer name for error message: 'at line x col y'."
|
||||
(save-excursion
|
||||
(save-match-data
|
||||
(re-search-backward "exception during formatting of \\(.*\\)")
|
||||
(match-string-no-properties 1))))
|
||||
|
||||
(defun gdscript-comint-gdformat--initialize-for-compilation-mode ()
|
||||
"Initialize buffer for compilation mode support."
|
||||
(setq-local
|
||||
compilation-error-regexp-alist
|
||||
'(("at line \\([[:digit:]]+\\) col \\([[:digit:]]+\\)" gdscript-comint-gdformat--failed-file-name 1 2 nil nil)
|
||||
("exception during formatting of \\(.*\\)$" 1 nil nil nil 1)
|
||||
("reformatted \\(.*\\)$" 1 nil nil nil 1)))
|
||||
(setq-local compilation-mode-font-lock-keywords nil)
|
||||
(compilation-setup t))
|
||||
|
||||
(provide 'gdscript-comint-gdformat)
|
||||
;;; gdscript-comint-gdformat.el ends here
|
||||
@@ -29,13 +29,15 @@
|
||||
;;
|
||||
;; godot-mode for handling stdout and stderr from godot executable.
|
||||
;;
|
||||
;; It support quick navigation from errors to file location.
|
||||
;; It supports quick navigation from errors to file location.
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(require 'ansi-color)
|
||||
(require 'comint)
|
||||
(require 'compile)
|
||||
(require 'gdscript-customization)
|
||||
(require 'gdscript-format)
|
||||
(require 'gdscript-utils)
|
||||
|
||||
(defvar gdscript-comint--mode-map
|
||||
@@ -61,6 +63,8 @@ When run it will kill existing process if one exists."
|
||||
|
||||
;; start new godot
|
||||
(with-current-buffer (get-buffer-create buffer-name)
|
||||
(when gdscript-gdformat-save-and-format
|
||||
(gdscript-comint-gdformat--modified-buffers))
|
||||
(unless (derived-mode-p 'godot-mode)
|
||||
(godot-mode)
|
||||
(buffer-disable-undo))
|
||||
|
||||
@@ -117,6 +117,18 @@ PATH."
|
||||
"The path to the gdformat executable.
|
||||
By default, it assumes that the executable is in the system's
|
||||
PATH."
|
||||
:type 'string
|
||||
:group 'gdscript)
|
||||
|
||||
(defcustom gdscript-gdformat-line-length 100
|
||||
"How many characters per line to allow when formatting gdscript by gdformat."
|
||||
:type 'integer
|
||||
:group 'gdscript)
|
||||
|
||||
(defcustom gdscript-gdformat-save-and-format nil
|
||||
"If t, save all modified buffers and format them with gdformat.
|
||||
It happens anytime Godot executable is run. Formatting runs on background,
|
||||
so it is not slowing down Godot execution."
|
||||
:type 'boolean
|
||||
:group 'gdscript)
|
||||
|
||||
|
||||
@@ -31,6 +31,31 @@
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'gdscript-comint-gdformat)
|
||||
|
||||
(defmacro gdscript-format--save-buffer (&rest body)
|
||||
"Execute the forms in BODY if current buffer is gdscript.
|
||||
|
||||
It also activates `auto-revert-mode' and saves the buffer if is it modified."
|
||||
(declare (indent 1) (debug t))
|
||||
`(when (and (buffer-file-name)
|
||||
(string-match ".*.gd$" (buffer-file-name)))
|
||||
(unless (bound-and-true-p auto-revert-mode)
|
||||
(auto-revert-mode))
|
||||
(when (buffer-modified-p)
|
||||
(save-buffer))
|
||||
,@body))
|
||||
|
||||
(defmacro gdscript-format--with-gdscripts (gdscript-buffers &rest body)
|
||||
"Execute the forms in BODY with GDSCRIPT-BUFFERS containing all gdscript buffers currently open."
|
||||
(declare (indent 1) (debug t))
|
||||
`(progn
|
||||
(dolist (buffer (buffer-list))
|
||||
(with-current-buffer buffer
|
||||
(gdscript-format--save-buffer
|
||||
(push (buffer-file-name) ,gdscript-buffers))))
|
||||
,@body))
|
||||
|
||||
(defun gdscript-format--format-region (start end)
|
||||
"Format the region between START and END using `gdformat'."
|
||||
(let
|
||||
@@ -44,20 +69,34 @@
|
||||
(shell-command-on-region start end cmd nil nil error-buffer t)))))
|
||||
|
||||
(defun gdscript-format-region()
|
||||
"Format the selected region using `gdformat'"
|
||||
"Format the selected region using `gdformat'."
|
||||
(interactive)
|
||||
(gdscript-format--format-region
|
||||
(region-beginning) (region-end)))
|
||||
|
||||
(defun gdscript-format-buffer()
|
||||
"Format the entire current buffer using `gdformat'"
|
||||
"Format the current buffer using `gdformat'."
|
||||
(interactive)
|
||||
(let ((original-point (point))
|
||||
(original-window-pos (window-start)))
|
||||
(gdscript-format--format-region
|
||||
(point-min) (point-max))
|
||||
(goto-char original-point)
|
||||
(set-window-start (selected-window) original-window-pos)))
|
||||
(gdscript-format--save-buffer
|
||||
(gdscript-comint-gdformat--run (list (buffer-file-name)))))
|
||||
|
||||
(defun gdscript-comint-gdformat--modified-buffers ()
|
||||
"Save and format all modified buffers using `gdformat'."
|
||||
(let ((gdscript-buffers))
|
||||
(gdscript-format--with-gdscripts gdscript-buffers
|
||||
(when gdscript-buffers
|
||||
(gdscript-comint-gdformat--run gdscript-buffers)))))
|
||||
|
||||
(defun gdscript-format-all()
|
||||
"Save modified buffers and then format all gdscripts in the project."
|
||||
(interactive)
|
||||
(let ((gdscript-buffers))
|
||||
(gdscript-format--with-gdscripts gdscript-buffers
|
||||
(let* ((rl (gdscript-util--find-project-configuration-file))
|
||||
(gdscript-file-list (directory-files-recursively rl ".*.gd$" t)))
|
||||
(let ((all-gdscripts (delete-dups (append gdscript-file-list gdscript-buffers))))
|
||||
(when all-gdscripts
|
||||
(pop-to-buffer (gdscript-comint-gdformat--run all-gdscripts))))))))
|
||||
|
||||
(provide 'gdscript-format)
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
;;; Code:
|
||||
|
||||
(require 'hydra nil t)
|
||||
(require 'gdscript-format)
|
||||
(require 'gdscript-godot)
|
||||
(require 'gdscript-history)
|
||||
(require 'gdscript-utils)
|
||||
@@ -117,8 +118,8 @@ on hydra checkboxes."
|
||||
: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 _q_ quit
|
||||
_e_ (?e?) Editor _s_ run scene _r_ run last _g_ switch to *godot*
|
||||
_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
|
||||
|
||||
_c_ [?c?] Visible collisions shapes
|
||||
_n_ [?n?] Visible navigation
|
||||
@@ -146,6 +147,8 @@ _n_ [?n?] Visible navigation
|
||||
gdscript-hydra--debug t
|
||||
gdscript-hydra--editor nil) (gdscript-hydra--selected gdscript-hydra--debug-navigation))
|
||||
("g" (gdscript-hydra--open-godot-buffer) :color blue)
|
||||
("a" (gdscript-format-all))
|
||||
("b" (gdscript-format-buffer))
|
||||
("q" nil)))
|
||||
|
||||
(provide 'gdscript-hydra)
|
||||
|
||||
@@ -118,6 +118,10 @@ WARNING: the Godot project must exist for this function to work."
|
||||
"Return buffer name for godot's stdout/stderr output."
|
||||
(format "*godot - %s*" (gdscript-util--get-godot-project-name)))
|
||||
|
||||
(defun gdscript-util--get-gdformat-buffer-name ()
|
||||
"Return buffer name for godot's stdout/stderr output."
|
||||
(format "*gdformat - %s*" (gdscript-util--get-godot-project-name)))
|
||||
|
||||
(defun gdscript-util--get-godot-project-file-path-relative (file-path)
|
||||
"Return the relative path of `FILE-PATH' to Godot's configuration file."
|
||||
(concat (file-name-sans-extension
|
||||
|
||||
Reference in New Issue
Block a user