From 4f9109821c2160185a0ac0fcf146973e7ed267d7 Mon Sep 17 00:00:00 2001 From: John Charman <102669158+charjr@users.noreply.github.com> Date: Sat, 20 Jun 2026 07:55:57 +0100 Subject: [PATCH] Add Transient menus 3 menus currently added: - `gdscript-menu`: the main menu that other menus are accessible from. - `gdscript-menu-godot`: for anything related to the Godot executable. - `gdscript-menu-gdscript`: for anything related to GDScript. History is built-in to transient by including a unique `:history-key`. History is navigatable with `C-x p` `C-x n`. History is setup for `gdscript-menu-godot`. The other menus have no configuration options, so have no use for it. GDFormat commands are greyed out unless the executable is found. There is also the option to make it completely hidden, but that would make the commands less discoverable. I used a shorthand variable `gd//` for transient-specific code. Using a shorthand here has two advantages. 1. Concise code 2. Discourage external use of internal details. --- gdscript-menu.el | 117 +++++++++++++++++++++++++++++++++++++++++++++++ gdscript-mode.el | 1 + 2 files changed, 118 insertions(+) create mode 100644 gdscript-menu.el diff --git a/gdscript-menu.el b/gdscript-menu.el new file mode 100644 index 0000000..327bd16 --- /dev/null +++ b/gdscript-menu.el @@ -0,0 +1,117 @@ +;;; gdscript-menu.el --- Godot transient menus -*- lexical-binding: t; -*- + +;; Copyright (C) 2020-2026 GDQuest and contributors. + +;; Author: John Charman +;; Maintainer: Jen-Chieh Shen + +;; 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 . + +;;; Commentary: + +;; Discoverable menus for common tasks in Godot game development. +;; - Call `gdscript-menu' for the main entrypoint. +;; - Call `gdscript-menu-godot' for launching the Godot engine. +;; - Call `gdscript-menu-gdscript' for GDScript. + +;;; Code: + +(require 'transient) ; Built-in + +;; For gdscript-menu-godot commands +(require 'gdscript-godot) + +;; For gdscript-menu-gdscript commands +(require 'gdscript-docs) +(require 'gdscript-format) + +; To display project name all menus +(require 'gdscript-utils) + + +;; Main Menu +(transient-define-prefix gdscript-menu () + "Main menu for Godot." + ["Godot Main Menu" + :description (lambda () + (format "Godot: %s" (gdscript-util--get-godot-project-name))) + ("g" "Godot Engine" gdscript-menu-godot) + ("s" "GDScript" gdscript-menu-gdscript)]) + + +;; Godot Menu +(transient-define-prefix gdscript-menu-godot () + "Menu for launching the Godot executable." + :history-key 'gdscript-menu-godot-history + :incompatible '(("--debug" "--editor")) + ["Godot Executable" + :description (lambda () + (format "Godot Engine: %s" (gdscript-util--get-godot-project-name))) + [("" "project" gd//run-project)] + [("" "current scene" gd//run-current-scene)]] + [["Run Options" + ("-d" "stdout debugger" "--debug") + ("-e" "open in editor" "--editor") + ("-h" "headless mode" "--headless") + ("-r" "recovery mode" "--recovery-mode")] + ["Debug Options" + ("-c" "show collision shapes" "--debug-collisions") + ("-p" "show path lines" "--debug-paths") + ("-n" "show navigation polygons" "--debug-navigation") + ("-a" "show navigation avoidance" "--debug-avoidance")]]) + +(transient-define-suffix gd//run-project (prefix) + "Report the PREFIX-ARG, prefix's scope, and infix values." + (interactive "P") + (transient-save) + (let ((args (transient-args transient-current-command))) + (gdscript-comint--run + `(,@args + "--path" ,(gdscript-util--find-project-configuration-file))))) + + +(transient-define-suffix gd//run-current-scene (prefix) + "Report the PREFIX-ARG, prefix's scope, and infix values." + (interactive "P") + (transient-save) + (let ((args (transient-args transient-current-command))) + (gdscript-comint--run + `(,@args + "--scene" ,(gdscript-godot--select-scene))))) + + +;; GDScript menu +(transient-define-prefix gdscript-menu-gdscript () + "Menu for GDScript files" + ["GDScript" + :description (lambda () (format "GDScript: %s" + (gdscript-util--get-godot-project-name))) + ["Docs" + ("d" "browse" gdscript-docs-browse-api)] + ["GDFormat" + :description (lambda () (if (file-exists-p gdscript-gdformat-executable) + "GDFormat" + "GDFormat (not found)")) + :inapt-if-not (lambda () (file-exists-p gdscript-gdformat-executable)) + ("f" "buffer" gdscript-format-buffer) + ("F" "all" gdscript-format-all)]]) + + +(provide 'gdscript-menu) +;; Local Variables: +;; read-symbol-shorthands: (("gd//" . "gdscript-menu--")) +;; End: +;;; gdscript-menu.el ends here diff --git a/gdscript-mode.el b/gdscript-mode.el index b0dacbf..94a0bf5 100644 --- a/gdscript-mode.el +++ b/gdscript-mode.el @@ -36,6 +36,7 @@ (require 'gdscript-syntax) (require 'gdscript-indent-and-nav) (require 'gdscript-imenu) +(require 'gdscript-menu) (require 'gdscript-fill-paragraph) (require 'gdscript-completion) (require 'gdscript-format)