Overview

-*- org -*-

Jane Street Emacs utilities

Linux note: I couldn't get omake to install with FAM support
via opam or from source.  The only way it worked was via apt.

* Usage

** Normal usage at the office

Everyone should add one of the following lines to their .emacs file.

      (load "/j/office/app/emacs/prod/jane-elisp/elisp/jane/jane-defaults")
        loads libraries, sets variables according to our coding
        standards, and sets standard defaults which many users find
        useful.

      (load "/j/office/app/emacs/prod/jane-elisp/elisp/jane/jane-common")
        leaves discretionary settings to the user.

** Beta testers

Beta-testers (thank you!) should add:

      (load "/j/office/app/emacs/dev/jane-elisp/elisp/jane/jane-defaults")

or:

      (load "/j/office/app/emacs/dev/jane-elisp/elisp/jane/jane-common")

These are analogous to the above, but with the next release.

** At home

For use at home:
  - Choose a site-lisp directory S.
  - Clone the BitBucket repo into S/jane.
  - Add one of the following to .emacs:

      (load "S/jane/elisp/jane/jane-defaults")
      (load "S/jane/elisp/jane/jane-common")

[You will also need to build omake_server.exe to use Omake.compile.]

* Development

** At the office

To build omake_server.exe:

    hg clone https://bitbucket.org/seanmcl/ocaml-core-external
    cd ocaml-core-external
    hg clone ssh://hg2//hg/jane-elisp/test
    patch -p1 < test/ocaml-core-external.patch # CentOS 5 compat
    cd test # this directory
    PATH=/janelibs/ocaml-4.00.1+jane3+with-fp/bin:$PATH
    jomake -j 8 .DEFAULT runtest

You can clone ocaml-core-external with ssh://hg@bitbucket.org rather
than https://bitbucket.org after you create an account and Sean gives
you access to his repo.  See
https://confluence.atlassian.com/display/BITBUCKET/Using+the+SSH+protocol+with+bitbucket
about setting up keys.

** Opam release

Our repo for opam is  https://seanmcl@bitbucket.org/seanmcl/omake-mode.

Workflow:
- Work on omake-mode in https://seanmcl@bitbucket.org/seanmcl/js-elisp.
- When we're ready for a major release, copy from there to https://seanmcl@bitbucket.org/seanmcl/omake-mode.
- Create a new version in opam-repository/packages/omake-mode.N.N in our fork of opam-repository
  https://github.com/seanmcl/opam-repository.git
- Issue a pull request to ocamlpro


* Notes

** lexical-let is buggy in Emacs 24

