A decompiler-gui.rkt => decompiler-gui.rkt +82 -0
@@ 0,0 1,82 @@
+#lang racket/base
+(require racket/gui
+ racket/path
+ racket/gui/easy
+ racket/gui/easy/operator
+ (rename-in racket/gui/easy
+ (dialog gui-dialog))
+ "decompiler.rkt")
+
+(define-syntax-rule (render-quietly form ...)
+ (void (render form ...)))
+
+(define (display-error e)
+ (define/obs @visible? #t)
+ (render
+ (gui-dialog #:title "Error"
+ #:mixin (λ (%) (class % (super-new) (obs-observe! @visible? (λ (visible?) (send this show visible?)))))
+ (vpanel #:margin '(10 10)
+ (text (exn-message e))
+ (button "OK" (λ () (:= @visible? #f)))))
+ main-window)
+ (void))
+
+(define/obs @loaded-path #f)
+(define/obs @dialog #f)
+
+(define (load-dialog path)
+ (when path
+ (with-handlers ([exn:fail:user? display-error])
+ (call-with-input-file* path
+ (λ (in)
+ (:= @dialog (read-dialog in))
+ (:= @loaded-path path))))))
+
+(define (save-prompt)
+ (define dialog (obs-peek @dialog))
+ (define loaded-path (obs-peek @loaded-path))
+ (when (and loaded-path dialog)
+ (define new-dest (file-name-from-path (path-replace-extension loaded-path ".md")))
+ (define path (put-file "Choose destination to export" #f #f new-dest "md" '() '(("Text Files" "*.md;*.txt") ("Any" "*.*"))))
+ (when path
+ (call-with-output-file path #:mode 'text #:exists 'replace
+ (λ (out)
+ (write-string (dialog->text dialog) out))))))
+
+(define problem-checkers
+ (list
+ (λ (i) (and ((length (interchange^-lines i)) . > . max-number-of-lines) "L"))))
+
+(define (dialog-table dialog)
+ (for/vector ([interchange (dialog^-interchanges dialog)]
+ [n0 (in-naturals 0)])
+ (define lines (interchange^-lines interchange))
+ (define first-line (if (pair? lines) (car lines) "<empty>"))
+ (define problem (or (for/or ([p problem-checkers]) (p interchange)) ""))
+ (vector
+ problem
+ (number->string n0)
+ first-line
+ (number->string (length (interchange^-lines interchange)))
+ (number->string (length (interchange^-replies interchange))))))
+
+(define main-window
+ (render
+ (window
+ #:title "Wonderland Adventures Dialog Decompiler"
+ #:size '(500 600)
+ (group "Files"
+ #:stretch '(#t #f)
+ (hpanel #:stretch '(#t #f)
+ (button "Open .dia file" #:stretch '(#t #t)
+ (λ ()
+ (define path (get-file "Choose a .dia file" #f #f #f "dia" '() '(("WA Dialogs" "*.dia") ("Any" "*.*"))))
+ (load-dialog path)))
+ (button "Export dialog as text" #:stretch '(#t #t) #:enabled? @dialog
+ save-prompt)))
+ (group "Details"
+ (if-view @dialog
+ (table #:column-widths '((2 300))
+ '("Ok?" "N#" "Text" "Lines" "Replies")
+ (@dialog . ~> . dialog-table))
+ (spacer))))))
M decompiler.rkt => decompiler.rkt +12 -8
@@ 2,6 2,16 @@
(require racket/list
racket/port)
+(provide
+ read-dialog
+ dialog->text
+ (struct-out dialog^)
+ (struct-out interchange^)
+ (struct-out effect^)
+ (struct-out reply^)
+ chars-per-line
+ max-number-of-lines)
+
;; test structures
(module+ test
@@ 19,9 29,8 @@
;; handler if there's not enough data
-(define (end-of-input [message "Tried to read more from the file, but reached the end of the file."])
- (displayln message)
- (exit 1))
+(define (end-of-input [message : String "Tried to read more from the file, but reached the end of the file."])
+ (raise (exn:fail:user message (current-continuation-marks))))
;; wonderland basic types
@@ 139,8 148,3 @@
(reply^-cmd-data-3 reply)
(reply^-cmd-data-4 reply)))
(displayln ""))))))
-
-;; go!
-(define in (open-input-file "x.dia"))
-(define dialog (read-dialog in))
-(displayln (dialog->text dialog))