;;; oni-js.el --- JavaScript configuration -*- lexical-binding: t; -*- ;; Copyright (C) 2019 Tom Willemse ;; Author: Tom Willemse ;; Keywords: local ;; Version: 2025.1110.160632 ;; Package-Requires: (oni-company js2-mode js2-refactor oni-flycheck fic-mode rjsx-mode prettier-js) ;; 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: ;; JavaScript configuration. ;;; Code: (require 'company) (require 'js) (require 'js2-mode) (require 'js2-refactor) (require 'whitespace) (eval-when-compile (require 'grep)) (defun oni-js-whitespace-mode () "Enable whitespace mode with only tabs showing." (setq-local whitespace-style '(face tabs)) (whitespace-mode)) (defun oni-js--auto-fill-mode () "Enable ‘auto-fill-mode’ only for comments." (setq-local comment-auto-fill-only-comments t) (auto-fill-mode)) (setq js-enabled-frameworks '(javascript)) (setq js2-include-node-externs t) (setq js2-strict-trailing-comma-warning nil) (setq js2-strict-missing-semi-warning nil) (setq js2-basic-offset 2) (add-hook 'js-mode-hook 'electric-pair-local-mode) (add-hook 'js-mode-hook 'electric-indent-local-mode) (add-hook 'js-mode-hook 'oni-js--auto-fill-mode) (add-hook 'js2-mode-hook 'company-mode) (add-hook 'js2-mode-hook 'display-fill-column-indicator-mode) (add-hook 'js2-mode-hook 'electric-pair-local-mode) (add-hook 'js2-mode-hook 'fic-mode) (add-hook 'js2-mode-hook 'flycheck-mode) (add-hook 'js2-mode-hook 'js2-refactor-mode) (add-hook 'js2-mode-hook 'oni-js--auto-fill-mode) (add-hook 'js2-mode-hook 'oni-js-whitespace-mode) (add-hook 'js2-mode-hook 'prettier-js-mode) (add-hook 'js2-mode-hook 'subword-mode) (js2r-add-keybindings-with-prefix "C-c r") ;;;###autoload (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.jsx\\'" . rjsx-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.mjs\\'" . js2-mode)) ;;;###autoload (with-eval-after-load 'grep (add-to-list 'grep-files-aliases '("js" . "*.js *.jsx *.json *.vue *.mjs"))) (defun oni-js-set-imenu-expression () (setq-local imenu-create-index-function 'imenu-default-create-index-function imenu-generic-expression (list (list nil (rx (seq bol (minimal-match (zero-or-more space)) (or (seq (optional "async ") (group-n 1 (minimal-match (one-or-more alnum))) "(" (minimal-match (zero-or-more (not ")"))) ")" (minimal-match (zero-or-more white)) "{") (seq (minimal-match (group-n 1 (one-or-more alnum))) ":" (minimal-match (zero-or-more white)) (optional "function ") "(") (seq (optional "export ") "function " (minimal-match (group-n 1 (one-or-more (any punct alnum)))) "(" (minimal-match (zero-or-more (not ")"))) ")" (minimal-match (zero-or-more space)) "{") (seq (optional "export ") (optional "const ") (minimal-match (group-n 1 (one-or-more (any punct alnum)))) (minimal-match (zero-or-more space)) "=" (minimal-match (zero-or-more space)) (optional "async") (optional "function") (minimal-match (zero-or-more space)) "(")))) 1)))) (add-hook 'js2-mode-hook #'oni-js-set-imenu-expression) (defun oni-js-guess-import-filename-at-point () (save-excursion (beginning-of-line) (when (looking-at "import") (let* ((bpos (progn (search-forward-regexp (rx (or "'" "\""))) (point))) (epos (progn (search-forward-regexp (rx (or "'" "\""))) (point))) (import-file (buffer-substring bpos (1- epos)))) (cond ((string-prefix-p "@/" import-file) (let ((file-name (expand-file-name (concat "src/" (substring import-file 2)) (project-root (project-current))))) (cond ((file-directory-p file-name) (concat file-name "/index.js")) ((null (file-name-extension file-name)) (concat file-name ".js")) (t file-name)))) ((or (string-prefix-p "../" import-file) (string-prefix-p "./" import-file)) (let ((file-name (expand-file-name (concat "src/" import-file) (project-root (project-current))))) (cond ((file-directory-p file-name) (concat file-name "/index.js")) ((null (file-name-extension file-name)) (concat file-name ".js")) (t file-name))))))))) (defun oni-js-add-ffap-function () (add-hook 'file-name-at-point-functions 'oni-js-guess-import-filename-at-point 0 t)) (add-hook 'js2-mode-hook #'oni-js-add-ffap-function) (provide 'oni-js) ;;; oni-js.el ends here