;; Debugger entered--Lisp error: (wrong-type-argument keymapp [bad-lexical-ref])
;; define-key([bad-lexical-ref] "w" (lambda (&rest --cl-rest--) "Watch the project on the given line." (interactive) (apply (quote (closure ((--cl-watch-- . --watch--) (--cl-root-- . --root--) (--cl-id-- . --id--) (--cl-p-- . --p--) (p . [cl-struct-Omake\.Project [cl-struct-Omake\.Id "/mnt/local/sda1/pszilagyi/jane-elisp"] "/home/pszilagyi/local/jane-elisp/test" "~/local/jane-elisp" "jomake -j 12 .DEFAULT runtest" 1 [cl-struct-Omake\.Env nil nil nil nil nil] [cl-struct-Omake\.Env nil nil nil nil nil]]) (i . 0) t) (G459 G460 G461) (Omake\.Model\.toggle-watch (symbol-value G460)))) (quote --root--) (quote --id--) (quote --p--) --cl-rest--)))
;; (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "w" (symbol-value --cl-watch--)))) (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "k" (symbol-value --cl-kill--)))) (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "d" (symbol-value --cl-kill--)))) (let ((--cl-_-- (define-key (symbol-value ...) "l" (symbol-value --cl-goto-error--)))) (let ((--cl-_-- (define-key ... "
" ...))) (let ((--cl-fullroot-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-line-keymap-- (make-sparse-keymap))) (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "w" (symbol-value --cl-watch--)))) (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "k" (symbol-value --cl-kill--)))) (let ((--cl-_-- (define-key (symbol-value ...) "d" (symbol-value --cl-kill--)))) (let ((--cl-_-- (define-key ... "l" ...))) (let ((--cl-_-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-dired-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda ... ...))) (list (quote quote) --cl-goto-error--) (list (quote quote) --cl-kill--) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--))))) (let ((--cl-line-keymap-- (make-sparse-keymap))) (let ((--cl-_-- (define-key (symbol-value (quote --cl-line-keymap--)) "w" (symbol-value --cl-watch--)))) (let ((--cl-_-- (define-key (symbol-value ...) "k" (symbol-value --cl-kill--)))) (let ((--cl-_-- (define-key ... "d" ...))) (let ((--cl-_-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-goto-error-- (make-symbol "--goto-error--"))) (set --cl-goto-error-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda (G450 G451 G452 G453 G454) (Omake\.next-error nil ...)))) (list (quote quote) --cl-kill--) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-dired-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function ...)) (list (quote quote) --cl-goto-error--) (list (quote quote) --cl-kill--) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--))))) (let ((--cl-line-keymap-- (make-sparse-keymap))) (let ((--cl-_-- (define-key (symbol-value ...) "w" (symbol-value --cl-watch--)))) (let ((--cl-_-- (define-key ... "k" ...))) (let ((--cl-_-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-kill-- (make-symbol "--kill--"))) (set --cl-kill-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Kill the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda (G455 G456 G457 G458) (Omake\.kill-project ...)))) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-goto-error-- (make-symbol "--goto-error--"))) (set --cl-goto-error-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda ... ...))) (list (quote quote) --cl-kill--) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-dired-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list ... ...) (list ... --cl-goto-error--) (list ... --cl-kill--) (list ... --cl-watch--) (list ... --cl-root--) (list ... --cl-id--) (list ... --cl-p--) (quote --cl-rest--))))) (let ((--cl-line-keymap-- (make-sparse-keymap))) (let ((--cl-_-- (define-key ... "w" ...))) (let ((--cl-_-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-watch-- (make-symbol "--watch--"))) (set --cl-watch-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Watch the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda (G459 G460 G461) (Omake\.Model\.toggle-watch ...)))) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-kill-- (make-symbol "--kill--"))) (set --cl-kill-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Kill the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda ... ...))) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-goto-error-- (make-symbol "--goto-error--"))) (set --cl-goto-error-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function ...)) (list (quote quote) --cl-kill--) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-dired-- (list (quote lambda) (quote ...) (quote "Jump to the next error for the project on the given line.") (quote ...) (list ... ... ... ... ... ... ... ... ...)))) (let ((--cl-line-keymap-- (make-sparse-keymap))) (let ((--cl-_-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-root-- (make-symbol "--root--"))) (set --cl-root-- (Omake\.Project\.omakeroot-dir (symbol-value --cl-p--))) (let ((--cl-watch-- (make-symbol "--watch--"))) (set --cl-watch-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Watch the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function (lambda ... ...))) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-kill-- (make-symbol "--kill--"))) (set --cl-kill-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Kill the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function ...)) (list (quote quote) --cl-watch--) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-goto-error-- (make-symbol "--goto-error--"))) (set --cl-goto-error-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Jump to the next error for the project on the given line.") (quote (interactive)) (list (quote apply) (list ... ...) (list ... --cl-kill--) (list ... --cl-watch--) (list ... --cl-root--) (list ... --cl-id--) (list ... --cl-p--) (quote --cl-rest--)))) (let ((--cl-dired-- (list ... ... ... ... ...))) (let ((--cl-line-keymap-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-id-- (make-symbol "--id--"))) (set --cl-id-- (Omake\.Project\.id (symbol-value --cl-p--))) (let ((--cl-root-- (make-symbol "--root--"))) (set --cl-root-- (Omake\.Project\.omakeroot-dir (symbol-value --cl-p--))) (let ((--cl-watch-- (make-symbol "--watch--"))) (set --cl-watch-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Watch the project on the given line.") (quote (interactive)) (list (quote apply) (list (quote quote) (function ...)) (list (quote quote) --cl-root--) (list (quote quote) --cl-id--) (list (quote quote) --cl-p--) (quote --cl-rest--)))) (let ((--cl-kill-- (make-symbol "--kill--"))) (set --cl-kill-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Kill the project on the given line.") (quote (interactive)) (list (quote apply) (list ... ...) (list ... --cl-watch--) (list ... --cl-root--) (list ... --cl-id--) (list ... --cl-p--) (quote --cl-rest--)))) (let ((--cl-goto-error-- (make-symbol "--goto-error--"))) (set --cl-goto-error-- (list (quote lambda) (quote ...) (quote "Jump to the next error for the project on the given line.") (quote ...) (list ... ... ... ... ... ... ... ...))) (let ((--cl-dired-- ...)) (let (...) (let ... ...))))))))
;; (let ((--cl-p-- (make-symbol "--p--"))) (setf (symbol-value --cl-p--) p) (let ((--cl-id-- (make-symbol "--id--"))) (set --cl-id-- (Omake\.Project\.id (symbol-value --cl-p--))) (let ((--cl-root-- (make-symbol "--root--"))) (set --cl-root-- (Omake\.Project\.omakeroot-dir (symbol-value --cl-p--))) (let ((--cl-watch-- (make-symbol "--watch--"))) (set --cl-watch-- (list (quote lambda) (quote (&rest --cl-rest--)) (quote "Watch the project on the given line.") (quote (interactive)) (list (quote apply) (list ... ...) (list ... --cl-root--) (list ... --cl-id--) (list ... --cl-p--) (quote --cl-rest--)))) (let ((--cl-kill-- (make-symbol "--kill--"))) (set --cl-kill-- (list (quote lambda) (quote ...) (quote "Kill the project on the given line.") (quote ...) (list ... ... ... ... ... ... ...))) (let ((--cl-goto-error-- ...)) (set --cl-goto-error-- (list ... ... ... ... ...)) (let (...) (let ... ...))))))))
;; (lexical-let ((p p)) (lexical-let ((id (Omake\.Project\.id p))) (lexical-let ((root (Omake\.Project\.omakeroot-dir p))) (lexical-let ((watch (lambda nil "Watch the project on the given line." (interactive) (Omake\.Model\.toggle-watch id)))) (lexical-let ((kill (lambda nil "Kill the project on the given line." ... ...))) (lexical-let ((goto-error ...)) (lexical-let (...) (lexical-let ... ...))))))))
;; (lexical-let* ((p p) (id (Omake\.Project\.id p)) (root (Omake\.Project\.omakeroot-dir p)) (watch (lambda nil "Watch the project on the given line." (interactive) (Omake\.Model\.toggle-watch id))) (kill (lambda nil "Kill the project on the given line." (interactive) (Omake\.kill-project id))) (goto-error (lambda nil "Jump to the next error for the project on the given line." (interactive) (Omake\.next-error nil id))) (dired (lambda nil "Jump to the next error for the project on the given line." (interactive) (Omake\.Project_buffer\.show-dired-buffer p))) (line-keymap (make-sparse-keymap)) (_ (define-key line-keymap "w" watch)) (_ (define-key line-keymap "k" kill)) (_ (define-key line-keymap "d" kill)) (_ (define-key line-keymap "l" goto-error)) (_ (define-key line-keymap (kbd "C-m") dired)) (fullroot (expand-file-name root)) (dir (Omake\.Project\.compilation-dir-relpath p)) (watched (if (Omake\.Model\.is-watching id) "yes" "no")) (num (Omake\.Project\.num-watchers p)) (str (format "[%d] %-8s %-11d %-25s %s\n" i watched num root dir))) (propertize str (quote keymap) line-keymap (quote index) i))
;; Omake\.Project_buffer\.to-line(0 [cl-struct-Omake\.Project [cl-struct-Omake\.Id "/mnt/local/sda1/pszilagyi/jane-elisp"] "/home/pszilagyi/local/jane-elisp/test" "~/local/jane-elisp" "jomake -j 12 .DEFAULT runtest" 1 [cl-struct-Omake\.Env nil nil nil nil nil] [cl-struct-Omake\.Env nil nil nil nil nil]])
;;
;; Fortunately, in Emacs Lisp, a lambda expression is
;; self-evaluating, i.e., functions are represented as their own
;; representative S-exprs, so we can splice something together.

Avoid using it.

** Prefer `buffer-read-only' to `inhibit-read-only'

inhibit-read-only is a global variable, so trying to
dynamically bind it to allow editing in this buffer is fraught
with peril.  Using setq-style dynamic binding without some
unwind-protect also breaks in the presence of debugging and
errors, whereas ordinary dynamic binding is quit-safe.
buffer-read-only is the appropriately buffer-local variable,
and dynamically binding it will work even with lexbind,
because it's from a defvar.

** Prefer `def-edebug-spec' to `declare'
Using edebug with macros is supposed to be handled by the `declare'
specification but it doesn't work.  Perhaps it's an issue with
lexical-binding?  Anyhow, calling this manually allows edebugging.