chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Scheme development workflow


From: Felix
Subject: Re: [Chicken-users] Scheme development workflow
Date: Sun, 14 Nov 2010 16:17:00 +0100 (CET)

From: Hans Nowak <address@hidden>
Subject: [Chicken-users] Scheme development workflow
Date: Sat, 13 Nov 2010 18:18:40 -0500

> 
> Right now, when I write a program in Chicken, it looks something like
> this. I have Emacs open with a number of Scheme files loaded. I have a
> terminal window open with a csi session, and a browser window with
> tabs for Chickadee, the Chicken manual and maybe other Scheme
> resources. To try/test code, I use csi -s or -ss at the shell prompt,
> and unit tests.
> 
> From what I understand, this is not very "lispy" at all (having seen
> videos of people using Common Lisp with SLIME, etc). How do people
> here develop in Scheme?

I used to do it just like you but recently I've tried to change this
somewhat. I use CL with slime at work and even though this makes it
very easy to get tangled up in stale fasls, unsaved changes and total
utter chaos, development and testing is greatly sped up. You also want
documentation at your fingertips to reduce time for looking up
function arguments. So what I do now is write my code in a way that
makes it possible to run as much as possible in the interpreter
(Recently the new ",c" and ",f" toplevel commands have been added
which are of great help when debugging - before that compiling your
code did actually provide more information than running it
interpreted). Wrapper files and separating module content from module
declarations allow me to run code without modules which simplifies
developing interactively. A set of badly written elisp code provides
the most important things to run csi as an inferior process. I don't
use "hen", just plain "scheme" mode. I also don't use paredit, even
though I should, but it's currently too strange for me.

C-c C-l            loads the current buffer into csi
C-c C-k            compiles the current buffer and loads it
C-x C-e            eval last expression
C-c C-a            "apropos" (needs "(use apropos)" in your .csirc)
C-c C-d            run chicken-doc in other buffer for word below point
C-c C-t            run chicken-doc for user input

I also use the "system" egg now, which loads and optionally compiles
files and automatically keeps track of changes and dependencies.

This is not slime (and I wouldn't consider me an expert, so I'm not
using all its possibilities), but these few emacs helpers have made
debugging being fun again.


cheers,
felix
;;;; chicken.el - Scheme mode modified for use with CHICKEN


