diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e1cb4d..b853c0a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how * fix(vcpkg): Use workaround for `MODULE_NOT_FOUND` error (#187) * Add docker command (#188) * Enter docker directly when no arguments (#191) +* Add command to generate recipe (#192) ## 0.8.x > Released Mar 08, 2023 diff --git a/cmds/clean/dist.js b/cmds/clean/dist.js index 01f43765..4f6c4de9 100644 --- a/cmds/clean/dist.js +++ b/cmds/clean/dist.js @@ -23,8 +23,9 @@ exports.command = ['dist [destination]', 'distribution [destination]']; exports.desc = 'Delete dist subdirectory'; exports.builder = yargs => yargs .positional( - '[destination]', { + 'destination', { description: 'destination path/folder to clean up', + alias: 'dest', type: 'string', }); diff --git a/cmds/core/package.js b/cmds/core/package.js index c525f088..c1e7e8a3 100644 --- a/cmds/core/package.js +++ b/cmds/core/package.js @@ -23,8 +23,9 @@ exports.command = ['package [destination]']; exports.desc = 'Build a package artifact, and put it into the given destination'; exports.builder = yargs => yargs .positional( - '[destination]', { + 'destination', { description: 'destination path/folder', + alias: 'dest', type: 'string', }); diff --git a/cmds/generate/recipe.js b/cmds/generate/recipe.js new file mode 100644 index 00000000..88442cd8 --- /dev/null +++ b/cmds/generate/recipe.js @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2023 Jen-Chieh Shen + * + * 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, 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 GNU Emacs; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +"use strict"; + +exports.command = ['recipe [destination]']; +exports.desc = 'Generate recipe file'; +exports.builder = yargs => yargs + .positional( + 'destination', { + description: 'destination path/folder', + alias: 'dest', + type: 'string', + }) + .options({ + 'yes': { + description: 'assume the answer to all prompts is yes', + alias: 'y', + type: 'boolean', + group: TITLE_CMD_OPTION, + }, + }); + +exports.handler = async (argv) => { + await UTIL.e_call(argv, 'generate/recipe' + , argv.dest + , UTIL.def_flag(argv.yes, '--yes')); +}; diff --git a/docs/content/en/Getting-Started/Commands-and-options.md b/docs/content/en/Getting-Started/Commands-and-options.md index 4a7a3e44..d855670e 100644 --- a/docs/content/en/Getting-Started/Commands-and-options.md +++ b/docs/content/en/Getting-Started/Commands-and-options.md @@ -170,7 +170,7 @@ Build the package artifact. $ eask package [DESTINATION] ``` -If [DESTINATION] is not specified, it will export to the `/dist` folder +If [DESTINATION] is not specified, it will generate to the `/dist` folder by default. ## 🔍 eask compile @@ -423,6 +423,17 @@ $ eask [GLOBAL-OPTIONS] generate pkg-file [Multi-file Packages (elisp)](https://www.gnu.org/software/emacs/manual/html_node/elisp/Multi_002dfile-Packages.html#Multi_002dfile-Packages) for details. +## 🔍 eask generate recipe + +Generate recipe file. + +```sh +$ eask [GLOBAL-OPTIONS] generate recipe [DESTINATION] +``` + +If [DESTINATION] is not specified, it will generate to the `/recipes` folder +by default. + ## 🔍 eask generate license Generate LICENSE file. diff --git a/docs/content/zh-TW/Getting-Started/Commands-and-options.md b/docs/content/zh-TW/Getting-Started/Commands-and-options.md index 9841ae4c..8d557fa6 100644 --- a/docs/content/zh-TW/Getting-Started/Commands-and-options.md +++ b/docs/content/zh-TW/Getting-Started/Commands-and-options.md @@ -416,6 +416,16 @@ $ eask [GLOBAL-OPTIONS] generate pkg-file `project` 是在 `Eask` 文件中聲明的項目名稱。 有關詳細信息,請參閱 [多文件包 (elisp)](https://www.gnu.org/software/emacs/manual/html_node/elisp/Multi_002dfile-Packages.html#Multi_002dfile-Packages)。 +## 🔍 eask generate recipe + +生成 recipe 文件。 + +```sh +$ eask [GLOBAL-OPTIONS] generate recipe [DESTINATION] +``` + +如果未指定 [DESTINATION],則默認導出到 `/recipes` 文件夾。 + ## 🔍 eask generate license 生成 LICENSE 文件。 @@ -830,9 +840,9 @@ $ eask -f [COMMAND] ## 🔍 --strict -Trigger error instead of warnings. +觸發錯誤代替警告。 -For instance, in **eask compile**: +例如,在 **eask compile** 中: ```elisp (setq byte-compile-error-on-warn t) diff --git a/lisp/_prepare.el b/lisp/_prepare.el index 0bce38b0..4f5677c3 100644 --- a/lisp/_prepare.el +++ b/lisp/_prepare.el @@ -718,6 +718,9 @@ full detials." (defun eask-number-p () "Non-nil when flag is on (`-n', `--number')." (eask--flag "--number")) +(defun eask-yes-p () + "Non-nil when flag is on (`--yes')." + (eask--flag "--yes")) ;;; String (with arguments) (defun eask-output () @@ -806,7 +809,8 @@ other scripts internally. See function `eask-call'.") "--no-color" "--clean" "--json" - "--number")) + "--number" + "--yes")) "List of boolean type options.") (defconst eask--option-args @@ -837,8 +841,10 @@ Simply remove `--eask' for each option, like `--eask--strict' to `--strict'." (eask-s-replace "--eask" "" arg)) eask-argv)) -(defun eask-args () - "Get all arguments except options." +(defun eask-args (&optional index) + "Get all arguments except options + +If the optional argument INDEX is non-nil, return the element." (let ((argv (cl-remove-if (lambda (arg) (member arg eask--option-switches)) eask-argv)) (args) (skip-next)) (dolist (arg argv) @@ -846,7 +852,8 @@ Simply remove `--eask' for each option, like `--eask--strict' to `--strict'." (if (member arg eask--option-args) (setq skip-next t) (push arg args)))) - (reverse args))) + (setq args (reverse args)) + (if index (nth 0 args) args))) (defmacro eask--batch-mode (&rest body) "Execute forms BODY in batch-mode." @@ -1811,6 +1818,11 @@ variable we use to test validation." :type 'string :group 'eask) +(defcustom eask-recipe-path "recipes" + "Name of default target directory for placing recipes." + :type 'string + :group 'eask) + ;; ;;; Linter diff --git a/lisp/clean/dist.el b/lisp/clean/dist.el index b6184b33..9e08e33d 100644 --- a/lisp/clean/dist.el +++ b/lisp/clean/dist.el @@ -46,7 +46,7 @@ (- 3 deleted)))) (eask-start - (let* ((eask-dist-path (or (eask-argv 0) eask-dist-path)) + (let* ((eask-dist-path (or (eask-args 0) eask-dist-path)) (eask-dist-path (expand-file-name eask-dist-path))) (if (file-directory-p eask-dist-path) (eask--clean-dist eask-dist-path) diff --git a/lisp/core/package.el b/lisp/core/package.el index 4042b473..eb01ce8e 100644 --- a/lisp/core/package.el +++ b/lisp/core/package.el @@ -68,7 +68,7 @@ Argument VERSION is a string represent the version number of this package." (eask--packaged-file "el"))) (eask-start - (let* ((eask-dist-path (or (eask-argv 0) eask-dist-path)) + (let* ((eask-dist-path (or (eask-args 0) eask-dist-path)) (eask-dist-path (expand-file-name eask-dist-path)) (packaged)) (ignore-errors (make-directory eask-dist-path t)) diff --git a/lisp/core/recipe.el b/lisp/core/recipe.el index e27e7403..219ebf93 100644 --- a/lisp/core/recipe.el +++ b/lisp/core/recipe.el @@ -14,29 +14,34 @@ (locate-dominating-file dir "_prepare.el")) nil t)) +(defun eask--recipe-string () + "Return the recipe format in string." + (when-let ((url (eask-package-desc-url))) + (let* ((fetcher (cond ((string-match-p "github.com" url) 'github) + ((string-match-p "gitlab.com" url) 'gitlab) + (t 'git))) + (url-regex (if (eq fetcher 'github) + "http[s]://github.com/" + "http[s]://gitlab.com/")) + (repo (replace-regexp-in-string url-regex "" url)) + (name (eask-guess-package-name)) + (recipe `(,(intern name) :fetcher ,fetcher))) + (cond ((memq fetcher '(git hg)) + (nconc recipe `(:url ,url))) + ((memq fetcher '(gitlab github)) + (nconc recipe `(:repo ,repo)))) + (when eask-files + (nconc recipe `(:files ,(append '(:defaults) eask-files)))) + recipe))) + (eask-start - (if-let ((url (eask-package-desc-url))) - (let* ((fetcher (cond ((string-match-p "github.com" url) 'github) - ((string-match-p "gitlab.com" url) 'gitlab) - (t 'git))) - (url-regex (if (eq fetcher 'github) - "http[s]://github.com/" - "http[s]://gitlab.com/")) - (repo (replace-regexp-in-string url-regex "" url)) - (name (eask-guess-package-name)) - (recipe - `(,(intern name) :fetcher ,fetcher))) - (cond ((memq fetcher '(git hg)) - (nconc recipe `(:url ,url))) - ((memq fetcher '(gitlab github)) - (nconc recipe `(:repo ,repo)))) - (when eask-files - (nconc recipe `(:files ,(append '(:defaults) eask-files)))) + (if-let ((recipe (eask--recipe-string)) + (name (eask-guess-package-name))) + (progn (eask-msg "") (eask-msg "recipes/%s:" name) (eask-msg "") - (eask-msg "%s" (pp-to-string recipe)) - (eask-msg "")) + (eask-msg "%s" (pp-to-string recipe))) (eask-msg "") (eask-info "(Repository URL is required to form a recipe)") (eask-help "core/recipe"))) diff --git a/lisp/generate/recipe.el b/lisp/generate/recipe.el new file mode 100644 index 00000000..01d2f066 --- /dev/null +++ b/lisp/generate/recipe.el @@ -0,0 +1,49 @@ +;;; generate/recipe.el --- Generate recipe file -*- lexical-binding: t; -*- + +;;; Commentary: +;; +;; Command use generate recipe file, +;; +;; $ eask generate recipe [destination] +;; +;; +;; Positional options: +;; +;; [destination] destination path/folder +;; + +;;; Code: + +(let ((dir (file-name-directory (nth 1 (member "-scriptload" command-line-args))))) + (load (expand-file-name "_prepare.el" + (locate-dominating-file dir "_prepare.el")) + nil t)) + +(eask-load "core/recipe") + +;; +;;; Core + +(eask-start + (if-let ((recipe (eask--recipe-string)) + (name (eask-guess-package-name))) + (let* ((eask-recipe-path (or (eask-args 0) eask-recipe-path)) + (eask-recipe-path (expand-file-name eask-recipe-path)) + (recipe-file (expand-file-name name eask-recipe-path)) + (recipe-string (pp-to-string recipe))) + (when (or (eask-yes-p) + (yes-or-no-p (format "%s\nIs this OK? " recipe-string))) + ;; XXX: Just to fake the user input! + (when (eask-yes-p) + (eask-msg (format "%s\nIs this OK? (yes or no) yes" recipe-string))) + (ignore-errors (make-directory eask-recipe-path t)) + (with-current-buffer (find-file recipe-file) + (erase-buffer) + (insert recipe-string) + (save-buffer)) + (eask-info "(Generated in %s)" recipe-file))) + (eask-msg "") + (eask-info "(Repository URL is required to form a recipe)") + (eask-help "core/recipe"))) + +;;; generate/recipe.el ends here diff --git a/test/commands/local/run.sh b/test/commands/local/run.sh index 951fd3c9..d9b66260 100644 --- a/test/commands/local/run.sh +++ b/test/commands/local/run.sh @@ -66,6 +66,7 @@ eask eval "(progn (require 'mini.emacs.pkg.1))" # Generation eask generate autoloads eask generate pkg-file +eask generate recipe -y #eask generate license gpl-3.0 # XXX: Avoid API rate limit exceeded error eask generate ignore elisp