2017-06-08 11:47:56 +02:00
|
|
|
;;; lang/javascript/autoload.el -*- lexical-binding: t; -*-
|
2017-02-19 18:57:16 -05:00
|
|
|
|
2017-03-02 18:20:46 -05:00
|
|
|
(defvar +javascript-npm-conf (make-hash-table :test 'equal))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +javascript-npm-conf (&optional project-root refresh-p)
|
|
|
|
"Retrieves an alist of this project's 'package.json'. If REFRESH-P is non-nil
|
|
|
|
ignore the cache."
|
|
|
|
(let ((project-root (or project-root (doom-project-root))))
|
|
|
|
(or (and (not refresh-p)
|
|
|
|
(gethash project-root +javascript-npm-conf))
|
|
|
|
(let ((package-file (expand-file-name "package.json" project-root)))
|
2019-06-25 21:38:16 +02:00
|
|
|
(when-let (json (and (file-exists-p package-file)
|
|
|
|
(require 'json)
|
|
|
|
(json-read-file package-file)))
|
2017-03-02 18:20:46 -05:00
|
|
|
(puthash project-root json +javascript-npm-conf))))))
|
|
|
|
|
2017-04-01 23:54:30 -04:00
|
|
|
;;;###autoload
|
|
|
|
(defun +javascript-npm-dep-p (packages &optional project-root refresh-p)
|
2019-06-25 21:38:16 +02:00
|
|
|
(when-let (data (and (bound-and-true-p +javascript-npm-mode)
|
|
|
|
(+javascript-npm-conf project-root refresh-p)))
|
2017-04-01 23:54:30 -04:00
|
|
|
(let ((deps (append (cdr (assq 'dependencies data))
|
|
|
|
(cdr (assq 'devDependencies data)))))
|
2017-04-02 23:02:50 -04:00
|
|
|
(cond ((listp packages)
|
|
|
|
(funcall (if (eq (car packages) 'and)
|
2017-06-08 11:47:56 +02:00
|
|
|
#'cl-every
|
|
|
|
#'cl-some)
|
2017-04-02 23:02:50 -04:00
|
|
|
(lambda (pkg) (assq pkg deps))
|
|
|
|
(if (listp packages) packages (list packages))))
|
|
|
|
((symbolp packages)
|
|
|
|
(assq packages deps))
|
|
|
|
(t (error "Expected a package symbol or list, got %s" packages))))))
|
2017-04-01 23:54:30 -04:00
|
|
|
|
2022-10-08 18:07:17 +02:00
|
|
|
;;;###autoload
|
|
|
|
(defun +javascript-add-npm-path-h ()
|
|
|
|
"Add node_modules/.bin to `exec-path'."
|
2023-07-25 03:52:24 +12:00
|
|
|
(when-let ((search-directory (or (doom-project-root) default-directory))
|
|
|
|
(node-modules-parent (locate-dominating-file search-directory "node_modules/"))
|
2022-10-08 18:07:17 +02:00
|
|
|
(node-modules-dir (expand-file-name "node_modules/.bin/" node-modules-parent)))
|
|
|
|
(make-local-variable 'exec-path)
|
|
|
|
(add-to-list 'exec-path node-modules-dir)
|
|
|
|
(doom-log ":lang:javascript: add %s to $PATH" (expand-file-name "node_modules/" node-modules-parent))))
|
|
|
|
|
2018-04-20 02:44:04 -04:00
|
|
|
|
|
|
|
;;
|
|
|
|
;; Commands
|
|
|
|
|
2017-03-24 15:01:03 -04:00
|
|
|
;;;###autoload
|
2019-02-18 01:56:38 -05:00
|
|
|
(defun +javascript/open-repl ()
|
2017-03-24 15:01:03 -04:00
|
|
|
"Open a Javascript REPL. Meaning either `skewer-repl', if any of the
|
|
|
|
skewer-*-mode's are enabled, or `nodejs-repl' otherwise."
|
|
|
|
(interactive)
|
|
|
|
(call-interactively
|
|
|
|
(if (and (featurep 'skewer-mode)
|
2020-05-31 22:34:42 -04:00
|
|
|
(or (bound-and-true-p skewer-mode)
|
|
|
|
(bound-and-true-p skewer-css-mode)
|
|
|
|
(bound-and-true-p skewer-html-mode)))
|
2018-04-20 02:44:04 -04:00
|
|
|
#'skewer-repl
|
2019-06-06 22:24:03 +02:00
|
|
|
#'nodejs-repl))
|
|
|
|
(current-buffer))
|
2017-03-24 15:01:03 -04:00
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +javascript/skewer-this-buffer ()
|
|
|
|
"Toggle a globalized skewer-mode, attaching an external browser (once),
|
|
|
|
initiating an internal httpd server (once) and enabling the appropriate
|
|
|
|
skewer-mode for the current buffer.
|
|
|
|
|
|
|
|
Run this for any buffer you want to skewer."
|
|
|
|
(interactive)
|
|
|
|
(when (bound-and-true-p impatient-mode)
|
|
|
|
(error "Skewer-mode isn't compatible with impatient mode"))
|
|
|
|
(require 'skewer-mode)
|
|
|
|
(unless (process-status "httpd")
|
|
|
|
(run-skewer))
|
2020-05-31 20:11:05 -04:00
|
|
|
(pcase major-mode
|
|
|
|
((or 'css-mode 'scss-mode 'less-css-mode)
|
2020-05-31 22:34:42 -04:00
|
|
|
(unless (bound-and-true-p skewer-css-mode)
|
2020-05-31 20:11:05 -04:00
|
|
|
(skewer-css-mode +1)))
|
|
|
|
((or 'web-mode 'html-mode)
|
2020-05-31 22:34:42 -04:00
|
|
|
(unless (bound-and-true-p skewer-html-mode)
|
2020-05-31 20:11:05 -04:00
|
|
|
(skewer-html-mode +1)))
|
|
|
|
('js2-mode
|
2020-05-31 22:34:42 -04:00
|
|
|
(unless (bound-and-true-p skewer-mode)
|
2020-05-31 20:11:05 -04:00
|
|
|
(skewer-mode +1)))
|
|
|
|
(_ (error "Invalid mode %s" major-mode))))
|
2017-03-24 15:01:03 -04:00
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun +javascript/skewer-cleanup ()
|
|
|
|
"Disable skewer-mode globally and disable the httpd server."
|
|
|
|
(interactive)
|
|
|
|
(when (process-status "httpd")
|
|
|
|
(httpd-stop))
|
|
|
|
(dolist (buf (buffer-list))
|
|
|
|
(with-current-buffer buf
|
2020-05-31 22:34:42 -04:00
|
|
|
(if (bound-and-true-p skewer-mode)
|
|
|
|
(skewer-mode -1))
|
|
|
|
(if (bound-and-true-p skewer-css-mode)
|
|
|
|
(skewer-css-mode -1))
|
|
|
|
(if (bound-and-true-p skewer-html-mode)
|
|
|
|
(skewer-html-mode -1)))))
|
2017-03-24 15:01:03 -04:00
|
|
|
|
2018-04-20 02:44:04 -04:00
|
|
|
|
|
|
|
;;
|
|
|
|
;; Hooks
|
|
|
|
|
2018-04-19 01:13:57 -04:00
|
|
|
;;;###autoload
|
2019-07-26 19:57:13 +02:00
|
|
|
(defun +javascript-cleanup-tide-processes-h ()
|
2018-05-09 12:49:09 +02:00
|
|
|
"Clean up dangling tsserver processes if there are no more buffers with
|
|
|
|
`tide-mode' active that belong to that server's project."
|
2018-04-19 01:13:57 -04:00
|
|
|
(when tide-mode
|
2018-05-09 12:49:09 +02:00
|
|
|
(unless (cl-loop with project-name = (tide-project-name)
|
2018-04-19 01:13:57 -04:00
|
|
|
for buf in (delq (current-buffer) (buffer-list))
|
2018-05-09 12:49:09 +02:00
|
|
|
if (and (buffer-local-value 'tide-mode buf)
|
|
|
|
(with-current-buffer buf
|
|
|
|
(string= (tide-project-name) project-name)))
|
|
|
|
return buf)
|
2018-04-19 01:13:57 -04:00
|
|
|
(kill-process (tide-current-server)))))
|
|
|
|
|
2018-04-20 02:44:04 -04:00
|
|
|
|
|
|
|
;;
|
|
|
|
;; Advice
|
|
|
|
|
2018-04-19 01:13:57 -04:00
|
|
|
;;;###autoload
|
2019-07-26 19:57:13 +02:00
|
|
|
(defun +javascript-tide-project-root-a ()
|
2018-04-19 01:13:57 -04:00
|
|
|
"Resolve to `doom-project-root' if `tide-project-root' fails."
|
|
|
|
(or tide-project-root
|
|
|
|
(or (locate-dominating-file default-directory "tsconfig.json")
|
|
|
|
(locate-dominating-file default-directory "jsconfig.json"))
|
2018-10-15 00:49:41 -04:00
|
|
|
(or (doom-project-root)
|
|
|
|
default-directory)))
|