From 13b4840893c0089f04a72ba14086e6d4829c1124 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 16 Dec 2008 12:49:00 -0600 Subject: [PATCH 01/11] fix windows file append --- basis/io/files/windows/nt/nt.factor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/basis/io/files/windows/nt/nt.factor b/basis/io/files/windows/nt/nt.factor index d0d9d5174a..15ac8ef1f0 100755 --- a/basis/io/files/windows/nt/nt.factor +++ b/basis/io/files/windows/nt/nt.factor @@ -4,7 +4,7 @@ io.backend.windows io.files.windows io.encodings.utf16n windows windows.kernel32 kernel libc math threads system environment alien.c-types alien.arrays alien.strings sequences combinators combinators.short-circuit ascii splitting alien strings assocs -namespaces make accessors tr ; +namespaces make accessors tr io.files.info ; IN: io.files.windows.nt M: winnt cwd @@ -45,7 +45,7 @@ M: winnt CreateFile-flags ( DWORD -- DWORD ) FILE_FLAG_OVERLAPPED bitor ; M: winnt open-append - 0 ! [ dup file-info size>> ] [ drop 0 ] recover + [ dup file-info size>> ] [ drop 0 ] recover [ (open-append) ] dip >>ptr ; M: winnt home "USERPROFILE" os-env ; From a92425adef2ce5aec60ff25756965dbf6f18c787 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 16 Dec 2008 12:53:04 -0600 Subject: [PATCH 02/11] fix launcher tests --- basis/io/launcher/windows/nt/nt-tests.factor | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/basis/io/launcher/windows/nt/nt-tests.factor b/basis/io/launcher/windows/nt/nt-tests.factor index 62fe45dc7f..93b1e8c2ff 100644 --- a/basis/io/launcher/windows/nt/nt-tests.factor +++ b/basis/io/launcher/windows/nt/nt-tests.factor @@ -41,8 +41,11 @@ IN: io.launcher.windows.nt.tests try-process ] unit-test +: launcher-test-path ( -- str ) + "resource:basis/io/launcher/windows/nt/test" ; + [ ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "out.txt" temp-file >>stdout @@ -60,7 +63,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "out.txt" temp-file >>stdout @@ -74,7 +77,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ "output" ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "err2.txt" temp-file >>stderr @@ -87,7 +90,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ t ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command ascii contents @@ -97,7 +100,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ t ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command +replace-environment+ >>environment-mode @@ -109,7 +112,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ "B" ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command { { "A" "B" } } >>environment @@ -120,7 +123,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ f ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command { { "USERPROFILE" "XXX" } } >>environment @@ -146,7 +149,7 @@ IN: io.launcher.windows.nt.tests [ "Hello appender\r\nHello appender\r\n" ] [ 2 [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "append.factor" 3array >>command "append-test" temp-file >>stdout From 8e0ff1989b97f65675b17d3b62bab9802ad96d93 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 16 Dec 2008 14:35:37 -0600 Subject: [PATCH 03/11] fix load error by making a word windows-file-size independent of the file-size word add constants --- basis/io/files/windows/nt/nt.factor | 14 ++- basis/windows/winsock/winsock.factor | 132 +++++++++++++-------------- 2 files changed, 78 insertions(+), 68 deletions(-) diff --git a/basis/io/files/windows/nt/nt.factor b/basis/io/files/windows/nt/nt.factor index 15ac8ef1f0..3241d19efa 100755 --- a/basis/io/files/windows/nt/nt.factor +++ b/basis/io/files/windows/nt/nt.factor @@ -4,7 +4,7 @@ io.backend.windows io.files.windows io.encodings.utf16n windows windows.kernel32 kernel libc math threads system environment alien.c-types alien.arrays alien.strings sequences combinators combinators.short-circuit ascii splitting alien strings assocs -namespaces make accessors tr io.files.info ; +namespaces make accessors tr windows.time ; IN: io.files.windows.nt M: winnt cwd @@ -44,8 +44,18 @@ M: winnt normalize-path ( string -- string' ) M: winnt CreateFile-flags ( DWORD -- DWORD ) FILE_FLAG_OVERLAPPED bitor ; + + [ GetFileAttributesEx win32-error=0/f ] keep + [ WIN32_FILE_ATTRIBUTE_DATA-nFileSizeLow ] + [ WIN32_FILE_ATTRIBUTE_DATA-nFileSizeHigh ] bi >64bit ; + +PRIVATE> + M: winnt open-append - [ dup file-info size>> ] [ drop 0 ] recover + [ dup windows-file-size ] [ drop 0 ] recover [ (open-append) ] dip >>ptr ; M: winnt home "USERPROFILE" os-env ; diff --git a/basis/windows/winsock/winsock.factor b/basis/windows/winsock/winsock.factor index 3ee333d05d..5c70e82ea9 100644 --- a/basis/windows/winsock/winsock.factor +++ b/basis/windows/winsock/winsock.factor @@ -15,74 +15,74 @@ TYPEDEF: void* SOCKET : ( -- byte-array ) HEX: 190 ; -: SOCK_STREAM 1 ; inline -: SOCK_DGRAM 2 ; inline -: SOCK_RAW 3 ; inline -: SOCK_RDM 4 ; inline -: SOCK_SEQPACKET 5 ; inline +CONSTANT: SOCK_STREAM 1 +CONSTANT: SOCK_DGRAM 2 +CONSTANT: SOCK_RAW 3 +CONSTANT: SOCK_RDM 4 +CONSTANT: SOCK_SEQPACKET 5 -: SO_DEBUG HEX: 1 ; inline -: SO_ACCEPTCONN HEX: 2 ; inline -: SO_REUSEADDR HEX: 4 ; inline -: SO_KEEPALIVE HEX: 8 ; inline -: SO_DONTROUTE HEX: 10 ; inline -: SO_BROADCAST HEX: 20 ; inline -: SO_USELOOPBACK HEX: 40 ; inline -: SO_LINGER HEX: 80 ; inline -: SO_OOBINLINE HEX: 100 ; inline +CONSTANT: SO_DEBUG HEX: 1 +CONSTANT: SO_ACCEPTCONN HEX: 2 +CONSTANT: SO_REUSEADDR HEX: 4 +CONSTANT: SO_KEEPALIVE HEX: 8 +CONSTANT: SO_DONTROUTE HEX: 10 +CONSTANT: SO_BROADCAST HEX: 20 +CONSTANT: SO_USELOOPBACK HEX: 40 +CONSTANT: SO_LINGER HEX: 80 +CONSTANT: SO_OOBINLINE HEX: 100 : SO_DONTLINGER ( -- n ) SO_LINGER bitnot ; inline -: SO_SNDBUF HEX: 1001 ; inline -: SO_RCVBUF HEX: 1002 ; inline -: SO_SNDLOWAT HEX: 1003 ; inline -: SO_RCVLOWAT HEX: 1004 ; inline -: SO_SNDTIMEO HEX: 1005 ; inline -: SO_RCVTIMEO HEX: 1006 ; inline -: SO_ERROR HEX: 1007 ; inline -: SO_TYPE HEX: 1008 ; inline +CONSTANT: SO_SNDBUF HEX: 1001 +CONSTANT: SO_RCVBUF HEX: 1002 +CONSTANT: SO_SNDLOWAT HEX: 1003 +CONSTANT: SO_RCVLOWAT HEX: 1004 +CONSTANT: SO_SNDTIMEO HEX: 1005 +CONSTANT: SO_RCVTIMEO HEX: 1006 +CONSTANT: SO_ERROR HEX: 1007 +CONSTANT: SO_TYPE HEX: 1008 -: TCP_NODELAY HEX: 1 ; inline +CONSTANT: TCP_NODELAY HEX: 1 -: AF_UNSPEC 0 ; inline -: AF_UNIX 1 ; inline -: AF_INET 2 ; inline -: AF_IMPLINK 3 ; inline -: AF_PUP 4 ; inline -: AF_CHAOS 5 ; inline -: AF_NS 6 ; inline -: AF_ISO 7 ; inline +CONSTANT: AF_UNSPEC 0 +CONSTANT: AF_UNIX 1 +CONSTANT: AF_INET 2 +CONSTANT: AF_IMPLINK 3 +CONSTANT: AF_PUP 4 +CONSTANT: AF_CHAOS 5 +CONSTANT: AF_NS 6 +CONSTANT: AF_ISO 7 ALIAS: AF_OSI AF_ISO -: AF_ECMA 8 ; inline -: AF_DATAKIT 9 ; inline -: AF_CCITT 10 ; inline -: AF_SNA 11 ; inline -: AF_DECnet 12 ; inline -: AF_DLI 13 ; inline -: AF_LAT 14 ; inline -: AF_HYLINK 15 ; inline -: AF_APPLETALK 16 ; inline -: AF_NETBIOS 17 ; inline -: AF_MAX 18 ; inline -: AF_INET6 23 ; inline -: AF_IRDA 26 ; inline -: AF_BTM 32 ; inline +CONSTANT: AF_ECMA 8 +CONSTANT: AF_DATAKIT 9 +CONSTANT: AF_CCITT 10 +CONSTANT: AF_SNA 11 +CONSTANT: AF_DECnet 12 +CONSTANT: AF_DLI 13 +CONSTANT: AF_LAT 14 +CONSTANT: AF_HYLINK 15 +CONSTANT: AF_APPLETALK 16 +CONSTANT: AF_NETBIOS 17 +CONSTANT: AF_MAX 18 +CONSTANT: AF_INET6 23 +CONSTANT: AF_IRDA 26 +CONSTANT: AF_BTM 32 -: PF_UNSPEC 0 ; inline -: PF_LOCAL 1 ; inline -: PF_INET 2 ; inline -: PF_INET6 23 ; inline +CONSTANT: PF_UNSPEC 0 +CONSTANT: PF_LOCAL 1 +CONSTANT: PF_INET 2 +CONSTANT: PF_INET6 23 -: AI_PASSIVE 1 ; inline -: AI_CANONNAME 2 ; inline -: AI_NUMERICHOST 4 ; inline +CONSTANT: AI_PASSIVE 1 +CONSTANT: AI_CANONNAME 2 +CONSTANT: AI_NUMERICHOST 4 : AI_MASK ( -- n ) { AI_PASSIVE AI_CANONNAME AI_NUMERICHOST } flags ; -: NI_NUMERICHOST 1 ; -: NI_NUMERICSERV 2 ; +CONSTANT: NI_NUMERICHOST 1 +CONSTANT: NI_NUMERICSERV 2 -: IPPROTO_TCP 6 ; inline -: IPPROTO_UDP 17 ; inline -: IPPROTO_RM 113 ; inline +CONSTANT: IPPROTO_TCP 6 +CONSTANT: IPPROTO_UDP 17 +CONSTANT: IPPROTO_RM 113 CONSTANT: WSA_FLAG_OVERLAPPED 1 ALIAS: WSA_WAIT_EVENT_0 WAIT_OBJECT_0 @@ -94,16 +94,16 @@ ALIAS: WSA_WAIT_TIMEOUT WAIT_TIMEOUT ALIAS: WSA_INFINITE INFINITE ALIAS: WSA_IO_PENDING ERROR_IO_PENDING -: INADDR_ANY 0 ; inline +CONSTANT: INADDR_ANY 0 : INVALID_SOCKET ( -- alien ) -1 ; inline -: SOCKET_ERROR -1 ; inline +CONSTANT: SOCKET_ERROR -1 -: SD_RECV 0 ; inline -: SD_SEND 1 ; inline -: SD_BOTH 2 ; inline +CONSTANT: SD_RECV 0 +CONSTANT: SD_SEND 1 +CONSTANT: SD_BOTH 2 -: SOL_SOCKET HEX: ffff ; inline +CONSTANT: SOL_SOCKET HEX: ffff ! TYPEDEF: uint in_addr_t ! C-STRUCT: in_addr @@ -207,7 +207,7 @@ C-STRUCT: QOS { "WSABUF" "ProviderSpecific" } ; TYPEDEF: QOS* LPQOS -: MAX_PROTOCOL_CHAIN 7 ; inline +CONSTANT: MAX_PROTOCOL_CHAIN 7 C-STRUCT: WSAPROTOCOLCHAIN { "int" "ChainLen" } @@ -215,7 +215,7 @@ C-STRUCT: WSAPROTOCOLCHAIN { { "DWORD" 7 } "ChainEntries" } ; TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN -: WSAPROTOCOL_LEN 255 ; inline +CONSTANT: WSAPROTOCOL_LEN 255 C-STRUCT: WSAPROTOCOL_INFOW { "DWORD" "dwServiceFlags1" } @@ -387,7 +387,7 @@ LIBRARY: mswsock FUNCTION: int AcceptEx ( void* listen, void* accept, void* out-buf, int recv-len, int addr-len, int remote-len, void* out-len, void* overlapped ) ; FUNCTION: void GetAcceptExSockaddrs ( void* a, int b, int c, int d, void* e, void* f, void* g, void* h ) ; -: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090 ; inline +CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090 : WSAID_CONNECTEX ( -- GUID ) "GUID" From 7172a00f21bfe212aa3ece2a11e1c3447ecfc572 Mon Sep 17 00:00:00 2001 From: "Jose A. Ortega Ruiz" Date: Wed, 17 Dec 2008 00:08:05 +0100 Subject: [PATCH 04/11] FUEL: More robust listener/emacs protocol; small fixes to the help mode. --- extra/fuel/fuel.factor | 2 +- misc/fuel/README | 4 +-- misc/fuel/fuel-connection.el | 28 ++++++++++++++++++--- misc/fuel/fuel-eval.el | 1 - misc/fuel/fuel-help.el | 28 +++++++++++---------- misc/fuel/fuel-listener.el | 48 +++++++++++++++++------------------- 6 files changed, 64 insertions(+), 47 deletions(-) diff --git a/extra/fuel/fuel.factor b/extra/fuel/fuel.factor index bf36969219..4535ac7fd6 100644 --- a/extra/fuel/fuel.factor +++ b/extra/fuel/fuel.factor @@ -112,7 +112,7 @@ M: source-file fuel-pprint path>> fuel-pprint ; error get fuel-eval-result get-global fuel-eval-output get-global - 3array fuel-pprint ; + 3array fuel-pprint flush nl "EOT:" write ; : fuel-forget-error ( -- ) f error set-global ; inline : fuel-forget-result ( -- ) f fuel-eval-result set-global ; inline diff --git a/misc/fuel/README b/misc/fuel/README index 9686124813..79c24ec69f 100644 --- a/misc/fuel/README +++ b/misc/fuel/README @@ -47,8 +47,8 @@ M-x customize-group fuel will show you how many. Quick key reference ------------------- -(Chords ending in a single letter accept also C- (e.g. C-cC-z is -the same as C-cz)). +(Triple chords ending in a single letter accept also C- (e.g. +C-cC-eC-r is the same as C-cC-er)). * In factor source files: diff --git a/misc/fuel/fuel-connection.el b/misc/fuel/fuel-connection.el index af793057ff..da621b3beb 100644 --- a/misc/fuel/fuel-connection.el +++ b/misc/fuel/fuel-connection.el @@ -14,8 +14,11 @@ ;;; Code: -(require 'fuel-base) (require 'fuel-log) +(require 'fuel-base) + +(require 'comint) +(require 'advice) ;;; Default connection: @@ -123,19 +126,34 @@ ;;; Connection setup: +(defun fuel-con--cleanup-connection (c) + (fuel-con--connection-cancel-timer c)) + (defun fuel-con--setup-connection (buffer) (set-buffer buffer) + (fuel-con--cleanup-connection fuel-con--connection) (let ((conn (fuel-con--make-connection buffer))) (fuel-con--setup-comint) (prog1 (setq fuel-con--connection conn) (fuel-con--connection-start-timer conn)))) +(defconst fuel-con--prompt-regex "( .+ ) ") +(defconst fuel-con--eot-marker "EOT:") +(defconst fuel-con--init-stanza (format "USE: fuel %S write" fuel-con--eot-marker)) + +(defconst fuel-con--comint-finished-regex + (format "%s%s" fuel-con--eot-marker fuel-con--prompt-regex)) + (defun fuel-con--setup-comint () + (comint-redirect-cleanup) (add-hook 'comint-redirect-filter-functions 'fuel-con--comint-redirect-filter t t) (add-hook 'comint-redirect-hook - 'fuel-con--comint-redirect-hook)) + 'fuel-con--comint-redirect-hook nil t)) + +(defadvice comint-redirect-setup (after fuel-con--advice activate) + (setq comint-redirect-finished-regexp fuel-con--comint-finished-regex)) ;;; Requests handling: @@ -169,6 +187,8 @@ (error (fuel-log--error "<%s>: continuation failed %S \n\t%s" id rstr cerr)))))) +(defvar fuel-con--debug-comint-p nil) + (defun fuel-con--comint-redirect-filter (str) (if (not fuel-con--connection) (fuel-log--error "No connection in buffer (%s)" str) @@ -176,13 +196,13 @@ (if (not req) (fuel-log--error "No current request (%s)" str) (fuel-con--request-output req str) (fuel-log--info "<%s>: in progress" (fuel-con--request-id req))))) - (fuel--shorten-str str 70)) + (if fuel-con--debug-comint-p (fuel--shorten-str str 256) "")) (defun fuel-con--comint-redirect-hook () (if (not fuel-con--connection) (fuel-log--error "No connection in buffer") (let ((req (fuel-con--connection-current-request fuel-con--connection))) - (if (not req) (fuel-log--error "No current request (%s)" str) + (if (not req) (fuel-log--error "No current request") (fuel-con--process-completed-request req) (fuel-con--connection-clean-current-request fuel-con--connection))))) diff --git a/misc/fuel/fuel-eval.el b/misc/fuel/fuel-eval.el index f14e4a922c..ca71012ec5 100644 --- a/misc/fuel/fuel-eval.el +++ b/misc/fuel/fuel-eval.el @@ -76,7 +76,6 @@ ((listp usings) `(:array ,@usings)) (t (error "Invalid 'usings' (%s)" usings)))) - ;;; Code sending: diff --git a/misc/fuel/fuel-help.el b/misc/fuel/fuel-help.el index 8170b31a1b..1b9cd9b121 100644 --- a/misc/fuel/fuel-help.el +++ b/misc/fuel/fuel-help.el @@ -108,14 +108,15 @@ displayed in the minibuffer." ;;; Help browser history: (defvar fuel-help--history - (list nil - (make-ring fuel-help-history-cache-size) - (make-ring fuel-help-history-cache-size))) + (list nil ; current + (make-ring fuel-help-history-cache-size) ; previous + (make-ring fuel-help-history-cache-size))) ; next (defvar fuel-help--history-idx 0) (defun fuel-help--history-push (term) - (when (car fuel-help--history) + (when (and (car fuel-help--history) + (not (string= (caar fuel-help--history) (car term)))) (ring-insert (nth 1 fuel-help--history) (car fuel-help--history))) (setcar fuel-help--history term)) @@ -135,7 +136,7 @@ displayed in the minibuffer." ;;; Fuel help buffer and internals: (defun fuel-help--help-buffer () - (with-current-buffer (get-buffer-create "*fuel-help*") + (with-current-buffer (get-buffer-create "*fuel help*") (fuel-help-mode) (current-buffer))) @@ -157,7 +158,7 @@ displayed in the minibuffer." (defun fuel-help--show-help-cont (def ret) (let ((out (fuel-eval--retort-output ret))) (if (or (fuel-eval--retort-error ret) (empty-string-p out)) - (message "No help for '%s'" ret) + (message "No help for '%s'" def) (fuel-help--insert-contents def out)))) (defun fuel-help--insert-contents (def str &optional nopush) @@ -167,14 +168,15 @@ displayed in the minibuffer." (set-buffer hb) (erase-buffer) (insert str) - (goto-char (point-min)) - (when (re-search-forward (format "^%s" def) nil t) - (beginning-of-line) - (kill-region (point-min) (point)) - (next-line) - (open-line 1)) + (unless nopush + (goto-char (point-min)) + (when (re-search-forward (format "^%s" def) nil t) + (beginning-of-line) + (kill-region (point-min) (point)) + (next-line) + (open-line 1) + (fuel-help--history-push (cons def (buffer-string))))) (set-buffer-modified-p nil) - (unless nopush (fuel-help--history-push (cons def str))) (pop-to-buffer hb) (goto-char (point-min)) (message "%s" def))) diff --git a/misc/fuel/fuel-listener.el b/misc/fuel/fuel-listener.el index f2dc760f94..c1e8d670cf 100644 --- a/misc/fuel/fuel-listener.el +++ b/misc/fuel/fuel-listener.el @@ -14,9 +14,11 @@ ;;; Code: (require 'fuel-eval) -(require 'fuel-base) (require 'fuel-completion) +(require 'fuel-connection) (require 'fuel-syntax) +(require 'fuel-base) + (require 'comint) @@ -63,19 +65,21 @@ buffer." (defun fuel-listener--start-process () (let ((factor (expand-file-name fuel-listener-factor-binary)) - (image (expand-file-name fuel-listener-factor-image))) + (image (expand-file-name fuel-listener-factor-image)) + (comint-redirect-perform-sanity-check nil)) (unless (file-executable-p factor) (error "Could not run factor: %s is not executable" factor)) (unless (file-readable-p image) (error "Could not run factor: image file %s not readable" image)) (message "Starting FUEL listener ...") - (comint-exec (fuel-listener--buffer) "factor" - factor nil `("-run=listener" ,(format "-i=%s" image))) (pop-to-buffer (fuel-listener--buffer)) - (goto-char (point-max)) - (comint-send-string nil "USE: fuel \"FUEL loaded\\n\" write\n") - (fuel-listener--wait-for-prompt 30) - (message "FUEL listener up and running!"))) + (make-comint-in-buffer "fuel listener" (current-buffer) factor nil + "-run=listener" (format "-i=%s" image)) + (fuel-listener--wait-for-prompt 10000) + (fuel-con--send-string/wait (current-buffer) + fuel-con--init-stanza + '(lambda (s) (message "FUEL listener up and running!")) + 20000))) (defun fuel-listener--process (&optional start) (or (and (buffer-live-p (fuel-listener--buffer)) @@ -87,21 +91,15 @@ buffer." (setq fuel-eval--default-proc-function 'fuel-listener--process) - -;;; Prompt chasing - -(defun fuel-listener--wait-for-prompt (&optional timeout) - (let ((proc (get-buffer-process (fuel-listener--buffer))) - (seen)) - (with-current-buffer (fuel-listener--buffer) - (goto-char (or comint-last-input-end (point-max))) - (while (and (not seen) - (accept-process-output proc (or timeout 10) nil t)) - (sleep-for 0 1) - (goto-char comint-last-input-end) - (setq seen (re-search-forward comint-prompt-regexp nil t))) - (goto-char (point-max)) - (unless seen (error "No prompt found!"))))) +(defun fuel-listener--wait-for-prompt (timeout) + (let ((p (point)) (seen)) + (while (and (not seen) (> timeout 0)) + (sleep-for 0.1) + (setq timeout (- timeout 100)) + (goto-char p) + (setq seen (re-search-forward comint-prompt-regexp nil t))) + (goto-char (point-max)) + (unless seen (error "No prompt found!")))) ;;; Completion support @@ -132,12 +130,10 @@ buffer." ;;; Fuel listener mode: -(defconst fuel-listener--prompt-regex ".* ) ") - (define-derived-mode fuel-listener-mode comint-mode "Fuel Listener" "Major mode for interacting with an inferior Factor listener process. \\{fuel-listener-mode-map}" - (set (make-local-variable 'comint-prompt-regexp) fuel-listener--prompt-regex) + (set (make-local-variable 'comint-prompt-regexp) fuel-con--prompt-regex) (set (make-local-variable 'comint-prompt-read-only) t) (fuel-listener--setup-completion)) From e13adc4db0e9347c3b399fa1470847fb47dfb59b Mon Sep 17 00:00:00 2001 From: "Jose A. Ortega Ruiz" Date: Wed, 17 Dec 2008 01:12:15 +0100 Subject: [PATCH 05/11] FUEL: Edit word interactive command; completion in help prompt. --- misc/fuel/README | 3 ++- misc/fuel/fuel-completion.el | 17 +++++++++++++++++ misc/fuel/fuel-help.el | 9 ++++++--- misc/fuel/fuel-mode.el | 34 +++++++++++++++++++++------------- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/misc/fuel/README b/misc/fuel/README index 79c24ec69f..cc938a60ff 100644 --- a/misc/fuel/README +++ b/misc/fuel/README @@ -57,7 +57,8 @@ C-cC-eC-r is the same as C-cC-er)). - M-. : edit word at point in Emacs - M-TAB : complete word at point - - C-cC-ev : edit vocabulary + - C-cC-ev : edit vocabulary (M-x fuel-edit-vocabulary) + - C-cC-ew : edit word (M-x fuel-edit-word) - C-cr, C-cC-er : eval region - C-M-r, C-cC-ee : eval region, extending it to definition boundaries diff --git a/misc/fuel/fuel-completion.el b/misc/fuel/fuel-completion.el index 6b89dbb008..8d2d779b31 100644 --- a/misc/fuel/fuel-completion.el +++ b/misc/fuel/fuel-completion.el @@ -143,6 +143,15 @@ terminates a current completion." (vs (and cv `("syntax" ,cv ,@(fuel-syntax--usings))))) (fuel-completion--words prefix vs))) +(defsubst fuel-completion--all-words-list (prefix) + (fuel-completion--words prefix nil)) + +(defvar fuel-completion--word-list-func + (completion-table-dynamic 'fuel-completion--word-list)) + +(defvar fuel-completion--all-words-list-func + (completion-table-dynamic 'fuel-completion--all-words-list)) + (defun fuel-completion--complete (prefix) (let* ((words (fuel-completion--word-list prefix)) (completions (all-completions prefix words)) @@ -150,6 +159,14 @@ terminates a current completion." (partial (if (eq partial t) prefix partial))) (cons completions partial))) +(defsubst fuel-completion--read-word (prompt &optional default history all) + (completing-read prompt + (if all fuel-completion--all-words-list-func + fuel-completion--word-list-func) + nil nil nil + history + (or default (fuel-syntax-symbol-at-point)))) + (defun fuel-completion--complete-symbol () "Complete the symbol at point. Perform completion similar to Emacs' complete-symbol." diff --git a/misc/fuel/fuel-help.el b/misc/fuel/fuel-help.el index 1b9cd9b121..1b0890ef9b 100644 --- a/misc/fuel/fuel-help.el +++ b/misc/fuel/fuel-help.el @@ -14,9 +14,10 @@ ;;; Code: -(require 'fuel-base) -(require 'fuel-font-lock) (require 'fuel-eval) +(require 'fuel-completion) +(require 'fuel-font-lock) +(require 'fuel-base) ;;; Customization: @@ -149,7 +150,9 @@ displayed in the minibuffer." (ask (or (not (memq major-mode '(factor-mode fuel-help-mode))) (not def) fuel-help-always-ask)) - (def (if ask (read-string prompt nil 'fuel-help--prompt-history def) + (def (if ask (fuel-completion--read-word prompt + def + 'fuel-help--prompt-history) def)) (cmd `(:fuel* ((:quote ,def) ,(if see 'see 'help)) t))) (message "Looking up '%s' ..." def) diff --git a/misc/fuel/fuel-mode.el b/misc/fuel/fuel-mode.el index 0f8e600165..b931605183 100644 --- a/misc/fuel/fuel-mode.el +++ b/misc/fuel/fuel-mode.el @@ -114,18 +114,26 @@ buffer in case of errors." "Opens a new window visiting the definition of the word at point. With prefix, asks for the word to edit." (interactive "P") - (let* ((word (fuel-syntax-symbol-at-point)) - (ask (or arg (not word))) - (word (if ask - (read-string nil - (format "Edit word%s: " - (if word (format " (%s)" word) "")) - word) - word))) - (let ((cmd `(:fuel ((:quote ,word) fuel-get-edit-location)))) - (condition-case nil - (fuel--try-edit (fuel-eval--send/wait cmd)) - (error (fuel-edit-vocabulary nil word)))))) + (let* ((word (or (and (not arg) (fuel-syntax-symbol-at-point)) + (fuel-completion--read-word "Edit word: "))) + (cmd `(:fuel ((:quote ,word) fuel-get-edit-location)))) + (condition-case nil + (fuel--try-edit (fuel-eval--send/wait cmd)) + (error (fuel-edit-vocabulary nil word))))) + +(defvar fuel-mode--word-history nil) + +(defun fuel-edit-word (&optional arg) + "Asks for a word to edit, with completion. +With prefix, only words visible in the current vocabulary are +offered." + (interactive "P") + (let* ((word (fuel-completion--read-word "Edit word: " + nil + fuel-mode--word-history + arg)) + (cmd `(:fuel ((:quote ,word) fuel-get-edit-location)))) + (fuel--try-edit (fuel-eval--send/wait cmd)))) (defvar fuel--vocabs-prompt-history nil) @@ -195,7 +203,7 @@ interacting with a factor listener is at your disposal. (fuel-mode--key ?e ?e 'fuel-eval-extended-region) (fuel-mode--key ?e ?r 'fuel-eval-region) (fuel-mode--key ?e ?v 'fuel-edit-vocabulary) -(fuel-mode--key ?e ?w 'fuel-edit-word-at-point) +(fuel-mode--key ?e ?w 'fuel-edit-word) (fuel-mode--key ?e ?x 'fuel-eval-definition) (fuel-mode--key ?d ?a 'fuel-autodoc-mode) From 7fa1f6131b0c41a5a3521dfd4dc86c9e488974b6 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Dec 2008 22:41:39 -0600 Subject: [PATCH 06/11] Slides from OTUG talk, December 2008 --- extra/otug-talk/2bi.png | Bin 0 -> 6719 bytes extra/otug-talk/2bi_at.png | Bin 0 -> 7674 bytes extra/otug-talk/2bi_star.png | Bin 0 -> 6404 bytes extra/otug-talk/authors.txt | 1 + extra/otug-talk/bi.png | Bin 0 -> 4837 bytes extra/otug-talk/bi_at.png | Bin 0 -> 4660 bytes extra/otug-talk/bi_star.png | Bin 0 -> 4415 bytes extra/otug-talk/logo.bmp | Bin 0 -> 20056 bytes extra/otug-talk/otug-talk.factor | 368 +++++++++++++++++++++++++++++++ extra/otug-talk/summary.txt | 1 + extra/otug-talk/tags.txt | 1 + 11 files changed, 371 insertions(+) create mode 100644 extra/otug-talk/2bi.png create mode 100644 extra/otug-talk/2bi_at.png create mode 100644 extra/otug-talk/2bi_star.png create mode 100644 extra/otug-talk/authors.txt create mode 100644 extra/otug-talk/bi.png create mode 100644 extra/otug-talk/bi_at.png create mode 100644 extra/otug-talk/bi_star.png create mode 100644 extra/otug-talk/logo.bmp create mode 100644 extra/otug-talk/otug-talk.factor create mode 100644 extra/otug-talk/summary.txt create mode 100644 extra/otug-talk/tags.txt diff --git a/extra/otug-talk/2bi.png b/extra/otug-talk/2bi.png new file mode 100644 index 0000000000000000000000000000000000000000..8f431f87ce059830ead37b1baeb701db3c5f7345 GIT binary patch literal 6719 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 literal 0 HcmV?d00001 diff --git a/extra/otug-talk/2bi_star.png b/extra/otug-talk/2bi_star.png new file mode 100644 index 0000000000000000000000000000000000000000..0fff37624b4c9f7d0292c23ce2735c2c934df35d GIT binary patch literal 6404 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 Ml(m(r6yAmZ7tM)ScK`qY literal 0 HcmV?d00001 diff --git a/extra/otug-talk/authors.txt b/extra/otug-talk/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/extra/otug-talk/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/extra/otug-talk/bi.png b/extra/otug-talk/bi.png new file mode 100644 index 0000000000000000000000000000000000000000..2470c9fab1570410f66cfa1cbe8094e038adce0e GIT binary patch literal 4837 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 literal 0 HcmV?d00001 diff --git a/extra/otug-talk/bi_star.png b/extra/otug-talk/bi_star.png new file mode 100644 index 0000000000000000000000000000000000000000..e94e3710cfc5163b08e3b6b5f69a4c4e7ccbb922 GIT binary patch literal 4415 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 literal 0 HcmV?d00001 diff --git a/extra/otug-talk/logo.bmp b/extra/otug-talk/logo.bmp new file mode 100644 index 0000000000000000000000000000000000000000..defc7cc8141088555d75c44f497413c5ff34e7f4 GIT binary patch literal 20056 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 literal 0 HcmV?d00001 diff --git a/extra/otug-talk/otug-talk.factor b/extra/otug-talk/otug-talk.factor new file mode 100644 index 0000000000..5730b7b635 --- /dev/null +++ b/extra/otug-talk/otug-talk.factor @@ -0,0 +1,368 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: slides help.markup math arrays hashtables namespaces +sequences kernel sequences parser memoize io.encodings.binary +locals kernel.private tools.vocabs.browser assocs quotations + tools.vocabs tools.annotations tools.crossref +help.topics math.functions compiler.tree.optimizer +compiler.cfg.optimizer fry graphics.bitmap graphics.viewer +ui.gadgets.panes tetris tetris.game combinators generalizations +multiline sequences.private ; +IN: otug-talk + +USING: cairo cairo.samples cairo.ffi cairo.gadgets accessors +io.backend ui.gadgets ; + +TUPLE: png-gadget < cairo-gadget surface ; + +: ( file -- gadget ) + png-gadget new-gadget + swap normalize-path + cairo_image_surface_create_from_png >>surface ; inline + +M: png-gadget pref-dim* ( gadget -- ) + surface>> + [ cairo_image_surface_get_width ] + [ cairo_image_surface_get_height ] + bi 2array ; + +M: png-gadget render-cairo* ( gadget -- ) + cr swap surface>> 0 0 cairo_set_source_surface + cr cairo_paint ; + +M: png-gadget ungraft* ( gadget -- ) + surface>> cairo_surface_destroy ; + +: $bitmap ( element -- ) + [ first gadget. ] ($block) ; + +: $tetris ( element -- ) + drop [ gadget. ] ($block) ; + +: otug-slides +{ + { $slide "Factor!" + { $url "http://factorcode.org" } + "Development started in 2003" + "Open source (BSD license)" + "Influenced by Forth, Lisp, and Smalltalk" + "Blurs the line between language and library" + "Interactive development" + } + { $slide "Part 1: the language" } + { $slide "Basics" + "Stack based, dynamically typed" + { "A " { $emphasis "word" } " is a named piece of code" } + { "Values are passed between words on a " { $emphasis "stack" } } + "Code evaluates left to right" + "Example:" + { $code "2 3 + ." } + } + { $slide "Quotations" + { "A " { $emphasis "quotation" } " is a block of code pushed on the stack" } + { "Syntax: " { $snippet "[ ... ]" } } + "Example:" + { $code + "\"/etc/passwd\" ascii file-lines" + "[ \"#\" head? not ] filter" + "[ \":\" split first ] map" + "." + } + } + { $slide "Words" + { "We can define new words with " { $snippet ": name ... ;" } " syntax" } + { $code ": remove-comments ( lines -- lines' )" " [ \"#\" head? not ] filter ;" } + { "Words are grouped into " { $emphasis "vocabularies" } } + { $link "vocab-index" } + "Libraries and applications are vocabularies" + { $vocab-link "spheres" } + } + { $slide "Constructing quotations" + { "Suppose we want a " { $snippet "remove-comments*" } " word" } + { $code ": remove-comments* ( lines string -- lines' )" " [ ??? head? not ] filter ;" } + { "We use " { $link POSTPONE: '[ } " instead of " { $link POSTPONE: [ } } + { "Create “holes” with " { $link _ } } + "Holes filled in left to right when quotation pushed on the stack" + } + { $slide "Constructing quotations" + { $code ": remove-comments* ( lines string -- lines' )" " '[ _ head? not ] filter ;" "" ": remove-comments ( lines -- lines' )" " \"#\" remove-comments* ;" } + { { $link @ } " inserts a quotation" } + { $code ": replicate ( n quot -- seq )" " '[ drop @ ] map ;" } + { $code "10 [ 1 10 [a,b] random ] replicate ." } + } + { $slide "Combinators" + { "A " { $emphasis "combinator" } " is a word taking quotations as input" } + { "Used for control flow, data flow, iteration" } + { $code "100 [ 5 mod 3 = [ \"Fizz!\" print ] when ] each" } + { "Control flow: " { $link if } ", " { $link when } ", " { $link unless } ", " { $link cond } } + { "Iteration: " { $link map } ", " { $link filter } ", " { $link all? } ", ..." } + } + { $slide "Data flow combinators - simple example" + "All examples so far used “pipeline style”" + "What about using a value more than once, or operating on values not at top of stack?" + { $code "{ 10 70 54 } [ sum ] [ length ] bi / ." } + { $code "5 [ 1 + ] [ sqrt ] [ 1 - ] tri 3array ." } + } + { $slide "Data flow combinators - cleave family" + { { $link bi } ", " { $link tri } ", " { $link cleave } } + { $bitmap "resource:extra/otug-slides/bi.png" } + } + { $slide "Data flow combinators - cleave family" + { { $link 2bi } ", " { $link 2tri } ", " { $link 2cleave } } + { $bitmap "resource:extra/otug-slides/2bi.png" } + } + { $slide "Data flow combinators" + "First, let's define a data type:" + { $code "TUPLE: person first-name last-name ;" } + "Make an instance:" + { $code "person new" " \"Joe\" >>first-name" " \"Sixpack\" >>last-name" } + } + { $slide "Data flow combinators" + "Let's do stuff with it:" + { $code + "[ first-name>> ] [ last-name>> ] bi" + "[ 2 head ] [ 5 head ] bi*" + "[ >upper ] bi@" + "\".\" glue ." + } + } + { $slide "Data flow combinators - spread family" + { { $link bi* } ", " { $link tri* } ", " { $link spread } } + { $bitmap "resource:extra/otug-slides/bi_star.png" } + } + { $slide "Data flow combinators - spread family" + { { $link 2bi* } } + { $bitmap "resource:extra/otug-slides/2bi_star.png" } + } + { $slide "Data flow combinators - apply family" + { { $link bi@ } ", " { $link tri@ } ", " { $link napply } } + { $bitmap "resource:extra/otug-slides/bi_at.png" } + } + { $slide "Data flow combinators - apply family" + { { $link 2bi@ } } + { $bitmap "resource:extra/otug-slides/2bi_at.png" } + } + { $slide "Shuffle words" + "When data flow combinators are not enough" + { $link "shuffle-words" } + "Lower-level, Forth/PostScript-style stack manipulation" + } + { $slide "Locals" + "When data flow combinators and shuffle words are not enough" + "Name your input parameters" + "Used in about 1% of all words" + } + { $slide "Locals example" + "Area of a triangle using Heron's formula" + { $code + <" :: area ( a b c -- x ) + a b c + + 2 / :> p + p + p a - * + p b - * + p c - * sqrt ;"> + } + } + { $slide "Previous example without locals" + "A bit unweildy..." + { $code + <" : area ( a b c -- x ) + [ ] [ + + 2 / ] 3bi + [ '[ _ - ] tri@ ] [ neg ] bi + * * * sqrt ;"> } + } + { $slide "More idiomatic version" + "But there's a trick: put the points in an array" + { $code <" : v-n ( v n -- w ) '[ _ - ] map ; + +: area ( points -- x ) + [ 0 suffix ] [ sum 2 / ] bi + v-n product sqrt ;"> } + } + ! { $slide "The parser" + ! "All data types have a literal syntax" + ! "Literal hashtables and arrays are very useful in data-driven code" + ! { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" } + ! "Libraries can define new parsing words" + ! } + { $slide "Programming without named values" + "Minimal glue between words" + "Easy multiple return values" + { "Avoid useless variable names: " { $snippet "x" } ", " { $snippet "n" } ", " { $snippet "a" } ", ..." } + { { $link at } " and " { $link at* } } + { $code "at* [ ... ] [ ... ] if" } + } + { $slide "Stack language idioms" + "Enables new idioms not possible before" + "We get the effect of “keyword parameters” for free" + { $vocab-link "smtp-example" } + } + { $slide "“Perfect” factoring" + { $table + { { $link head } { $link head-slice } } + { { $link tail } { $link tail-slice } } + } + { "Modifier: " { $link from-end } } + { "Modifier: " { $link short } } + "4*2*2=16 operations, 6 words!" + } + { $slide "Modifiers" + "“Modifiers” can express MN combinations using M+N words" + { $code + "\"Hello, Joe\" 4 head ." + "\"Hello, Joe\" 3 tail ." + "\"Hello, Joe\" 3 from-end tail ." + } + { $code + "\"Hello world\" 5 short head ." + "\"Hi\" 5 short tail ." + } + } + { $slide "Modifiers" + { "C-style " { $snippet "while" } " and " { $snippet "do while" } " loops" } + } + { $slide "Modifiers" + { $code ": bank ( n -- n )" " readln string>number +" " dup \"Balance: $\" write . ;" } + { $code "0 [ dup 0 > ] [ bank ] [ ] while" } + } + { $slide "Modifiers" + { $code "0 [ dup 0 > ] [ bank ] [ ] do while" } + { { $link do } " executes one iteration of a " { $link while } " loop" } + { { $link while } " calls " { $link do } } + } + { $slide "More “pipeline style” code" + { "Suppose we want to get the price of the customer's first order, but any one of the steps along the way could be a nil value (" { $link f } " in Factor):" } + { $code + "dup [ orders>> ] when" + "dup [ first ] when" + "dup [ price>> ] when" + } + } + { $slide "This is hard with mainstream syntax!" + { $code + <" var customer = ...; +var orders = (customer == null ? null : customer.orders); +var order = (orders == null ? null : orders[0]); +var price = (order == null ? null : order.price);"> } + } + { $slide "An ad-hoc solution" + "Something like..." + { $code "var price = customer.?orders.?[0].?price;" } + } + ! { $slide "Stack languages are fundamental" + ! "Very simple semantics" + ! "Easy to generate stack code programatically" + ! "Everything is almost entirely library code in Factor" + ! "Factor is easy to extend" + ! } + { $slide "Part 2: the implementation" } + { $slide "Interactive development" + { $tetris } + } + { $slide "Application deployment" + { $vocab-link "webkit-demo" } + "Demonstrates Cocoa binding" + "Let's deploy a stand-alone binary with the deploy tool" + "Deploy tool generates binaries with no external dependencies" + } + { $slide "The UI" + "Renders with OpenGL" + "Backends for Cocoa, Windows, X11: managing windows, input events, clipboard" + "Cross-platform API" + } + { $slide "UI example" + { $code + <" + { 5 5 } >>gap + 1 >>fill + "Hello world!"