From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Edward O'Connor Newsgroups: gmane.emacs.devel Subject: Re: including javascript/ecmascript mode Date: Wed, 18 Jan 2006 09:05:23 -0800 Organization: Church of Emacs Message-ID: References: <878xtkghxj.fsf-monnier+emacs@gnu.org> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1137615554 21728 80.91.229.2 (18 Jan 2006 20:19:14 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 18 Jan 2006 20:19:14 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Jan 18 21:19:11 2006 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1EzJls-0007zC-FS for ged-emacs-devel@m.gmane.org; Wed, 18 Jan 2006 21:19:09 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1EzJoG-00029A-8f for ged-emacs-devel@m.gmane.org; Wed, 18 Jan 2006 15:21:36 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1EzGrR-0007yL-EK for emacs-devel@gnu.org; Wed, 18 Jan 2006 12:12:41 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1EzGrO-0007xD-59 for emacs-devel@gnu.org; Wed, 18 Jan 2006 12:12:40 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1EzGrM-0007we-Ou for emacs-devel@gnu.org; Wed, 18 Jan 2006 12:12:37 -0500 Original-Received: from [80.91.229.2] (helo=ciao.gmane.org) by monty-python.gnu.org with esmtp (TLS-1.0:RSA_AES_128_CBC_SHA:16) (Exim 4.34) id 1EzGvE-0000iL-C2 for emacs-devel@gnu.org; Wed, 18 Jan 2006 12:16:37 -0500 Original-Received: from list by ciao.gmane.org with local (Exim 4.43) id 1EzGlG-0007ls-BA for emacs-devel@gnu.org; Wed, 18 Jan 2006 18:06:19 +0100 Original-Received: from rrcs-67-52-157-90.west.biz.rr.com ([67.52.157.90]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 18 Jan 2006 18:06:18 +0100 Original-Received: from hober0 by rrcs-67-52-157-90.west.biz.rr.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 18 Jan 2006 18:06:18 +0100 X-Injected-Via-Gmane: http://gmane.org/ Original-To: emacs-devel@gnu.org Original-Lines: 359 Original-X-Complaints-To: usenet@sea.gmane.org X-Gmane-NNTP-Posting-Host: rrcs-67-52-157-90.west.biz.rr.com Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAHlBMVEX47PoBAAegiLwiH1N IQYI0M4iMeKYBAAYGBBGqm9JF4g0mAAACYElEQVR4nGWTsY/aMBTGLXoLo8WQjNVrFJXxzviUbig JEcy5SNft5LhRGT3RNecUuRuiCMn/bZ+dhHDqJ2SZ7+f3nt/DEMOcqv9E9AdQTsD7fPw6hRIz+iw xxuhbMBn3SUtRofk95CTa9D49UIWiRvt4TnTiNmUbHIIDykUxdwm8lTvQUmergwoCpXR/qwojXqk 7jTEK1xANXhKOgD8eRmHggrt2CNKKtfcAU3EHkCbB5OJn4Ws40Prco6jhAyiDoSyeTrAb1gNe+dI eKNVlpvXNE5+pT6HUIjEi24a8B6XvjSrd0rCon5vCDwX7eA2wvV9bqrPWdCAFZBtfA0tQRWmRsE6 uZCMA6qYHbRDg6I5RlxVSFNCISG56QB3oIBNSRKL+JuLMg9LZlGqIUhCFlH9m8FN74GxFQwEFxKm crWYQJQ680v43TSEGEDArAWLJPVAObN8BHDghhrwcI1RYH2GSLMfiKnzWd6DGx4DvwNc41mIC0QQ WqzgXH0HV+kvVoohvIB5AaHRSyCZHyzawtOd4SBUyXR9lxOb2RB7Sz4T0AB8zY/smvWzRIrN0OQL GcsbW8zf7dY1gfsIlZm66JUsdOK3ljjjNCbnoHuxq9jQnb+TkAa6XY0XyJmf7C1uRwfbk4b0m1tr 8+zljb+ROD0+xA9f4umHP9+CTAAesjfGPWNyBvzCAc5ax/I40CFJPvkQrC/vRP+NsiC58LpGKfWH 7Ppy/JMY8ObK0AJfTRUDTz5eQxHS2VxPlG1697N0ee4qSbjeQ64bjc94Nhex1b+2N5Hn1MoJJwlp pf1Rr7/8DXitGHanPc2gAAAAASUVORK5CYII= X-Attribution: Ted User-Agent: Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.50 (darwin) Cancel-Lock: sha1:3bgfzVL/RBQoUDyRMnA34zti6wM= X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:49236 Archived-At: --=-=-= Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Mathias Dahl wrote: > When speaking about modes, how about adding a *real* (not the one in > generic-x) ecmascript/javascript-mode too? Coding javascript is not > likely to be less common in the near future. Including a Javascript mode would be really awesome. FWIW, I compared the various existing Javascript modes not too long ago: http://emacsen.org/2005/09/26-javascript I concluded that Karl Landström's javascript.el is the nicest one out there. You can download it from his website here: http://web.comhem.se/~u83406637/javascript-mode/javascript.el I've also attached it for convenience. Hopefully he's already filed (or is willing to file) Emacs papers! :) Ted -- Edward O'Connor hober0@gmail.com Ense petit placidam sub libertate quietem. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=javascript.el Content-Transfer-Encoding: quoted-printable Content-Description: Karl =?iso-8859-1?Q?Landstr=F6m's?= javascript.el ;;; javascript.el --- Major mode for editing JavaScript source code ;; Copyright (C) 2005 Karl Landstr=C3=B6m ;; Author: Karl Landstr=C3=B6m ;; Maintainer: Karl Landstr=C3=B6m ;; Version: 1.0 ;; Keywords: languages, oop ;; This file 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 2, or (at your option) ;; any later version. ;; This file 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 GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; Installation: ;;=20 ;; Put this file in a folder where Emacs can find it. On GNU/Linux ;; it's usually /usr/local/share/emacs/site-lisp/ and on Windows it's ;; something like "C:\Program Files\Emacs\site-lisp". To ;; make it run slightly faster you can also compile it from Emacs (M-x ;; `emacs-lisp-byte-compile'). Then add ;;=20 ;; (add-to-list 'auto-mode-alist (cons "\\.js\\'" 'javascript-mode)) ;; (autoload 'javascript-mode "javascript" nil t) ;;=20=20=20=20 ;; to your .emacs initialization file (_emacs on Windows). ;; This mode assumes that block comments are not nested inside block ;; comments and that strings does not contain line breaks. ;;; Code: (require 'cc-mode) (defcustom js-indent-level 3 "Number of spaces for each indent step.") ;; KEYMAP (defvar javascript-mode-map nil "Keymap in JavaScript mode.") (unless javascript-mode-map (setq javascript-mode-map (make-sparse-keymap))) ;; SYNTAX TABLE AND PARSING (defvar javascript-mode-syntax-table (let ((table (make-syntax-table))) (c-populate-syntax-table table) (modify-syntax-entry ?_ "w" table) table) "Syntax table used in JavaScript mode.") (defun js-re-search-forward-inner (regexp &optional bound count) "Used by `js-re-search-forward'." (let ((parse) (saved-point (point-min))) (while (> count 0) (re-search-forward regexp bound) (setq parse (parse-partial-sexp saved-point (point))) (cond ((nth 3 parse) (re-search-forward=20 (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))=20 (save-excursion (end-of-line) (point)) t)) ((nth 7 parse) (forward-line)) ((or (nth 4 parse) (and (eq (char-before) ?\/) (eq (char-after) ?\*))) (re-search-forward "\\*/")) (t (setq count (1- count)))) (setq saved-point (point)))) (point)) (defun js-re-search-forward (regexp &optional bound noerror count) "Invokes `re-search-forward' but treats the buffer as if strings and comments have been removed." (let ((saved-point (point)) (search-expr=20 (cond ((null count) '(js-re-search-forward-inner regexp bound 1)) ((< count 0) '(js-re-search-backward-inner regexp bound (- count))) ((> count 0) '(js-re-search-forward-inner regexp bound count))))) (condition-case err (eval search-expr) (search-failed (goto-char saved-point) (unless noerror (error (error-message-string err))))))) (defun js-re-search-backward-inner (regexp &optional bound count) "Used by `js-re-search-backward'." (let ((parse) (saved-point (point-min))) (while (> count 0) (re-search-backward regexp bound) (setq parse (parse-partial-sexp saved-point (point))) (cond ((nth 3 parse) (re-search-backward (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))=20 (save-excursion (beginning-of-line) (point)) t)) ((nth 7 parse)=20 (goto-char (nth 8 parse))) ((or (nth 4 parse) (and (eq (char-before) ?/) (eq (char-after) ?*))) (re-search-backward "/\\*")) (t (setq count (1- count)))))) (point)) (defun js-re-search-backward (regexp &optional bound noerror count) "Invokes `re-search-backward' but treats the buffer as if strings and comments have been removed." (let ((saved-point (point)) (search-expr=20 (cond ((null count) '(js-re-search-backward-inner regexp bound 1)) ((< count 0) '(js-re-search-forward-inner regexp bound (- count))) ((> count 0) '(js-re-search-backward-inner regexp bound count))))) (condition-case err (eval search-expr) (search-failed (goto-char saved-point) (unless noerror (error (error-message-string err))))))) ;; INDENTATION (defun js-indent-line () (interactive) (let ((indent (save-excursion (back-to-indentation) (let ((p (parse-partial-sexp (point-min) (point))) (brace-p (looking-at "[{}]")) (continued-expr-p (looking-at "[[:punct:]]"))) (cond ;; comment ((or (nth 8 p) (looking-at "/[/*]")) (current-indentation)) ;; single statement in control statement ((save-excursion (and (js-re-search-backward=20 "^[[:blank:]]*[[:graph:]]" nil t) (looking-at=20 "^[[:blank:]]*\\<\\(for\\|if\\|else\\|while\\|do\\)\= \>") (save-excursion (null (nth 1 (parse-partial-sexp (point)=20 (point-at-eol)))))= )) (save-excursion (goto-char (match-beginning 0)) (+ (current-indentation) js-indent-level))) ;; parenthesis/braces/brackets ((nth 1 p) (save-excursion=20 (goto-char (nth 1 p)) (if (looking-at "{") (cond (brace-p=20 (current-indentation)) (continued-expr-p (+ (current-indentation) (* js-indent-level 2))) (t (+ (current-indentation) js-indent-level))) (+ (current-column) 1)))) (t 0))))) (offset (- (current-column) (current-indentation)))) (indent-line-to indent) (if (> offset 0) (forward-char offset)))) ;; FONT LOCK (defvar js-function-heading-re "^[[:blank:]]*function[[:blank:]]*\\(\\sw+\\= )") (defvar js-keywords-re (regexp-opt '("abstract" "break" "case" "catch" "class" "const" "continue" "debugger" "default" "delete" "do" "else" "enum" "export" "extends" "final" "finally" "for" "function" "goto" "if" "implements" "import" "in" "instanceof" "interface" "native" "new" "package" "private" "protected" "public" "return" "static" "super" "switch" "synchronized" "this" "throw" "throws" "transient" "try" "typeof" "var" "void" "volatile" "while" "with") 'words) "The reserved words in JavaScript.") (defvar js-basic-types-re (regexp-opt '("boolean" "byte" "char" "double" "float" "int" "long" "short" "void") 'words) "Future reserved words in JavaScript.") (defvar js-constants-re (regexp-opt '("false" "null" "true") 'words) "Future reserved words in JavaScript.") (defvar js-font-lock-keywords-1 (list=20 "\\"=20 (list js-function-heading-re 1 font-lock-function-name-face) (list "[[:punct:]][[:blank:]]*\\(/.*?/[[:word:]]*\\)" 1=20 font-lock-string-face)) "Level one font lock.") (defvar js-font-lock-keywords-2 (append js-font-lock-keywords-1 (list js-keywords-re (cons js-basic-types-re font-lock-type-face) (cons js-constants-re font-lock-constant-face)))) (defvar js-font-lock-keywords-3 (append js-font-lock-keywords-2 (list=20 (list (concat "\\\\|" js-basic-types-re "\\|"=20 js-function-heading-re) (list "\\(\\w+\\)[[:blank:]]*\\(,\\|=3D[[:blank:]]*\\(\".*?\"\\= |'.*?'\\|{.*?}\\|.*?,\\)\\|.*\\)" ;; "\\(\\w+\\)[[:blank:]]*\\([,)]\\|/[/*]\\|$\\)" nil nil '(1 font-lock-variable-name-face)))))) (defconst js-font-lock-keywords '(js-font-lock-keywords-3 js-font-lock-keywords-1 js-font-lock-keywords-2 js-font-lock-keywords-3) "See `font-lock-keywords'.") ;; IMENU (defvar js-imenu-generic-expression=20 (setq js-imenu-generic-expression (list (list nil=20 "function\\s-+\\(\\sw+\\)\\s-*(" 1))) "Regular expression matching top level procedures. Used by imenu.") ;;;###autoload (defun javascript-mode () "Major mode for editing JavaScript source code. Key bindings: \\{javascript-mode-map}" (interactive) (kill-all-local-variables) (use-local-map javascript-mode-map) (set-syntax-table javascript-mode-syntax-table) (set (make-local-variable 'indent-line-function) 'js-indent-line) (set (make-local-variable 'font-lock-defaults) (list js-font-lock-keyword= s)) ;; Imenu (setq imenu-case-fold-search nil) (set (make-local-variable 'imenu-generic-expression) js-imenu-generic-expression) (when (featurep 'newcomment) (set (make-local-variable 'comment-start) "/*") (set (make-local-variable 'comment-end) "*/") (set (make-local-variable 'comment-start-skip) "/\\*+ *") (set (make-local-variable 'comment-end-skip) " *\\*+/") (require 'advice) (defadvice comment-dwim (after inhibit-indent) "Indent new comment lines to column zero and insert only one space before a trailing comment." (when (eq major-mode 'javascript-mode) (let ((prs (parse-partial-sexp=20 (save-excursion (beginning-of-line) (point))=20 (point)))) (when (nth 4 prs) (save-excursion=20 (goto-char (nth 8 prs)) (when (looking-at "/\\*[ \t]*\\*/") (if (=3D (current-column) (current-indentation)) (indent-line-to 0) (just-one-space)))))))) =20=20=20=20 (ad-activate 'comment-dwim)) (setq major-mode 'javascript-mode) (setq mode-name "JavaScript") (run-hooks 'javascript-mode-hook)) (provide 'javascript-mode) ;;; javascript.el ends here --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --=-=-=--