(require 'cmuscheme)
(require 'cl)

(define-key scheme-mode-map "\C-c\C-l" 'chicken-load-current-file)
(define-key scheme-mode-map "\C-c\C-k" 'chicken-compile-current-file)
(define-key scheme-mode-map "\C-x\C-e" 'chicken-send-last-sexp-with-info)
(define-key scheme-mode-map "\C-c\C-a" 'chicken-apropos)

(global-set-key "\C-c\C-d" 'chicken-doc)
(global-set-key "\C-c\C-t" 'chicken-toc)
(global-set-key "\C-c\C-g" 'scheme-grep-current-word)
(define-key inferior-scheme-mode-map "\C-c\C-d" 'chicken-doc)
(define-key inferior-scheme-mode-map "\C-c\C-t" 'chicken-toc)
(define-key inferior-scheme-mode-map "\C-c\C-a" 'chicken-apropos)

(defun chicken-load-current-file (&optional switch)
  (interactive "P")
  (let ((file-name (buffer-file-name)))
    (comint-check-source file-name)
    (setq chicken-prev-l/c-dir/file
          (cons (file-name-directory file-name)
                (file-name-nondirectory file-name)))
    (comint-send-string
     (scheme-proc)
     (concat "(load \"" file-name "\"\)\n"))
    (if switch
      (switch-to-scheme t)
      (message "\"%s\" loaded." file-name) ) ) )

(defun chicken-compile-current-file (&optional switch)
  (interactive "P")
  (let ((file-name (buffer-file-name)))
    (comint-check-source file-name)
    (setq chicken-prev-l/c-dir/file
          (cons (file-name-directory file-name)
                (file-name-nondirectory file-name)))
    (message "compiling \"%s\" ..." file-name)
    (comint-send-string 
     (scheme-proc) 
     (concat "(compile-file \"" file-name "\"\)\n"))
    (if switch
      (switch-to-scheme t)
      (message "\"%s\" compiled and loaded." file-name) ) ) )

(defun chicken-send-last-sexp-with-info ()
  "hacked version from cmuscheme.el"
  (interactive)
  (let* ((str (buffer-substring (save-excursion (backward-sexp) (point)) 
(point)))
         (lnbreak (position ?\n str)))
    (comint-send-string (scheme-proc) str)
    (comint-send-string 
     (scheme-proc)
     (concat 
      "(display #<<EOFEOF\n\n;;; "
      (if lnbreak 
          (substring str 0 lnbreak)
        str)
      " ...\n\nEOFEOF\n)\n"))))

(defun chicken-doc (&optional arg)
  (interactive "P")
  (let ((words
         (if current-prefix-arg
             (split-string (read-from-minibuffer "chicken-doc: ") " ")
           (list (current-word)))))
    (unless (null words)
      (run-chicken-doc words))))

(defun chicken-toc (&optional arg)
  (interactive "P")
  (let ((words
         (if current-prefix-arg
             (split-string (read-from-minibuffer "chicken-doc: ") " ")
           (list (current-word)))))
    (unless (null words)
      (run-chicken-doc (cons "-c" words)))))

(defun run-chicken-doc (args)
  (with-current-buffer (get-buffer-create "*chicken-doc*")
    (erase-buffer)
    (when (zerop (apply 'call-process "chicken-doc" nil "*chicken-doc*" t args))
      (goto-char (point-min))))
  (unless (string= "*chicken-doc*" (buffer-name (current-buffer)))
    (display-buffer "*chicken-doc*" t)))

(defun chicken-apropos ()
  (interactive)
  (let ((func (current-word)))
    (when func
      (process-send-string "*scheme*" (concat "(begin (newline) (apropos \"" 
func "\"))\n"))
      (unless (string= (buffer-name (current-buffer)) "*scheme*")
        (display-buffer "*scheme*" t)))))

(defun scheme-grep-current-word (&optional arg)
  (interactive "P")
  (let ((word (or (and (not current-prefix-arg)
                       (current-word))
                  (read-from-minibuffer 
                   (concat grep-command " <word> *.scm: ")))))
    (grep (concat grep-command " \'" word "\' " "*.scm"))))

(setq scheme-program-name "csi -:c")

(setq chicken-keyword-list
      '((receive 2)
        (match 1)
        (match-lambda 0)
        (match-lambda* 0)
        (match-let scheme-let-indent)
        (match-let* 1)
        (match-letrec 1)
        (and-let* 1)
        (declare 0)
        (cond-expand 0)
        (let-values scheme-let-indent)
        (let*-values scheme-let-indent)
        (letrec-values 1)
        (parameterize scheme-let-indent)
        (let-location 1)
        (foreign-lambda 2)
        (foreign-lambda* 2)
        (foreign-safe-lambda 2)
        (foreign-safe-lambda* 2)
        (set! 1)
        (let-optionals* 2)
        (let-optionals 2)
        (condition-case 1)
        (when 1)
        (unless 1)
        (dotimes 1)
        (use 0)
        (require-extension 0)
        (import 0)
        (with-input-from-file 1)
        (with-output-to-file 1)
        (handle-exceptions 2)
        (regex-case 1)
        (define-inline 1)
        (define-constant 1)
        (select 1)
        (module 2) ) )

(setq chicken-indent-list
      '((printf 1)
        (fprintf 2)
        (sprintf 1)))

(put 'module 'scheme-indent-function 'chicken-module-indent)

(defun chicken-module-indent (state indent-point normal-indent) 0)

(defun chicken-build-keyword-regexp (kwl)
  (let ((str "\\<\\(module\\>"))
    (dolist (kw kwl)
      (put (car kw) 'scheme-indent-hook (cadr kw))
      (setq str (concat str "\\|" (regexp-quote (symbol-name (car kw))) "\\>")))
    (concat str "\\)")))

(setq chicken-keyword-regexp
      (chicken-build-keyword-regexp chicken-keyword-list))

(dolist (e chicken-indent-list)
  (put (car e) 'scheme-indent-hook (cadr e)))

(add-hook
 'scheme-mode-hook
 (lambda ()
   (font-lock-add-keywords
    'scheme-mode
    `(("\\<\\sw+\\>:" . font-lock-constant-face) ;XXX doesn't work, yet
      ("##\\(core\\|sys\\)#\\sw+\\>" . font-lock-builtin-face)
      (,chicken-keyword-regexp . font-lock-keyword-face) 
      )
    1)))

(provide 'chicken)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]