switch to scheme/base

svn: r8441

original commit: 21ffab3fe3
This commit is contained in:
Eli Barzilay 2008-01-28 08:38:12 +00:00
parent 50108948b0
commit 88a4e688bf

View File

@ -1,142 +1,141 @@
;; The main client of this module is browser/external.ss ;; The main client of this module is browser/external.ss
;; (others just use the (send-url url [new?]) interface.) ;; (others just use the (send-url url [new?]) interface.)
(module sendurl mzscheme #lang scheme/base
(require (lib "process.ss")
(lib "file.ss")
(lib "kw.ss")
(lib "port.ss")
(lib "sendevent.ss"))
(provide send-url unix-browser-list browser-preference? external-browser) (require scheme/system
scheme/file
scheme/promise
scheme/port)
(define separate-by-default? (provide send-url unix-browser-list browser-preference? external-browser)
(get-preference 'new-browser-for-urls (lambda () #t)))
(define unix-browser-list '(gnome-open firefox galeon opera netscape mozilla dillo)) (define separate-by-default?
(get-preference 'new-browser-for-urls (lambda () #t)))
;; : any -> bool (define unix-browser-list
(define (custom-browser? x) '(gnome-open firefox galeon opera netscape mozilla dillo))
(and (pair? x) (string? (car x)) (string? (cdr x))))
;; : any -> bool ;; : any -> bool
(define (browser-preference? x) (define (custom-browser? x)
(or (not x) (eq? 'plt x) (memq x unix-browser-list) (custom-browser? x) (and (pair? x) (string? (car x)) (string? (cdr x))))
(procedure? x)))
(define external-browser ;; : any -> bool
(make-parameter (define (browser-preference? x)
#f ; #f means "consult the preferences file" (or (not x) (eq? 'plt x) (memq x unix-browser-list) (custom-browser? x)
(lambda (x) (procedure? x)))
(if (browser-preference? x)
x
(error 'external-browser "~e is not a valid browser preference" x)))))
;; like (system-type), but return the real OS for OSX with XonX (define external-browser
;; (could do the same for Cygwin, but that it doesn't have shell-execute) (make-parameter
(define systype #f ; #f means "consult the preferences file"
(delay (let ([t (system-type)]) (lambda (x)
(cond [(not (eq? t 'unix)) t] (if (browser-preference? x)
[(regexp-match? #rx"-darwin($|/)" x
(path->string (system-library-subpath))) (error 'external-browser "~e is not a valid browser preference" x)))))
'macosx]
[else t]))))
; send-url : str [bool] -> void ;; like (system-type), but return the real OS for OSX with XonX
(define/kw (send-url url-str ;; (could do the same for Cygwin, but that it doesn't have shell-execute)
#:optional [separate-window? separate-by-default?]) (define systype
(define stupid-internal-define-syntax1 (delay (let ([t (system-type)])
(unless (string? url-str) (cond [(not (eq? t 'unix)) t]
(error 'send-url "expected a string, got ~e" url-str))) [(regexp-match? #rx"-darwin($|/)"
(define external (external-browser)) (path->string (system-library-subpath)))
(define stype (force systype)) 'macosx]
(define preferred '|? ? ?|) [else t]))))
(define (use-browser browser-name)
(when (eq? preferred '|? ? ?|)
(set! preferred (or external (get-preference 'external-browser))))
(and (or (not preferred) (eq? preferred browser-name))
(find-executable-path (symbol->string browser-name) #f)))
(cond
[(procedure? external) (external url-str)]
[(eq? stype 'macosx)
(browser-process (format "osascript -e 'open location \"~a\"'" url-str))]
[(eq? stype 'windows)
(let ([simple
(lambda ()
(shell-execute #f url-str "" (current-directory) 'SW_SHOWNORMAL))])
(if (regexp-match #rx"#" url-str)
;; complex case: need to launch the browser directly,
;; otherwise the fragment is ignored. Use `ftype' to discover
;; the browser...
(let ([p (process "ftype htmlfile")])
(close-output-port (cadr p))
(let ([s (read-line (car p) 'return-linefeed)])
(close-input-port (car p))
(close-input-port (cadddr p))
(let ([m (regexp-match #rx"^htmlfile=(.*)" s)])
(if m
(browser-process (string-append (cadr m) " " url-str))
;; give up and use simple mode
(simple)))))
;; simple case: no fragment
(simple)))]
[(not (eq? stype 'unix))
(error 'send-url "don't know how to open URL on platform: ~s" stype)]
;; unix
[(use-browser 'opera)
=> (lambda (exe)
;; opera may not return -- always open asyncronously
;; opera starts a new browser automatically, if it can't find one
(browser-process* exe "-remote"
(format "openURL(~a)"
(if separate-window?
(format "~a,new-window" url-str)
url-str))))]
[(use-browser 'galeon)
=> (lambda (exe)
(browser-process* exe (if separate-window? "-w" "-x") url-str))]
[(use-browser 'gnome-open)
=> (lambda (exe)
(browser-process* exe url-str))]
[(or (use-browser 'netscape)
(use-browser 'mozilla)
(use-browser 'firefox))
=> (lambda (exe)
;; netscape's -remote returns with an error code, if no netscape is
;; around. start a new netscape in that case.
(or (system* exe "-remote"
(format "openURL(~a)"
(if separate-window?
(format "~a,new-window" url-str)
url-str)))
(browser-process* exe url-str)))]
[(use-browser 'dillo)
=> (lambda (exe) (browser-process* exe url-str))]
[(custom-browser? preferred)
(let ([cmd (string-append (car preferred)
url-str
(cdr preferred))])
(browser-process cmd))]
[else
(error 'send-url "Couldn't find a browser to open URL: ~e" url-str)])
(void))
;; run-browser : process-proc list-of-strings -> void ;; send-url : str [bool] -> void
(define (run-browser process*/ports args) (define (send-url url-str [separate-window? separate-by-default?])
(let-values ([(stdout stdin pid stderr control) (define stupid-internal-define-syntax1
(apply values (unless (string? url-str)
(apply process*/ports (error 'send-url "expected a string, got ~e" url-str)))
(open-output-nowhere) #f (current-error-port) (define external (external-browser))
args))]) (define stype (force systype))
(close-output-port stdin) (define preferred '|? ? ?|)
(thread (lambda () (define (use-browser browser-name)
(control 'wait) (when (eq? preferred '|? ? ?|)
(when (eq? 'done-error (control 'status)) (set! preferred (or external (get-preference 'external-browser))))
(error 'run-browser "process execute failed: ~e" args)))) (and (or (not preferred) (eq? preferred browser-name))
(void))) (find-executable-path (symbol->string browser-name) #f)))
(cond
[(procedure? external) (external url-str)]
[(eq? stype 'macosx)
(browser-process (format "osascript -e 'open location \"~a\"'" url-str))]
[(eq? stype 'windows)
(let ([simple
(lambda ()
(shell-execute #f url-str "" (current-directory) 'SW_SHOWNORMAL))])
(if (regexp-match #rx"#" url-str)
;; complex case: need to launch the browser directly,
;; otherwise the fragment is ignored. Use `ftype' to discover
;; the browser...
(let ([p (process "ftype htmlfile")])
(close-output-port (cadr p))
(let ([s (read-line (car p) 'return-linefeed)])
(close-input-port (car p))
(close-input-port (cadddr p))
(let ([m (regexp-match #rx"^htmlfile=(.*)" s)])
(if m
(browser-process (string-append (cadr m) " " url-str))
;; give up and use simple mode
(simple)))))
;; simple case: no fragment
(simple)))]
[(not (eq? stype 'unix))
(error 'send-url "don't know how to open URL on platform: ~s" stype)]
;; unix
[(use-browser 'opera)
=> (lambda (exe)
;; opera may not return -- always open asyncronously
;; opera starts a new browser automatically, if it can't find one
(browser-process* exe "-remote"
(format "openURL(~a)"
(if separate-window?
(format "~a,new-window" url-str)
url-str))))]
[(use-browser 'galeon)
=> (lambda (exe)
(browser-process* exe (if separate-window? "-w" "-x") url-str))]
[(use-browser 'gnome-open)
=> (lambda (exe) (browser-process* exe url-str))]
[(or (use-browser 'netscape)
(use-browser 'mozilla)
(use-browser 'firefox))
=> (lambda (exe)
;; netscape's -remote returns with an error code, if no netscape is
;; around. start a new netscape in that case.
(or (system* exe "-remote"
(format "openURL(~a)"
(if separate-window?
(format "~a,new-window" url-str)
url-str)))
(browser-process* exe url-str)))]
[(use-browser 'dillo)
=> (lambda (exe) (browser-process* exe url-str))]
[(custom-browser? preferred)
(let ([cmd (string-append (car preferred)
url-str
(cdr preferred))])
(browser-process cmd))]
[else
(error 'send-url "Couldn't find a browser to open URL: ~e" url-str)])
(void))
(define (browser-process* . args) ;; run-browser : process-proc list-of-strings -> void
(run-browser process*/ports args)) (define (run-browser process*/ports args)
(let-values ([(stdout stdin pid stderr control)
(apply values
(apply process*/ports
(open-output-nowhere) #f (current-error-port)
args))])
(close-output-port stdin)
(thread (lambda ()
(control 'wait)
(when (eq? 'done-error (control 'status))
(error 'run-browser "process execute failed: ~e" args))))
(void)))
(define (browser-process . args) (define (browser-process* . args)
(run-browser process/ports args))) (run-browser process*/ports args))
(define (browser-process . args)
(run-browser process/ports args))