add basic support for #lang line-specific editing
Specifically, the #lang line now selects for a definitions text surrogate, on top of which several extensions can be built to, say, more easily add keybindings or change indenting decisions, etc.
This commit is contained in:
parent
2e49672561
commit
905033e3f8
|
@ -101,7 +101,11 @@
|
|||
module-language-big-defs/ints-interactions-text-mixin
|
||||
module-language-big-defs/ints-definitions-text-mixin
|
||||
initialize-prefs-panel
|
||||
big-defs/ints-label<%>))
|
||||
big-defs/ints-label<%>
|
||||
|
||||
change-lang-surrogate-mixin
|
||||
default-surrogate%
|
||||
change-lang-host-mixin))
|
||||
|
||||
(define-signature drracket:module-language-tools-cm^
|
||||
(frame-mixin
|
||||
|
|
|
@ -118,12 +118,13 @@
|
|||
(make-extender get-base-interactions-text% 'interactions-text%))
|
||||
|
||||
(define (get-base-definitions-text%)
|
||||
(drracket:module-language:module-language-online-expand-text-mixin
|
||||
(drracket:module-language-tools:definitions-text-mixin
|
||||
(drracket:module-language:module-language-big-defs/ints-definitions-text-mixin
|
||||
(drracket:debug:test-coverage-definitions-text-mixin
|
||||
(drracket:debug:profile-definitions-text-mixin
|
||||
(drracket:unit:get-definitions-text%)))))))
|
||||
(drracket:module-language:change-lang-host-mixin
|
||||
(drracket:module-language:module-language-online-expand-text-mixin
|
||||
(drracket:module-language-tools:definitions-text-mixin
|
||||
(drracket:module-language:module-language-big-defs/ints-definitions-text-mixin
|
||||
(drracket:debug:test-coverage-definitions-text-mixin
|
||||
(drracket:debug:profile-definitions-text-mixin
|
||||
(drracket:unit:get-definitions-text%))))))))
|
||||
|
||||
(define-values (extend-definitions-text get-definitions-text)
|
||||
(make-extender get-base-definitions-text%
|
||||
|
|
|
@ -1,46 +1,54 @@
|
|||
#lang racket/unit
|
||||
(require string-constants
|
||||
racket/class
|
||||
racket/list
|
||||
framework
|
||||
drracket/private/drsig)
|
||||
(require string-constants
|
||||
racket/class
|
||||
racket/list
|
||||
framework
|
||||
racket/gui/base
|
||||
drracket/private/drsig)
|
||||
|
||||
(import [prefix drracket:module-language: drracket:module-language/int^])
|
||||
(export drracket:modes^)
|
||||
|
||||
(define-struct mode (name surrogate repl-submit matches-language))
|
||||
(define modes (list))
|
||||
|
||||
(define (get-modes) modes)
|
||||
|
||||
(define (add-mode name surrogate repl-submit matches-language)
|
||||
(let ([new-mode (make-mode name
|
||||
surrogate
|
||||
repl-submit
|
||||
matches-language)])
|
||||
(set! modes (cons new-mode modes))
|
||||
new-mode))
|
||||
|
||||
(define (not-a-language-language? l)
|
||||
(and (not (null? l))
|
||||
(equal? (last l)
|
||||
(string-constant no-language-chosen))))
|
||||
|
||||
|
||||
(define (add-initial-modes)
|
||||
|
||||
(import)
|
||||
(export drracket:modes^)
|
||||
;; must be added first, to make it last in mode list,
|
||||
;; since predicate matches everything
|
||||
(add-mode
|
||||
(string-constant scheme-mode)
|
||||
(new racket:text-mode%)
|
||||
(λ (text prompt-position) (racket:text-balanced? text prompt-position))
|
||||
(λ (l) #t))
|
||||
|
||||
(define-struct mode (name surrogate repl-submit matches-language))
|
||||
(define modes (list))
|
||||
(add-mode
|
||||
(string-constant racket-mode)
|
||||
(new drracket:module-language:default-surrogate%)
|
||||
(λ (text prompt-position) (racket:text-balanced? text prompt-position))
|
||||
(λ (l) (member (string-constant module-language-name) l)))
|
||||
|
||||
(define (get-modes) modes)
|
||||
|
||||
(define (add-mode name surrogate repl-submit matches-language)
|
||||
(let ([new-mode (make-mode name
|
||||
surrogate
|
||||
repl-submit
|
||||
matches-language)])
|
||||
(set! modes (cons new-mode modes))
|
||||
new-mode))
|
||||
|
||||
(define (not-a-language-language? l)
|
||||
(and (not (null? l))
|
||||
(equal? (last l)
|
||||
(string-constant no-language-chosen))))
|
||||
|
||||
(define (add-initial-modes)
|
||||
|
||||
;; must be added first, to make it last in mode list,
|
||||
;; since predicate matches everything
|
||||
(add-mode
|
||||
(string-constant scheme-mode)
|
||||
(new racket:text-mode%)
|
||||
(λ (text prompt-position) (racket:text-balanced? text prompt-position))
|
||||
(λ (l) #t))
|
||||
|
||||
(add-mode
|
||||
(string-constant text-mode)
|
||||
#f
|
||||
(λ (text prompt-position) #t)
|
||||
(λ (l)
|
||||
(and l
|
||||
(or (not-a-language-language? l)
|
||||
(ormap (λ (x) (regexp-match #rx"Algol" x)) l))))))
|
||||
(add-mode
|
||||
(string-constant text-mode)
|
||||
#f
|
||||
(λ (text prompt-position) #t)
|
||||
(λ (l)
|
||||
(and l
|
||||
(or (not-a-language-language? l)
|
||||
(ormap (λ (x) (regexp-match #rx"Algol" x)) l))))))
|
||||
|
|
|
@ -2552,4 +2552,74 @@
|
|||
[tab (in-list (send frame get-tabs))]
|
||||
[v (in-value (send (send tab get-defs) get-filename))]
|
||||
#:when v)
|
||||
v)))
|
||||
v))
|
||||
|
||||
|
||||
|
||||
(define-local-member-name maybe-change-language)
|
||||
|
||||
(define change-lang-host<%> (interface () maybe-change-language))
|
||||
|
||||
(define change-lang-host-mixin
|
||||
(mixin ((class->interface text%) mode:host-text<%>) (change-lang-host<%>)
|
||||
(inherit set-surrogate)
|
||||
|
||||
(define current-surrogate-mod #f)
|
||||
(define current-language-end #f)
|
||||
|
||||
;; called by the surrogate-mixin to see if the surrogate needs changing if
|
||||
;; the mode is not the racket language mode, then this doesn't get called.
|
||||
(define/public (maybe-change-language start)
|
||||
(when (or (not current-language-end)
|
||||
(< start current-language-end))
|
||||
(update-surrogate)))
|
||||
|
||||
(define/private (update-surrogate)
|
||||
(define defs-port (open-input-text-editor this))
|
||||
;; need this to count chars, not bytes (in case of non-ASCII
|
||||
;; in defs before #lang line)
|
||||
(port-count-lines! defs-port)
|
||||
(define get-info
|
||||
(with-handlers ([exn:fail? (λ (x) #f)])
|
||||
(read-language defs-port (λ () #f))))
|
||||
(define-values (line col pos) (port-next-location defs-port))
|
||||
(define new-surrogate-mod
|
||||
(and get-info
|
||||
(get-info 'definitions-text-surrogate #f)))
|
||||
(set! current-language-end pos)
|
||||
(unless (equal? current-surrogate-mod new-surrogate-mod)
|
||||
(set! current-surrogate-mod new-surrogate-mod)
|
||||
(define new-surrogate
|
||||
(and new-surrogate-mod
|
||||
(with-handlers ([exn:fail?
|
||||
(λ (x)
|
||||
(log-error
|
||||
(format "Error while loading surrogate; expected to be in ~s\n~a"
|
||||
new-surrogate-mod
|
||||
(exn-message x)))
|
||||
#f)])
|
||||
(dynamic-require new-surrogate-mod 'surrogate%))))
|
||||
(set-surrogate (new (if new-surrogate
|
||||
(change-lang-surrogate-mixin
|
||||
new-surrogate)
|
||||
default-surrogate%)))))
|
||||
|
||||
(super-new)))
|
||||
|
||||
(define change-lang-surrogate-mixin
|
||||
(mixin (mode:surrogate-text<%>) ()
|
||||
(define/override (after-insert ths supr start len)
|
||||
(super after-insert ths supr start len)
|
||||
(when (is-a? ths change-lang-host<%>)
|
||||
(send ths maybe-change-language start)))
|
||||
|
||||
(define/override (after-delete ths supr start len)
|
||||
(super after-delete ths supr start len)
|
||||
(when (is-a? ths change-lang-host<%>)
|
||||
(send ths maybe-change-language start)))
|
||||
|
||||
(super-new)))
|
||||
|
||||
(define default-surrogate%
|
||||
(change-lang-surrogate-mixin
|
||||
racket:text-mode%)))
|
||||
|
|
|
@ -570,16 +570,32 @@ has.
|
|||
@index{modes}
|
||||
@index{scheme mode}
|
||||
@index{racket mode}
|
||||
@index{definitions-text-surrogate}
|
||||
|
||||
DrRacket provides support for multiple editor modes. Tools
|
||||
register modes via
|
||||
DrRacket provides support for multiple editor modes based on the
|
||||
@tt{#lang} line at the beginning of the editor. If the
|
||||
@onscreen{Modes} submenu of the @onscreen{Edit} menu has
|
||||
the @onscreen{Racket} mode chosen (which is the default if the
|
||||
Language dialog's ``The Racket Language'' is chosen), then
|
||||
DrRacket calls the language's @racket[get-info] procedure
|
||||
(see @racket[read-language] for more about how to set up
|
||||
a language's @racket[get-info] procedure) with
|
||||
@racket['definitions-text-surrogate]. This is expected to return
|
||||
a quoted module path (in the sense of @racket[module-path?]) that
|
||||
names a module that exports @racket[surrogate%]. It is expected
|
||||
to be bound to a class implementing the @racket[mode:surrogate-text<%>]
|
||||
interface. Assuming so, it is used as the surrogate for the definitions
|
||||
text.
|
||||
|
||||
Additionally, plugins can register modes via
|
||||
@racket[drracket:modes:add-mode]. Each mode is
|
||||
visible in the @onscreen{Modes} submenu of the @onscreen{Edit}
|
||||
menu. Initially, DrRacket only supports two modes: Racket
|
||||
mode and text mode.
|
||||
|
||||
DrRacket automatically selects a mode for each open
|
||||
file based on the file's extension. If the file ends with
|
||||
file based on the file's extension (and the language chosen
|
||||
as described above). If the file ends with
|
||||
@File{.txt}, DrRacket uses text mode. Otherwise, DrRacket
|
||||
uses Racket mode.
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user