(defun js-fix-spacing-line ()
(interactive)
(let ((current (char-after))
(next (char-after 1))
(old-point (point))
(postfix)
(difference 0))
(labels
((incf-dif
()
(when (< 0 (+ difference (- old-point (point))))
(incf difference))
(insert " "))
(js-face
(&optional (pos (point)))
(get-char-property pos 'face)))
(beginning-of-line)
(while (not (eolp))
(setf current (char-after (1- (point)))
next (char-after))
(cond
((or (char-equal current ?\ )
(char-equal current ?\t)
(char-equal next ?\ )
(char-equal next ?\t)))
((and (equal (js-face (1- (point))) 'font-lock-string-face)
(equal (js-face) 'font-lock-string-face)))
((and (equal (js-face (1- (point))) 'font-lock-comment-face)
(equal (js-face) 'font-lock-comment-face)))
((and (equal (js-face (1- (point))) 'font-lock-keyword-face)
(not (equal (js-face)
'font-lock-keyword-face))
(not (position current " \t")))
(incf-dif))
((position next "=/|&%?><*^:}")
(when (or (not (position current "=!&|*+-^><")) postfix)
(setf postfix nil)
(incf-dif)))
((position current "?:,{});,")
(unless (char-equal next ?\;)
(unless (and (char-equal current ?})
(or (char-equal next ?\,)
(char-equal next ?\))))
(unless (and (char-equal current ?\))
(or (char-equal next ?\))
(char-equal next ?\.)
(char-equal next ?\,)
(char-equal next ?\[)))
(incf-dif)))))
((char-equal current ?=)
(unless (position next "=")
(incf-dif)))
((position current "<>&|*/%^")
(unless (and (char-equal next ?=)
(and (char-equal current ?&)
(char-equal next ?&))
(and (char-equal current ?|)
(char-equal next ?|)))
(incf-dif)))
((position next "!~")
(unless (position current "([")
(incf-dif)))
((char-equal next ?+)
(cond
((char-equal current ?+))
((char-equal (char-after (1+ (point))) ?+)
(if (looking-at ".\\+\\+\\(\\sw\\|\\s_\\|\\s(\\)")
(incf-dif)
(setf postfix t)))
((char-equal (char-after (1+ (point))) ?=)
(setf postfix nil)
(incf-dif))
((looking-at "[=><?;/&%*,|:-]\\|\\s(")
(setf postfix nil)
(incf-dif))
(t (incf-dif)
(setf postfix t))))
((char-equal current ?+)
(unless (or (char-equal next ?\+) (char-equal next ?\=))
(when postfix
(incf-dif)
(setf postfix nil))))
((char-equal next ?-)
(cond
((char-equal current ?-))
((char-equal (char-after (1+ (point))) ?-)
(if (looking-at ".\\-\\-\\(\\sw\\|\\s_\\|\\s(\\)")
(incf-dif)
(setf postfix t)))
((char-equal (char-after (1+ (point))) ?=)
(setf postfix nil)
(incf-dif))
((looking-at "[=><?;/&%*,|:+]\\|\\s(")
(setf postfix nil)
(incf-dif))
(t (incf-dif)
(setf postfix t))))
((char-equal current ?-)
(unless (or (char-equal next ?\-) (char-equal next ?\=))
(when postfix
(incf-dif)
(setf postfix nil)))))
(forward-char)))
(goto-char (+ old-point difference))))
(add-hook
'js-mode-hook
(lambda ()
(local-set-key (kbd "C-x SPC") 'js-fix-spacing-line)))