Search code examples
javascriptemacsindentationauto-indent

Auto indent Javascript code in Emacs (bsd style aka Allman style)


I can't set Emacs to work with Javascript. I want Emacs makes auto indent, when I press "{" and "}". When I write code on C, it works very well. When I press "}" the parenthesis tooks its place. I'd like to see something like this:

very good styles

But I get this:

it's my problem here

I don't understand why parenthesis remain in place.

Could you tell me, what should I do to make it right, please?

I think, I need to add something to my .emacs file, aren't I?

Here is my .emacs:

(setq c-default-style "bsd" 
      c-basic-offset 4)
(setq-default c-basic-offset 4
              tab-width 4
              indent-tabs-mode nil)

(setq make-backup-files nil
      auto-save-default nil
      auto-save-list-file-name nil)


(global-set-key (kbd "RET") 'newline-and-indent)                           

(show-paren-mode t) ; Highlight expression between {}, (), []
(setq show-paren-style 'parenthesis) ; parenthesis | expression | mixed

(add-hook 'html-mode-hook
            (lambda ()
                  ;; Default indentation is usually 2 spaces, changing to 4.
                  (set (make-local-variable 'sgml-basic-offset) 2)
                  (setq tab-width 2)
            )
)

(setq font-lock-maximum-decoration
      '((html-mode . 1)))

(setq column-number-mode t)

;(electric-pair-mode t)
;(setq electric-pair-preserve-balance nil)
;(electric-indent-mode -1)


; 80 letters rule (highlight)
(setq-default
  whitespace-line-column 78
   whitespace-style       '(face lines-tail))
(add-hook 'prog-mode-hook #'whitespace-mode) ; only if I write code
(add-hook 'text-mode-hook #'whitespace-mode) ; and the other cases

; Use all c-mode settings when I code on javascript (indent, tab-width, ...)
;(add-hook 'js-mode-hook 'c-mode)

;(add-hook 'js-mode-hook #'c-default-style)

;(add-to-list 'auto-mode-alist '("\\.js\\'" . c-mode))

Solution

  • I couldn't find any built-in functions or ready-made solution, so I read emacs documentation and wrote my own emacs-lisp function. Maybe someone will need it.

    (global-set-key (kbd "RET") 'newline-and-indent)
    
    (add-hook 'js-mode-hook
        (lambda()
            (local-set-key (kbd "{")
                (lambda() (interactive)
                    (my-bsd-lparen-align)
                    (insert "{")
                )
            )
            (local-set-key (kbd "}")
                (lambda() (interactive)
                    (insert "}")
                    (indent-according-to-mode)
                    ;(c-indent-command)                                             
                )
            )
        )
    )
    
    
    (defun my-bsd-lparen-align()
        (skip-chars-forward " \t")
        (setq cur_pos (point))
        (my-line-begin)
        (setq new_pos (point))
        (goto-char cur_pos)
        (if (eq cur_pos new_pos)
            (__my-bsd-lparen-put)
        )
    )
    
    (defun my-line-begin()
        (beginning-of-line)
        (skip-chars-forward " \t")
        (current-column)
    )
    
    (defun __my-bsd-lparen-put()
        (setq init_pos (point))
        (setq cur_start (my-line-begin))
        (forward-line -1)
        (setq block_start (my-line-begin))
        (setq diff (- cur_start block_start))
        (goto-char init_pos)
        (if (>= diff 0)
            (delete-backward-char diff)
            (loop for i from 1 to (- diff) do (insert " "))
        )
    )