improved magic square bracket stuff

svn: r4496
This commit is contained in:
Robby Findler 2006-10-05 21:32:58 +00:00
parent 8ecb66ec3c
commit c1350ef9d8
3 changed files with 194 additions and 106 deletions

View File

@ -29,6 +29,23 @@
'("case-lambda" "cond" "field" "provide/contract") '("case-lambda" "cond" "field" "provide/contract")
(λ (x) (and (list? x) (andmap string? x)))) (λ (x) (and (list? x) (andmap string? x))))
(preferences:set-default 'framework:square-bracket:cond/offset
'(("case-lambda" 0)
("cond" 0)
("field" 0)
("provide/contract" 0)
("new" 1)
("case" 1)
("syntax-case" 2)
("syntax-case*" 3))
(λ (x) (and (list? x) (andmap (λ (x) (and (pair? x)
(string? (car x))
(pair? (cdr x))
(number? (cadr x))
(null? (cddr x))))
x))))
(preferences:set-default 'framework:square-bracket:letrec (preferences:set-default 'framework:square-bracket:letrec
'("let" '("let"
"let*" "let-values" "let*-values" "let*" "let-values" "let*-values"

View File

@ -13,7 +13,8 @@
(lib "thread.ss") (lib "thread.ss")
(lib "etc.ss") (lib "etc.ss")
(lib "surrogate.ss") (lib "surrogate.ss")
(lib "scheme-lexer.ss" "syntax-color")) (lib "scheme-lexer.ss" "syntax-color")
"../gui-utils.ss")
(provide scheme@) (provide scheme@)
@ -1235,94 +1236,103 @@
(set! real-char c))] (set! real-char c))]
[start-pos (send text get-start-position)] [start-pos (send text get-start-position)]
[end-pos (send text get-end-position)] [end-pos (send text get-end-position)]
[case-like-forms (preferences:get 'framework:square-bracket:case)]
[cond-like-forms (preferences:get 'framework:square-bracket:cond)]
[letrec-like-forms (preferences:get 'framework:square-bracket:letrec)]) [letrec-like-forms (preferences:get 'framework:square-bracket:letrec)])
(send text begin-edit-sequence #f #f) (send text begin-edit-sequence #f #f)
(send text insert "[" start-pos 'same #f) (send text insert "[" start-pos 'same #f)
(when (eq? (send text classify-position pos) 'parenthesis) (when (eq? (send text classify-position pos) 'parenthesis)
(let* ([before-whitespace-pos (send text skip-whitespace pos 'backward #t)] (let* ([before-whitespace-pos (send text skip-whitespace pos 'backward #t)]
[backward-match (send text backward-match before-whitespace-pos 0)]) [matched-cond-like-keyword
(let ([b-m-char (and (number? backward-match) (send text get-character backward-match))]) ;; searches backwards for the keyword in the sequence at this level.
(cond ;; if found, it counts how many sexps back it was and then uses that to
[backward-match ;; check the preferences.
;; there is an expression before this, at this layer (let loop ([pos before-whitespace-pos]
(let* ([before-whitespace-pos2 (send text skip-whitespace backward-match 'backward #t)] [n 0])
[backward-match2 (send text backward-match before-whitespace-pos2 0)]) (let ([backward-match (send text backward-match pos 0)])
(cond
[backward-match
(let ([before-whitespace-pos (send text skip-whitespace backward-match 'backward #t)])
(loop before-whitespace-pos
(+ n 1)))]
[else
(let* ([afterwards (send text forward-match pos (send text last-position))]
[keyword
(and afterwards
(send text get-text pos afterwards))])
(and keyword
(member (list keyword (- n 1))
(preferences:get 'framework:square-bracket:cond/offset))))])))])
(cond
[matched-cond-like-keyword
;; just leave the square backet in, in this case
(void)]
[else
(let* ([backward-match (send text backward-match before-whitespace-pos 0)]
[b-m-char (and (number? backward-match) (send text get-character backward-match))])
(cond
[backward-match
;; there is an expression before this, at this layer
(let* ([before-whitespace-pos2 (send text skip-whitespace backward-match 'backward #t)]
[backward-match2 (send text backward-match before-whitespace-pos2 0)])
(cond (cond
;; we found a 'case'-like expression, two steps back, so we don't use the sibling [(member b-m-char '(#\( #\[ #\{))
;; check here -- we just go with square brackets. ;; found a "sibling" parenthesized sequence. use the parens it uses.
[(and backward-match2 (change-to 1 b-m-char)]
(ormap [else
(λ (x) ;; otherwise, we switch to (
(text-between-equal? x text backward-match2 before-whitespace-pos2)) (change-to 2 #\()]))]
case-like-forms)) [(not (zero? before-whitespace-pos))
(void)] ;; this is the first thing in the sequence
[(member b-m-char '(#\( #\[ #\{)) ;; pop out one layer and look for a keyword.
;; found a "sibling" parenthesized sequence. use the parens it uses. (let ([b-w-p-char (send text get-character (- before-whitespace-pos 1))])
(change-to 1 b-m-char)] (cond
[else [(equal? b-w-p-char #\()
;; there is a sexp before this, but it isn't parenthesized. (let* ([second-before-whitespace-pos (send text skip-whitespace
;; if it is the `cond' keyword, we get a square bracket. otherwise not. (- before-whitespace-pos 1)
(unless (and (beginning-of-sequence? text backward-match) 'backward
(ormap #t)]
(λ (x) [second-backwards-match (send text backward-match
(text-between-equal? x text backward-match before-whitespace-pos)) second-before-whitespace-pos
cond-like-forms)) 0)])
(change-to 2 #\())]))] (cond
[(not (zero? before-whitespace-pos)) [(not second-backwards-match)
;; this is the first thing in the sequence (change-to 3 #\()]
;; pop out one layer and look for a keyword. [(and (beginning-of-sequence? text second-backwards-match)
(let ([b-w-p-char (send text get-character (- before-whitespace-pos 1))]) (ormap (λ (x) (text-between-equal? x
(cond text
[(equal? b-w-p-char #\() second-backwards-match
(let* ([second-before-whitespace-pos (send text skip-whitespace second-before-whitespace-pos))
(- before-whitespace-pos 1) letrec-like-forms))
'backward ;; we found a let<mumble> keyword, so we get a square bracket
#t)] (void)]
[second-backwards-match (send text backward-match [else
second-before-whitespace-pos ;; go back one more sexp in the same row, looking for `let loop' pattern
0)]) (let* ([second-before-whitespace-pos2 (send text skip-whitespace
(cond second-backwards-match
[(not second-backwards-match) 'backward
(change-to 3 #\()] #t)]
[(and (beginning-of-sequence? text second-backwards-match) [second-backwards-match2 (send text backward-match
(ormap (λ (x) (text-between-equal? x second-before-whitespace-pos2
text 0)])
second-backwards-match (cond
second-before-whitespace-pos)) [(and second-backwards-match2
letrec-like-forms)) (eq? (send text classify-position second-backwards-match)
;; we found a let<mumble> keyword, so we get a square bracket ;;; otherwise, this isn't a `let loop', it is a regular let!
(void)] 'symbol)
[else (member "let" letrec-like-forms)
;; go back one more sexp in the same row, looking for `let loop' / 'case' pattern (text-between-equal? "let"
(let* ([second-before-whitespace-pos2 (send text skip-whitespace text
second-backwards-match second-backwards-match2
'backward second-before-whitespace-pos2))
#t)] ;; found the `(let loop (' so we keep the [
[second-backwards-match2 (send text backward-match (void)]
second-before-whitespace-pos2 [else
0)]) ;; otherwise, round.
(cond (change-to 4 #\()]))]))]
[(and second-backwards-match2 [else
(eq? (send text classify-position second-backwards-match) (change-to 5 #\()]))]
;;; otherwise, this isn't a `let loop', it is a regular let! [else
'symbol) (change-to 6 #\()]))])))
(member "let" letrec-like-forms)
(text-between-equal? "let"
text
second-backwards-match2
second-before-whitespace-pos2))
;; found the `(let loop (' or `case' so we keep the [
(void)]
[else
;; otherwise, round.
(change-to 4 #\()]))]))]
[else
(change-to 5 #\()]))]
[else
(change-to 6 #\()]))))
(send text delete pos (+ pos 1) #f) (send text delete pos (+ pos 1) #f)
(send text end-edit-sequence) (send text end-edit-sequence)
(send text insert real-char start-pos end-pos))) (send text insert real-char start-pos end-pos)))
@ -1381,7 +1391,7 @@
'framework:square-bracket:letrec)) 'framework:square-bracket:letrec))
(define pref-prefixes '("Case" "Cond" "Letrec")) (define pref-prefixes '("Case" "Cond" "Letrec"))
(define (mk-list-box sym keyword-type) (define (mk-list-box sym keyword-type pref->string get-new-one)
(letrec ([vp (new vertical-panel% [parent boxes-panel])] (letrec ([vp (new vertical-panel% [parent boxes-panel])]
[_ (new message% [_ (new message%
[label (format (string-constant x-like-keywords) keyword-type)] [label (format (string-constant x-like-keywords) keyword-type)]
@ -1390,7 +1400,7 @@
(new list-box% (new list-box%
[label #f] [label #f]
[parent vp] [parent vp]
[choices (preferences:get sym)] [choices (map pref->string (preferences:get sym))]
[callback [callback
(λ (lb evt) (λ (lb evt)
(send remove-button enable (pair? (send lb get-selections))))])] (send remove-button enable (pair? (send lb get-selections))))])]
@ -1401,43 +1411,101 @@
[parent bp] [parent bp]
[callback [callback
(λ (x y) (λ (x y)
(let ([new-one (let ([new-one (get-new-one)])
(keymap:call/text-keymap-initializer
(λ ()
(get-text-from-user
(format (string-constant enter-new-keyword) keyword-type)
(format (string-constant x-keyword) keyword-type))))])
(when new-one (when new-one
(let ([parsed (with-handlers ((exn:fail:read? (λ (x) #f))) (preferences:set sym (append (preferences:get sym)
(read (open-input-string new-one)))]) (list new-one))))))])]
(when parsed
(preferences:set sym (append (preferences:get sym)
(list new-one))))))))])]
[remove-button [remove-button
(new button% (new button%
[label (string-constant remove-keyword)] [label (string-constant remove-keyword)]
[parent bp] [parent bp]
[callback [callback
(λ (x y) (λ (x y)
(let ([s (send lb get-string-selection)] (let ([n (send lb get-selections)])
[n (send lb get-selections)]) (when (pair? n)
(when s (preferences:set
(preferences:set sym (remove s (preferences:get sym))) sym
(let loop ([i 0]
[prefs (preferences:get sym)])
(cond
[(= i (car n)) (cdr prefs)]
[else (cons (car prefs)
(loop (+ i 1)
(cdr prefs)))])))
(cond (cond
[(= 0 (send lb get-number)) [(= 0 (send lb get-number))
(send remove-button enable #f)] (send remove-button enable #f)]
[else [else
(send lb set-selection (send lb set-selection
(max (- (send lb get-number) 1) (if (= (car n) (send lb get-number))
(car n)))]))))])]) (- (send lb get-number) 1)
(car n)))]))))])])
(unless (pair? (send lb get-selections)) (unless (pair? (send lb get-selections))
(send remove-button enable #f)) (send remove-button enable #f))
(preferences:add-callback sym (preferences:add-callback sym
(λ (p v) (λ (p v)
(send lb clear) (send lb clear)
(for-each (λ (x) (send lb append x)) v))))) (for-each (λ (x) (send lb append (pref->string x))) v)))))
(define (get-new-letrec-keyword)
(let ([new-one
(keymap:call/text-keymap-initializer
(λ ()
(get-text-from-user
(format (string-constant enter-new-keyword) "Letrec")
(format (string-constant x-keyword) "Letrec"))))])
(and new-one
(let ([parsed (with-handlers ((exn:fail:read? (λ (x) #f)))
(read (open-input-string new-one)))])
parsed))))
(define (get-new-cond-keyword)
(define f (new dialog% [label (format (string-constant enter-new-keyword) "Cond")]))
(define tb (keymap:call/text-keymap-initializer
(λ ()
(new text-field%
[parent f]
[label #f]))))
(define number-panel (new horizontal-panel% [parent f] [stretchable-height #f]))
(define number-label (new message% [parent number-panel] [label (string-constant skip-subexpressions)]))
(define number
(keymap:call/text-keymap-initializer
(λ ()
(new text-field%
[parent number-panel]
[init-value "1"]
[min-width 50]
[label #f]))))
(define answers #f)
(define bp (new horizontal-panel%
[parent f]
[stretchable-height #f]
[alignment '(right center)]))
(define (confirm-callback b e)
(let ([n (string->number (send number get-value))]
[sym (with-handlers ([exn:fail:read? (λ (x) #f)])
(read (open-input-string (send tb get-value))))])
(when (and (number? n)
(symbol? sym))
(set! answers (list (symbol->string sym) n)))
(send f show #f)))
(define (cancel-callback b e)
(send f show #f))
(define-values (ok-button cancel-button)
(gui-utils:ok/cancel-buttons bp confirm-callback cancel-callback (string-constant ok) (string-constant cancel)))
(send f show #t)
answers)
(define stupid-internal-definition-syntax1 (define stupid-internal-definition-syntax1
(for-each mk-list-box pref-syms pref-prefixes)) (mk-list-box 'framework:square-bracket:letrec "Letrec" values get-new-letrec-keyword))
(define stupid-internal-definition-syntax2
(mk-list-box 'framework:square-bracket:cond/offset
"Cond"
(λ (l) (format "~a (~a)" (car l) (cadr l)))
get-new-cond-keyword))
(define check-box (new check-box% (define check-box (new check-box%
[parent main-panel] [parent main-panel]

View File

@ -452,13 +452,16 @@ please adhere to these guidelines:
(indenting-prefs-panel-label "Indenting") (indenting-prefs-panel-label "Indenting")
(indenting-prefs-extra-regexp "Extra regexp") (indenting-prefs-extra-regexp "Extra regexp")
(square-bracket-prefs-panel-label "Square bracket") (square-bracket-prefs-panel-label "Square Bracket")
; filled with define, lambda, or begin ; filled with define, lambda, or begin
(enter-new-keyword "Enter new ~a-like keyword:") (enter-new-keyword "Enter new ~a-like keyword:")
(x-keyword "~a Keyword") (x-keyword "~a Keyword")
(x-like-keywords "~a-like Keywords") (x-like-keywords "~a-like Keywords")
; used in Square bracket panel
(skip-subexpressions "Number of sub-expressions to skip")
(expected-a-symbol "expected a symbol, found: ~a") (expected-a-symbol "expected a symbol, found: ~a")
(already-used-keyword "\"~a\" is already a specially indented keyword") (already-used-keyword "\"~a\" is already a specially indented keyword")
(add-keyword "Add") (add-keyword "Add")