Skip to content

Commit

Permalink
Fork npm.el to bun.el, update command names an quick bun test
Browse files Browse the repository at this point in the history
  • Loading branch information
shaneikennedy committed Dec 22, 2024
1 parent 45ac45b commit 0011c20
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 427 deletions.
33 changes: 11 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,26 @@
# npm.el
[![MELPA](https://melpa.org/packages/npm-badge.svg)](https://melpa.org/#/npm)
[![MELPA Stable](https://stable.melpa.org/packages/npm-badge.svg)](https://stable.melpa.org/#/npm)
[![Actions Status](https://github.com/shaneikennedy/npm.el/workflows/check/badge.svg)](https://github.com/shaneikennedy/npm.el/actions)
[![Actions Status](https://github.com/shaneikennedy/bun.el/workflows/check/badge.svg)](https://github.com/shaneikennedy/bun.el/actions)


This is an npm client for emacs.
This is a bun.sh client for emacs.

## Important
There is another package [npm-mode](https://github.com/mojochao/npm-mode) that serves a similar purpose to this package. npm-mode offers a way to execute npm commands quickly using key-bindings whereas this package makes use of [transient.el](https://github.com/magit/transient) to offer a more graphical user experience for interacting with npm that I find to be advantageous for exploration and in general when you aren't totally familiar with npm or your current node project. Since both packages serve a similar purpose, they both define a mode called `npm-mode` and as such there would likely be conflicts if both packages were installed. **Choose the package that best fits your desired NPM workflow**.
This package makes use of [transient.el](https://github.com/magit/transient) to offer an interactive experience with bun that I find to be advantageous for exploration and in general when you aren't totally familiar with bun or your current javascript/typescript project.

## Install
This package is available on MELPA
This package is not yet available on MELPA

### Using `use-package`

`git clone [email protected]:shaneikennedy/bun.el.git /path/to/bun.el`

``` emacs-lisp
(use-package npm
:ensure t)
(use-package bun
:ensure t
:load-path "~/dev/shane/bun.el/")
```

## Usage
`M-x npm`

|![Startup screen for npm](assets/npm-startup.png "NPM startup") | ![Run screen for npm](assets/npm-run.png "NPM run") |
:----------------------------------------------------------------------:|:-------------:
![Install screen for npm](assets/npm-install.png "NPM install") | ![Update screen for npm](assets/npm-update.png "NPM update")


### Common workflows

If you use this package to run your dev server, then the default configuration in this package will kill the process every time you need to install/update a package or run a different script (aka not ideal). To keep your dev server (or any long running process) running while you run your other npm workflows with this package, you can set `npm-common-buffer-name-function` to `npm-common-create-unique-buffer-name` which will generate a unique buffer name for each of your workflows. You can set this directly with `setq` or through the cusomtimzation menu for `npm`.

`M-x bun`

As of right now this package only supports the `npm run, test, install, update, and publish` commands but I hope to add more functionality soon. If you have a command you would really like to see added here please open an issue!

NPM test uses the [emacs-jest](https://github.com/Emiller88/emacs-jest/tree/4c6ddd3304e199211f0fbdc8a5b83ccbfe1f7fcc) package by default. If you want to run your project's custom test script, for now, use npm-run and choose "test".
As of right now this package only supports the `bun run, test, install, and update` commands but I hope to add more functionality soon. If you have a command you would really like to see added here please open an issue!
87 changes: 87 additions & 0 deletions bun-common.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
;;; bun-common.el --- Run your bun workflows -*- lexical-binding: t; -*-

;; Copyright (C) 2024 Shane Kennedy

;; Author: Shane Kennedy
;; Homepage: https://github.com/shaneikennedy/bun.el
;; Keywords: tools
;; Version: 0

;; 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:
;; The common functions needed by many or all bun commands.

;;; Code:
(require 'compile)
(require 'json)
(require 'subr-x)
(require 'transient)

(defgroup bun ()
"Group for bun."
:group 'tools
:prefix "bun-")

(defconst bun-common--config-file "package.json")

(defcustom bun-common-buffer-name-function "*bun*"
"Buffer name for `bun' command, or function which return buffer name.
The function takes three arguments, ROOT, BUN-COMMAND, ARGS.
ROOT is project root directory. BUN-COMMAND is bun command string.
ARGS is list of arguments passed to bun command.
You can use `bun-common-create-unique-buffer-name' to use unique buffer name
among all sesstions."
:group 'bun
:type '(choice
(string :tag "Use same buffer through all sessions")
(const :tag "Use unique buffer name among all sessions" bun-common-create-unique-buffer-name)
function))

(defun bun-common-create-unique-buffer-name (root bun-command _args)
"Create buffer name unique to ROOT and BUN-COMMAND."
(concat "*" bun-command " in " root "*"))

(defun bun-common--generate-buffer-name-function (root bun-command args)
"Generate function which return buffer name to pass `compilation-start'.
ROOT is project root directory. BUN-COMMAND is bun command string.
ARGS is list of arguments passed to bun command.
This function uses `bun-common-buffer-name-function'."
(lambda (_)
(if (stringp bun-common-buffer-name-function)
bun-common-buffer-name-function
(funcall bun-common-buffer-name-function
root bun-command args))))

;; Common
(defun bun-common--get-prorect-dir ()
"Function to determine the file path of the project root directory."
(message (locate-dominating-file (or (buffer-file-name) default-directory)
bun-common--config-file)))

(defun bun-common--compile (bun-command &optional args)
"Generic compile command for BUN-COMMAND with ARGS functionality."
(compilation-start (string-join (list bun-command args) " ")
'bun-mode
(bun-common--generate-buffer-name-function
(bun-common--get-project-dir) bun-command args)))

(defun bun-common--arguments nil
"Arguments function for transient."
(transient-args 'bun-menu))

(provide 'bun-common)
;;; bun-common.el ends here
32 changes: 16 additions & 16 deletions npm-init.el → bun-init.el
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
;;; npm-init.el --- Run your npm workflows -*- lexical-binding: t; -*-
;;; bun-init.el --- Run your bun workflows -*- lexical-binding: t; -*-

;; Copyright (C) 2020 Shane Kennedy

;; Author: Shane Kennedy
;; Homepage: https://github.com/shaneikennedy/npm.el
;; Homepage: https://github.com/shaneikennedy/bun.el
;; Keywords: tools
;; Version: 0

Expand All @@ -24,25 +24,25 @@
;; Functions for initializing a node project.

;;; Code:
(require 'npm-common)
(require 'bun-common)

(defconst npm-init--prefix-command "npm init")
(defconst npm-init--temp-buffer ".npminit")
(defconst bun-init--prefix-command "bun init")
(defconst bun-init--temp-buffer ".buninit")

;;;###autoload
(defun npm-init ()
"Initialize a project folder as a npm project."
(interactive)
(save-excursion
(let* ((project-root-folder (read-directory-name "Project root :"))
(command npm-init--prefix-command))
(generate-new-buffer (concat project-root-folder npm-init--temp-buffer))
(set-buffer (concat project-root-folder npm-init--temp-buffer))
(defun bun-init ()
"Initialize a project folder as a bun project."
(interactive)
(save-excursion
(let* ((project-root-folder (read-directory-name "Project root :"))
(command bun-init--prefix-command))
(generate-new-buffer (concat project-root-folder bun-init--temp-buffer))
(set-buffer (concat project-root-folder bun-init--temp-buffer))
(let ((current-prefix-arg '(4)))
(setq compilation-read-command nil)
(setq compile-command command)
(call-interactively #'compile))
(kill-buffer project-root-folder))))
(kill-buffer project-root-folder))))

(provide 'npm-init)
;;; npm-init.el ends here
(provide 'bun-init)
;;; bun-init.el ends here
77 changes: 77 additions & 0 deletions bun-install.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
;;; bun-install.el --- Run your bun workflows -*- lexical-binding: t; -*-

;; Copyright (C) 2024 Shane Kennedy

;; Author: Shane Kennedy
;; Homepage: https://github.com/shaneikennedy/bun.el
;; Keywords: tools
;; Version: 0

;; 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:
;; Functions for installing bun packages.

;;; Code:
(require 'bun-common)

(transient-define-prefix bun-install-menu ()
"Open bun install transient menu pop up."
["Arguments"
("-f" "Force fetching even if copy exists on disk" "--force")
("-g" "Save as global dependency" "--global")
("-p" "Save as production dependency" "--save-prod")
("-d" "Save as development dependency" "--save-dev")
("-o" "Save as optional dependency" "--save-optional")
("-e" "Save exact version" "--save-exact")
("-n" "Do not save to package.json" "--no-save")]
[["Command"
("i" "Install new package" bun-install)
("I" "Install current packages (in package.json)" bun-install-current)]]
(interactive)
(transient-setup 'bun-install-menu))


(defconst bun-install--prefix-command "bun install")

(defun bun-install--get-install-command (package-name)
"Construct the shell command for a given PACKAGE-NAME."
(concat bun-install--prefix-command " " package-name))

(defun bun-install--choose-package ()
"Let user choose which package to install."
(interactive)
(completing-read "Type the name of the package you want to install: " ()))

(defun bun-install-menu-arguments nil
"Arguments function for transient."
(transient-args 'bun-install-menu))

(defun bun-install-current (&optional args)
"Invoke the compile mode with the install prefix-command and ARGS if provided but no packages."
(interactive)
(let ((arguments (string-join args " "))
(bun-command (bun-install--get-install-command "")))
(bun-common--compile bun-command arguments)))

;;;###autoload
(defun bun-install (&optional args)
"Invoke the compile mode with the install prefix-command and ARGS if provided."
(interactive (list (bun-install-menu-arguments)))
(let* ((arguments (string-join args " "))
(bun-command (bun-install--get-install-command (bun-install--choose-package))))
(bun-common--compile bun-command arguments)))

(provide 'bun-install)
;;; bun-install.el ends here
36 changes: 18 additions & 18 deletions npm-run.el → bun-run.el
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
;;; npm-run.el --- Run your npm workflows -*- lexical-binding: t; -*-
;;; bun-run.el --- Run your bun workflows -*- lexical-binding: t; -*-

;; Copyright (C) 2020 Shane Kennedy
;; Copyright (C) 2024 Shane Kennedy

;; Author: Shane Kennedy
;; Homepage: https://github.com/shaneikennedy/npm.el
;; Homepage: https://github.com/shaneikennedy/bun.el
;; Keywords: tools
;; Version: 0

Expand All @@ -21,32 +21,32 @@
;; along with this program. If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:
;; Functions for using npm run.
;; Functions for using bun run.

;;; Code:
(require 'npm-common)
(require 'bun-common)

(defconst npm-run--prefix-command "npm run")
(defconst bun-run--prefix-command "bun run")

(defun npm-run--get-run-command (script-name)
(defun bun-run--get-run-command (script-name)
"Construct the shell command for a given SCRIPT-NAME."
(concat npm-run--prefix-command " " script-name))
(concat bun-run--prefix-command " " script-name))

(defun npm-run--get-scripts (project-dir)
"Function to parse package.json in the PROJECT-DIR to find npm scripts."
(mapcar 'car (cdr (assoc 'scripts (json-read-file (concat project-dir npm-common--config-file))))))
(defun bun-run--get-scripts (project-dir)
"Function to parse package.json in the PROJECT-DIR to find bun scripts."
(mapcar 'car (cdr (assoc 'scripts (json-read-file (concat project-dir bun-common--config-file))))))


(defun npm-run--choose-script ()
(defun bun-run--choose-script ()
"Let user choose which script to run."
(interactive)
(completing-read "Select script from list: " (npm-run--get-scripts (npm-common--get-project-dir)) nil t))
(completing-read "Select script from list: " (bun-run--get-scripts (bun-common--get-project-dir)) nil t))

;;;###autoload
(defun npm-run (&optional _args)
(defun bun-run (&optional _args)
"Invoke the compile mode with the run prefix-command and ARGS if provided."
(interactive (list (npm-common--arguments)))
(npm-common--compile (npm-run--get-run-command (npm-run--choose-script))))
(interactive (list (bun-common--arguments)))
(bun-common--compile (bun-run--get-run-command (bun-run--choose-script))))

(provide 'npm-run)
;;; npm-run.el ends here
(provide 'bun-run)
;;; bun-run.el ends here
52 changes: 52 additions & 0 deletions bun-test.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
;;; bun-test.el --- Run your bun workflows -*- lexical-binding: t; -*-

;; Copyright (C) 2024 Shane Kennedy

;; Author: Shane Kennedy
;; Homepage: https://github.com/shaneikennedy/bun.el
;; Keywords: tools
;; Version: 0

;; 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:
;; Functions for testing bun packages.

;;; Code:
(require 'bun-common)

(transient-define-prefix bun-test-menu ()
"Open bun test transient menu pop up."
[]
[["Command"
("t" "Test current project" bun-test)]]
(interactive)
(transient-setup 'bun-test-menu))


(defconst bun-test--prefix-command "bun test")

(defun bun-test-menu-arguments nil
"Arguments function for transient."
(transient-args 'bun-test-menu))

;;;###autoload
(defun bun-test (&optional args)
"Invoke the compile mode with the test prefix-command and ARGS if provided."
(interactive (list (bun-test-menu-arguments)))
(let* ((arguments (string-join args " ")))
(bun-common--compile bun-test--prefix-command arguments)))

(provide 'bun-test)
;;; bun-test.el ends here
Loading

0 comments on commit 0011c20

Please sign in to comment.