Skip to content

Instantly share code, notes, and snippets.

@Metaxal
Last active December 16, 2015 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Metaxal/5495979 to your computer and use it in GitHub Desktop.
Save Metaxal/5495979 to your computer and use it in GitHub Desktop.
dabbrev for DrRacket. Similar to dabbrev for emacs, a bit simplified.
#lang racket/base
(require racket/class
racket/list
racket/format
;racket/gui ;for message-box
)
(define non-word-str "\"'`,;\r\n\t (){}[]")
(define non-word-chars (string->list non-word-str))
(define non-word-re (regexp-quote non-word-str))
;; Returns the first position that is not a word-like symbol
;; dir is -1 (for left) or 1 (for right)
(define (word-pos ed pos dir)
(define offset (if (= dir 1) 0 -1))
(define last (if (= dir 1)
(send ed last-position)
0))
(or
(for/or ([p (in-range pos last dir)])
(define ch (send ed get-text (+ p offset) (+ 1 p offset)))
(and ch
(memq (first (string->list ch)) non-word-chars)
p))
last))
;; Returns the string for the left- or right-hand-side of pos, depending on if dir=-1 or dir=1.
(define (get-word ed pos dir)
(let ([p (word-pos ed pos dir)])
(if p
(send ed get-text (min p pos) (max p pos))
"")))
;; In the editor ed, removes the right-hand-side word part at the cursor position if any,
;; and completes the left-hand-side word at the cursor position by the next possible
;; rhs word in the text.
;; The cursor position is not modified, therefore by calling this procedure repeatedly,
;; it is possible to cycle among all the corresponding words.
;; string? -> (or/c string? #f)
(provide dabbrev)
(define (dabbrev s #:editor ed)
(define pos (send ed get-end-position))
(define left (get-word ed pos -1))
(define right (get-word ed pos 1))
(define txt (send ed get-text))
(define matches
(remove-duplicates
(regexp-match* (pregexp (string-append "\\b" (regexp-quote left)
"[^" non-word-re "]*"))
txt)))
;(message-box "" (~v (list left right)))
(when matches
(define mems (member (string-append left right) matches))
(define str
(if (and mems (not (empty? (rest mems))))
(second mems)
(first matches)))
;(message-box "" (~v (list left right matches mems str)))
(when str
(send ed begin-edit-sequence)
(send ed delete pos (+ pos (string-length right)))
(send ed insert
(substring str (string-length left)))
(send ed set-position pos)
(send ed end-edit-sequence)))
#f)
((label . "String Utils")
(functions . ((dabbrev "Dynamic completion")))
(shortcut . #\t)
(shortcut-prefix . (ctl shift))
(help-string . "Help String")
(output-to . selection)
(persistent . #f)
(active . #t))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment