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-interactions-text-mixin
|
||||||
module-language-big-defs/ints-definitions-text-mixin
|
module-language-big-defs/ints-definitions-text-mixin
|
||||||
initialize-prefs-panel
|
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^
|
(define-signature drracket:module-language-tools-cm^
|
||||||
(frame-mixin
|
(frame-mixin
|
||||||
|
|
|
@ -118,12 +118,13 @@
|
||||||
(make-extender get-base-interactions-text% 'interactions-text%))
|
(make-extender get-base-interactions-text% 'interactions-text%))
|
||||||
|
|
||||||
(define (get-base-definitions-text%)
|
(define (get-base-definitions-text%)
|
||||||
(drracket:module-language:module-language-online-expand-text-mixin
|
(drracket:module-language:change-lang-host-mixin
|
||||||
(drracket:module-language-tools:definitions-text-mixin
|
(drracket:module-language:module-language-online-expand-text-mixin
|
||||||
(drracket:module-language:module-language-big-defs/ints-definitions-text-mixin
|
(drracket:module-language-tools:definitions-text-mixin
|
||||||
(drracket:debug:test-coverage-definitions-text-mixin
|
(drracket:module-language:module-language-big-defs/ints-definitions-text-mixin
|
||||||
(drracket:debug:profile-definitions-text-mixin
|
(drracket:debug:test-coverage-definitions-text-mixin
|
||||||
(drracket:unit:get-definitions-text%)))))))
|
(drracket:debug:profile-definitions-text-mixin
|
||||||
|
(drracket:unit:get-definitions-text%))))))))
|
||||||
|
|
||||||
(define-values (extend-definitions-text get-definitions-text)
|
(define-values (extend-definitions-text get-definitions-text)
|
||||||
(make-extender get-base-definitions-text%
|
(make-extender get-base-definitions-text%
|
||||||
|
|
|
@ -1,46 +1,54 @@
|
||||||
#lang racket/unit
|
#lang racket/unit
|
||||||
(require string-constants
|
(require string-constants
|
||||||
racket/class
|
racket/class
|
||||||
racket/list
|
racket/list
|
||||||
framework
|
framework
|
||||||
drracket/private/drsig)
|
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)
|
;; must be added first, to make it last in mode list,
|
||||||
(export drracket:modes^)
|
;; 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))
|
(add-mode
|
||||||
(define modes (list))
|
(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)
|
(add-mode
|
||||||
|
(string-constant text-mode)
|
||||||
(define (add-mode name surrogate repl-submit matches-language)
|
#f
|
||||||
(let ([new-mode (make-mode name
|
(λ (text prompt-position) #t)
|
||||||
surrogate
|
(λ (l)
|
||||||
repl-submit
|
(and l
|
||||||
matches-language)])
|
(or (not-a-language-language? l)
|
||||||
(set! modes (cons new-mode modes))
|
(ormap (λ (x) (regexp-match #rx"Algol" x)) l))))))
|
||||||
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))))))
|
|
||||||
|
|
|
@ -2552,4 +2552,74 @@
|
||||||
[tab (in-list (send frame get-tabs))]
|
[tab (in-list (send frame get-tabs))]
|
||||||
[v (in-value (send (send tab get-defs) get-filename))]
|
[v (in-value (send (send tab get-defs) get-filename))]
|
||||||
#:when v)
|
#: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{modes}
|
||||||
@index{scheme mode}
|
@index{scheme mode}
|
||||||
@index{racket mode}
|
@index{racket mode}
|
||||||
|
@index{definitions-text-surrogate}
|
||||||
|
|
||||||
DrRacket provides support for multiple editor modes. Tools
|
DrRacket provides support for multiple editor modes based on the
|
||||||
register modes via
|
@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
|
@racket[drracket:modes:add-mode]. Each mode is
|
||||||
visible in the @onscreen{Modes} submenu of the @onscreen{Edit}
|
visible in the @onscreen{Modes} submenu of the @onscreen{Edit}
|
||||||
menu. Initially, DrRacket only supports two modes: Racket
|
menu. Initially, DrRacket only supports two modes: Racket
|
||||||
mode and text mode.
|
mode and text mode.
|
||||||
|
|
||||||
DrRacket automatically selects a mode for each open
|
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
|
@File{.txt}, DrRacket uses text mode. Otherwise, DrRacket
|
||||||
uses Racket mode.
|
uses Racket mode.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user