Skip to content

KarimAziev/js-imports

Repository files navigation

js-imports

An Emacs package for importing symbols from JavaScript and TypeScript modules with helm and ivy (swiper) interface. Also provides jumping and some refactor actions.

./js-imports-demo.gif

Installation

Manual

Download the source code and put it wherever you like, and add the directory to the load path:

(add-to-list 'load-path "/path/to/js-imports/")

(require 'js-imports)

If you are using straight.el, then you can use a normal recipe to install:

(straight-use-package
 '(js-imports :type git :host github :repo "KarimAziev/js-imports"))

You might be using use-package with straight.el, then you can install and enable at the same time:

(use-package js-imports
  :straight (js-imports
             :type git
             :host github
             :repo "KarimAziev/js-imports"))

An example of configuration with straight and use-package.

(use-package js-imports
  :init
  (setq-default js-imports-completion-system 'ivy-completing-read)
  (setq-default js-imports-modules-default-names '(("ramda" . "R")
                                                   ("react" . "React")))
  :straight (js-imports
             :type git
             :host github
             :repo "KarimAziev/js-imports")
  :hook ((js-mode . js-imports-mode)
         (js2-mode . js-imports-mode)
         (typescript-mode . js-imports-mode)
         (web-mode . js-imports-mode)
         (js-imports-mode .
                          (lambda ()
                            (add-hook
                             'before-save-hook
                             'js-imports-transform-relative-imports-to-aliases
                             nil t))))
  :bind ((:map js-imports-mode-map
               ("C-c C-i" . js-imports)
               ("C-c C-j" . js-imports-jump-to-definition)
               ("C-c C-f" . js-imports-find-file-at-point)
               ("C-c C-." . js-imports-symbols-menu)
               ("C->" . js-imports-transform-import-path-at-point))
         (:map js-imports-file-map
               ("C->" . js-imports-select-next-alias)
               ("C-<" . js-imports-select-prev-alias))))

You can also install it with quelpa.

(quelpa '(js-imports
          :repo "KarimAziev/js-imports"
          :fetcher git
          :url "git@github.com:KarimAziev/js-imports.git"))

Usage

M-x js-imports

This command read a project file, extract exported symbols from it and ask which to import.

During file completion you can cycle beetwen relative and aliased filenames with such commands:

CommandDescriptionDefault keybinding
js-imports-select-next-aliasToggle forward aliases and relative filesC->
js-imports-select-prev-aliasToggle backward aliases and relative filesC-<

To change keybindings modify js-imports-file-map, e.g:

(require 'js-imports)
(define-key js-imports-file-map (kbd "C-]") 'js-imports-select-next-alias)
(define-key js-imports-file-map (kbd "C-[") 'js-imports-select-prev-alias)

Ivy specific file commands

To change keybindings modify js-imports-ivy-file-map:

CommandDescriptionDefault keybinding
js-imports-ivy-preview-file-exportsPreview expored symbols in fileC-j
js-imports-ivy-find-file-other-windowJump to file in other windowC-c M-o

Helm specific file commands:

To change keybindings modify js-imports-helm-file-map:

CommandDescriptionDefault keybinding
js-imports-helm-find-fileJump to fileC-c M-o
js-imports-helm-find-file-other-windowJump to file in other windowC-c C-o

Additional commands

js-imports-mode
Toggle minor mode. It is provide such keymap:
CommandDescriptionDefault keybinding
js-importsAdd importC-c M-i
js-imports-jump-to-definitionJump to a definition of a symbol at the pointC-c .
js-imports-symbols-menuJump to symbol in bufferC-c M-j
js-imports-find-file-at-pointFind a file under the cursor
js-imports-transform-import-path-at-pointReplace import path with alias or relative
js-imports-transform-relative-imports-to-aliasesReplace all import paths with alias or relative
js-imports-transform-relative-imports-to-aliases

For example, such statements

import { a, b } from '../fileA';
import { c, d } from './fileB';

transforms to:

import { a, b } from '@/fileA';
import { c, d } from './fileB';
js-imports-change-completion
Customize which completion system to use:
js-imports-reset-cache
Manually removes cache. It is rarely needed to use, because cache invalidation is managed automatically.
js-imports-helm-reset-sources
Resets file and symbol sources for helm. Use it if some error occured.

Setup

Aliases

There are two ways to configure file aliases:

  • automatically with TSConfig file (tsconfig.json or jsconfig.json):

No setup is needed if a project root directory contains either tsconfig.json or jsconfig.json with configured paths and baseUrl in the compilerOptions.

For example, with such config two aliases will be used: @ for all files in ./src directory and UI for ./src/components/UI,

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "UI/*": ["src/components/UI/*", "src/components/Layout/*"]
    }
  }
}
  • manually by customizing a variable js-imports-project-aliases:

If no tsconfig.json or jsconfig.json is found, the variable js-imports-project-aliases will be used. It is a list of aliases and associated paths.

You can specify aliases as directory local variable to use different settings per project in .dir-locals.el. For example with such config two aliases will be used: “@” for all files in “./src” directory and “UI” for “./src/components/UI”.

((nil .
      ((js-imports-project-aliases . (("@/" "src/")
                                      ("UI/" "src/components/UI/" "src/components/Layout/"))))))

Customization

  • js-imports-completion-system

Which completion system to use.

  • js-imports-project-aliases

An associated list of ((ALIAS_A . DIRECTORY_A) (ALIAS_B . DIR_B DIR_C)).

  • js-imports-tsconfig-filename

Name of tsconfig or jsconfig.

  • js-imports-helm-file-actions

Default actions for files.

  • js-imports-modules-default-names

Alist mapping module path to default and namespace import name.

  • js-imports-root-ignored-directories

A list of directories in project root to ignore.

  • js-imports-normalize-paths-functions

List of functions to use in js-imports-normalize-path.

  • js-imports-preffered-extensions

Preferred suffixes for files with different extension.

  • js-imports-node-modules-dir

Relative to project root or absolute path to node_modules directory.

  • js-imports-node-modules-priority-section-to-read

Package-json sections to retrieve candidates from node_modules.

  • js-imports-package-json-sections

Package-json sections to retrieve candidates from node_modules.

  • js-imports-helm-dependencies-number-limit

The limit for number of dependencies to display in helm sources.

  • js-imports-helm-files-number-limit

The limit for number of project files to display in helm sources.

  • js-imports-quote

Which quote to use in imports.

License

Copyright © 2020 Karim Aziiev.

Distributed under the GNU General Public License, version 3