Merge pull request #72 from VlachJosef/master

Hydra gdformat current/all buffers, save/gdformat all modified buffers
This commit is contained in:
Nathan Lovato
2020-07-24 08:38:09 -06:00
committed by GitHub
7 changed files with 189 additions and 14 deletions

View File

@@ -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
View 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

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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