From: A Soare <alinsoar@voila.fr>
To: "Emacs Dev [emacs-devel]" <emacs-devel@gnu.org>
Subject: Re: An automaton for indenting the lisp code in linear time
Date: Tue, 1 Jul 2008 02:49:29 +0200 (CEST) [thread overview]
Message-ID: <27153496.3851311214873369561.JavaMail.www@wwinf4619> (raw)
[-- Attachment #1: Type: text/plain, Size: 362 bytes --]
What do you think about the code? Do I have any chance that the code be used?
In this case, what functions should I write? (indent-region, etc)...
I modified it a little and I send a new version.
A Soare.
____________________________________________________
Sur le mail Voila, vous pouvez personnaliser l’anti-spam ! http://mail.voila.fr
[-- Attachment #2: indent.el --]
[-- Type: application/octet-stream, Size: 8119 bytes --]
(defun lisp-indent-value ()
"
VERSION : NEW
"
(cond ((elt state 3)
;; Inside a string, don't change indentation.
nil
)
((null (cadr state))
;; outside an expression align to the left column
0
)
((null indent)
;; an empty parethesis
(1+ start-col))
((and (integerp lisp-indent-offset)
(integerp (cadr indent)))
;; indent by constant offset
(+ (cadr indent) lisp-indent-offset)
)
((looking-at "\\s<\\s<\\s<")
;; Comments that start with three semicolons or more, should
;; start at the left margin
0
)
((eq (car indent) :l)
;; indent beneath a list
(caddr indent)
)
((and (eq (car indent) :w)
(stringp (cadr indent))
(>= (length (cadr indent)) 3)
(string-equal "def" (substring (cadr indent) 0 3)))
;; indent a def-form
(+ lisp-body-indent start-col)
)
((and (eq (car indent) :w)
(wholenump (get (intern-soft (cadr indent)) 'lisp-indent-function)))
;; here there is a special form
(setq oo (or (get (intern-soft (cadr indent)) 'lisp-indent-function)
(get (intern-soft (cadr indent)) 'lisp-indent-hook)))
(if (> (length indent) (* 3 oo))
(+ lisp-body-indent start-col)
(+ (* 2 lisp-body-indent) start-col))
)
((and (eq (car indent) :w)
(get (intern-soft (cadr indent)) 'lisp-indent-hook)
nil)
;; indent defined by another function
;; not defined yet
(funcall (get (intern-soft (cadr indent)) 'lisp-indent-hook))
)
((and (equal (following-char) ?:)
nil)
;; indent of a constant symbol
;; not yed defined
(caddr indent)
)
((and (eq (car indent) :w)
(> (length indent) 3))
;; indent beneath the `indent-what-argument' parameter
(elt indent (+ 3 (1- (* 3 indent-what-argument))))
)
(t
;; the first parameter of a function call
(caddr indent))
))
(defun lisp-indent-what-argument nil
(cond ((and (eq (car indent) :w)
(stringp (cadr indent))
(>= (length (cadr indent)) 3)
(string-equal "def" (substring (cadr indent) 0 3))
(= (length indent) 9))
;; if the second parameter of defun is a list, then this list
;; is not a function call
0)
((or
(and (>= (length indent) 6)
(eq (elt indent (- (length indent ) 6)) :q))
(and (eq (car indent) :w)
(stringp (cadr indent))
(string-equal "quote" (cadr indent))))
;; a quoted list is not a function call
0
)
(t
;; for the rest, always indent beneath the first parameter of
;; the function...
1)))
(defun lisp-indent-next-state (&optional n)
(parse-partial-sexp (point) (+ (or n 1) (point)) () () state))
(defun lisp-indent-automaton (&optional end state indent-what-argument start-col)
"
an automaton to indent the lisp code
VERSION: NEW
"
(let (
indent
indent-next-line-to
)
(or end (beginning-of-line) (setq end (point)))
(or indent-what-argument
(setq indent-what-argument 0))
(or state (beginning-of-defun))
(and (null start-col) (setq start-col 0))
(catch 'STOP
(while (< (point) end)
(cond ((and (elt state 8)
(not (elt state 4)))
;; inside a string
(and (looking-at "\\s>")
(setq indent-lines (cons (lisp-indent-value) indent-lines)))
(setq state (lisp-indent-next-state))
)
((looking-at "\\s\"")
;; the start of a string
(setq indent (append indent (list :s () (current-column)))
state (lisp-indent-next-state))
)
((looking-at "\\s\(")
;; open a parenthesis
(let ((col (if indent-lines
(+ (current-column) (- (caar indent-lines) (cdar indent-lines)))
(current-column))))
(setq indent (append indent (list :l () col))
state (lisp-indent-automaton end (lisp-indent-next-state)
(lisp-indent-what-argument)
col)))
)
((looking-at "\\s\)")
;; close a parenthesis
(throw 'STOP (lisp-indent-next-state))
)
((looking-at "\\s ")
;; spaces are ignored
(while (looking-at "[[:blank:]]")
(setq state (lisp-indent-next-state)))
)
((looking-at "\\sw\\|\\s_")
;; a function or a parameter
(let* ((col (if indent-lines
(+ (current-column) (- (caar indent-lines) (cdar indent-lines)))
(current-column)))
r
(w (catch 'WORD
(while t
(setq r (concat r (string (following-char))))
(setq state (lisp-indent-next-state))
(and (not (looking-at "\\w\\|\\s_"))
(throw 'WORD r))))))
(setq indent (append indent (list :w w col))))
)
((looking-at "\\s<")
;; start of a comment
(while (not (looking-at "\\s>"))
(setq state (lisp-indent-next-state)))
)
((looking-at "\\s\'")
;; quote
(setq indent (append indent (list :q () (current-column))))
(setq state (lisp-indent-next-state))
)
((looking-at "\\s\\")
;; a special character
(setq state (lisp-indent-next-state 2))
)
((looking-at "\\s>")
;; end of line
(setq state (lisp-indent-next-state))
(while (looking-at "\\s ")
(setq state (lisp-indent-next-state)))
(setq indent-lines (cons (cons (lisp-indent-value) (current-column)) indent-lines))
)
(t
(error "oops! unknown class of syntax ! (indent failed at position %d)" (point))))))))
(defun indent-defun-example nil
"
An example how to use the automatonin for indentig a whole region
of lisp code in linear time (a function from the beginning to the point).
"
(let* (indent-lines
state
l)
(save-excursion
(lisp-indent-automaton)
(dolist (i indent-lines)
(when (consp i)
(setq l (prog2 (beginning-of-line) (point)))
(skip-chars-forward "[[:blank:]]")
(when (not (zerop (- (- l (point)) (- (cdr i) (car i)))))
(delete-region l (point))
(indent-to (car i))))
(previous-line)))))
(defun indent-line-example nil
"
An example how to indent a line of code using the automaton
"
(let* (indent-lines
state
dif
(pos (point-marker))
(l (prog2 (beginning-of-line) (point))))
(save-excursion (lisp-indent-automaton))
(if (not (consp (car indent-lines)))
nil
(setq dif
(catch 'DIF
(dolist (i (cdr indent-lines))
(and (consp i)
(throw 'DIF (- (cdr i) (car i)))))))
(skip-chars-forward "[[:blank:]]")
(when (not (zerop (- (+ (caar indent-lines) dif) (- (point) l))))
(delete-region l (point))
(indent-to (+ (caar indent-lines) dif))
(goto-char (max pos (point)))))))
next reply other threads:[~2008-07-01 0:49 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-01 0:49 A Soare [this message]
2008-07-01 1:06 ` An automaton for indenting the lisp code in linear time Lennart Borgman (gmail)
-- strict thread matches above, loose matches on Subject: below --
2008-07-04 21:14 A Soare
2008-07-01 15:28 A Soare
2008-07-01 13:59 A Soare
2008-07-01 2:24 A Soare
2008-06-30 0:41 A Soare
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=27153496.3851311214873369561.JavaMail.www@wwinf4619 \
--to=alinsoar@voila.fr \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).