From beac587761a480e83deb4d088824d2a41e35b832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franco=20Eus=C3=A9bio=20Garcia?= Date: Sun, 29 Mar 2020 13:57:31 -0300 Subject: [PATCH] Add commands to open and run files in Godot Closes #11 and #13. --- gdscript-customization.el | 13 +++++ gdscript-mode.el | 8 +++ gdscript-utils.el | 114 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/gdscript-customization.el b/gdscript-customization.el index d20d736..f6c5336 100644 --- a/gdscript-customization.el +++ b/gdscript-customization.el @@ -103,6 +103,19 @@ fill parens." :type 'integer :safe 'natnump) +(defcustom gdscript-godot-executable "godot" + "The path to the Godot executable. +By default, it assumes that the executable is in the system's +PATH." + :type 'string + :group 'gdscript) + +(defcustom gdscript-shell-buffer-name "*Godot*" + "Default buffer name for Godot running process." + :type 'string + :group 'gdscript + :safe 'stringp) + (provide 'gdscript-customization) ;;; gdscript-customization.el ends here diff --git a/gdscript-mode.el b/gdscript-mode.el index fef4ba9..b49fec8 100644 --- a/gdscript-mode.el +++ b/gdscript-mode.el @@ -57,6 +57,14 @@ (define-key map "\177" 'gdscript-indent-dedent-line-backspace) (define-key map (kbd "") 'gdscript-indent-dedent-line) (define-key map (kbd "\t") 'company-complete) + ;; Run in Godot. + (define-key map "\C-c\C-g" 'gdscript--run-godot-editor) + (define-key map "\C-c\C-p" 'gdscript--run-project-in-godot) + (define-key map "\C-c\C-s" 'gdscript--run-current-scene-in-godot) + (define-key map "\C-c\C-e" 'gdscript--edit-current-scene-in-godot) + (define-key map "\C-c\C-r" 'gdscript--run-current-script-in-godot) + (define-key map "\C-c\C-dp" 'gdscript--run-project-in-godot-debug-mode) + (define-key map "\C-c\C-ds" 'gdscript--run-current-scene-in-godot-debug-mode) map) "Keymap for `gdscript-mode'.") diff --git a/gdscript-utils.el b/gdscript-utils.el index ef43037..f591079 100644 --- a/gdscript-utils.el +++ b/gdscript-utils.el @@ -90,6 +90,120 @@ allowed files." (list full-file-name)))) (directory-files dir-name))))) +;;;###autoload +(defun gdscript--run-command (cmd &optional dedicated show) + "Run a Godot process. +Input and output via buffer named after +`gdscript--shell-buffer-name'. If there is a process already +running in that buffer, just switch to it. + +With argument, allows you to define CMD so you can edit the +command used to call the interpreter and define DEDICATED, so a +dedicated process for the current buffer is open. When numeric +prefix arg is other than 0 or 4 do not SHOW." + (interactive + (if current-prefix-arg + (list + (read-string "Run Godot: " (gdscript--build-shell-command)) + (y-or-n-p "Make dedicated process? ") + (= (prefix-numeric-value current-prefix-arg) 4)) + (list (gdscript--build-shell-command) nil t))) + (start-process-shell-command "Godot Process" (if show + gdsript-shell-buffer-name nil) + cmd)) ; gdscript-godot-executable)) + +(defun gdscript--build-shell-command () + "Calculate the string used to execute the inferior Godot-GDScript process." + (format "%s %s" + (shell-quote-argument + (executable-find gdscript-godot-executable)) + gdscript-godot-executable-args)) + +(defun gdscript--build-shell-command (&optional path) + "Build base shell command to run Godot Engine with the +project's base PATH. If PATH is not provided, try to find it +using the current file's directory as starting point." + (let* ((project-path (or path (gdscript--find-project-configuration-path)))) + (concat gdscript-godot-executable " --path " project-path))) + +(defun gdscript--run-godot-editor () + "Run Godot Engine Editor." + (interactive) + (gdscript--run-command + (concat (gdscript--build-shell-command) " -e"))) + +(defun gdscript--run-project-in-godot () + "Run the current project in Godot Engine." + (interactive) + (let* ((project-path (gdscript--find-project-configuration-path))) + (gdscript--run-command + (gdscript--build-shell-command)))) + +(defun gdscript--run-project-in-godot-debug-mode () + "Run the current project in Godot Engine." + (interactive) + (let* ((project-path (gdscript--find-project-configuration-path))) + (gdscript--run-command + (concat (gdscript--build-shell-command) " -d")))) + +(defun gdscript--run-current-scene-in-godot () + "Run the current script file in Godot Engine." + (interactive) + (gdscript--run-command + (concat (gdscript--build-shell-command) " " + (gdscript--get-file-relative-path-to-project buffer-file-name) ".tscn"))) + +(defun gdscript--run-current-scene-in-godot-debug-mode () + "Run the current script file in Godot Engine." + (interactive) + (gdscript--run-command + (concat (gdscript--build-shell-command) " -d " + (gdscript--get-file-relative-path-to-project buffer-file-name) ".tscn"))) + +(defun gdscript--edit-current-scene-in-godot () + "Run the current script file in Godot Engine." + (interactive) + (gdscript--run-command + (concat (gdscript--build-shell-command) " -e " + (gdscript--get-file-relative-path-to-project buffer-file-name) ".tscn"))) + +(defun gdscript--run-current-script-in-godot () + "Run the current script file in Godot Engine. + +For this to work, the script must inherit either from +\"SceneTree\" or \"MainLoop\"." + (interactive) + (gdscript--run-command + (concat (gdscript--build-shell-command) " -s " (file-relative-name buffer-file-name)))) + +(defun gdscript--find-project-configuration-path (&optional path) + "Return the path where Godot's configuration File (\"project.godot\") is stored. + +If PATH is given, starts searching by it. Otherwise, the search +starts by the current buffer path." + ;; This assumes that the project does exist (i.e. it was created before the + ;; call). The function will fail if the project is not found. + (let ((base-path (or path default-directory))) + (locate-dominating-file base-path + (lambda (parent) + (directory-files parent t "project.godot"))))) + +(defun gdscript--get-project-name () + "Retrieve the project name from Godot's configuration file." + (with-temp-buffer + (insert-file-contents (concat (gdscript--find-project-configuration-path) "project.godot")) + (goto-char (point-min)) + (if (re-search-forward "config/name=\"\\([^\"]*\\)\"" nil t) + (match-string 1) + (error "Could not find the name of the project")))) + +(defun gdscript--get-file-relative-path-to-project (file-path) + "Return the relative path of `file-path' to Godot's configuration file." + (concat (gdscript--build-shell-command) " -d " + (file-name-sans-extension + (file-relative-name file-path + (gdscript--find-project-configuration-path))))) + (provide 'gdscript-utils) ;;; gdscript-utils.el ends here