[ ] [ "monitor-test-self" temp-file touch-file ] unit-test
[ t ] [
- "m" get next-change drop
+ "m" get next-change path>>
[ "" = ] [ "monitor-test-self" temp-file = ] bi or
] unit-test
[ ] [ "monitor-test-self" temp-file touch-file ] unit-test
[ t ] [
- "m" get next-change drop
+ "m" get next-change path>>
[ "" = ] [ "monitor-test-self" temp-file = ] bi or
] unit-test
{ $contract "Opens a file system change monitor which listens for changes on " { $snippet "path" } " and posts notifications to " { $snippet "mailbox" } " as triples with shape " { $snippet "{ path changed monitor } " } ". The boolean indicates whether changes in subdirectories should be reported." }\r
{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ;\r
\r
+HELP: file-change\r
+{ $class-description "A change notification output by " { $link next-change } ". The " { $snippet "path" } " slot holds a pathname string. The " { $snippet "changed" } " slots holds a sequence of symbols documented in " { $link "io.monitors.descriptors" } "." } ;\r
+\r
HELP: next-change\r
-{ $values { "monitor" "a monitor" } { "path" "a pathname string" } { "changed" "a change descriptor" } }\r
-{ $contract "Waits for file system changes and outputs the pathname of the first changed file. The change descriptor is a sequence of symbols documented in " { $link "io.monitors.descriptors" } "." }\r
+{ $values { "monitor" "a monitor" } { "change" file-change } }\r
+{ $contract "Waits for file system changes and outputs a change descriptor for the first changed file." }\r
{ $errors "Throws an error if the monitor is closed from another thread." } ;\r
\r
HELP: with-monitor\r
{ $description "Indicates that a file has been renamed." } ;\r
\r
ARTICLE: "io.monitors.descriptors" "File system change descriptors"\r
-"Change descriptors output by " { $link next-change } ":"\r
+"The " { $link next-change } " word outputs instances of a class:"\r
+{ $subsection file-change }\r
+"The " { $slot "changed" } " slot holds a sequence which may contain any of the following symbols:"\r
{ $subsection +add-file+ }\r
{ $subsection +remove-file+ }\r
{ $subsection +modify-file+ }\r
{ $subsection +rename-file+ } ;\r
\r
ARTICLE: "io.monitors.platforms" "Monitors on different platforms"\r
-"Whether the " { $snippet "path" } " output value of " { $link next-change } " contains an absolute path or a path relative to the path given to " { $link <monitor> } " is unspecified, and may even vary on the same platform. User code should not assume either case."\r
+"Whether the " { $slot "path" } " slot of a " { $link file-change } " contains an absolute path or a path relative to the path given to " { $link <monitor> } " is unspecified, and may even vary on the same platform. User code should not assume either case."\r
$nl\r
"If the immediate path being monitored was changed, then " { $snippet "path" } " will equal " { $snippet "\"\"" } "; however this condition is not reported on all platforms. See below."\r
{ $heading "Mac OS X" }\r
$nl\r
{ $snippet "FSEventStream" } "s always monitor directory hierarchies recursively, and the " { $snippet "recursive?" } " parameter to " { $link <monitor> } " has no effect."\r
$nl\r
-"The " { $snippet "changed" } " output value of the " { $link next-change } " word always outputs " { $link +modify-file+ } " and the " { $snippet "path" } " output value is always the directory containing the file that changed. Unlike other platforms, fine-grained information is not available."\r
+"The " { $snippet "changed" } " slot of the " { $link file-change } " word tuple always contains " { $link +modify-file+ } " and the " { $snippet "path" } " slot is always the directory containing the file that changed. Unlike other platforms, fine-grained information is not available."\r
$nl\r
"Only directories may be monitored, not individual files. Changes to the directory itself (permissions, modification time, and so on) are not reported; only changes to children are reported."\r
{ $heading "Windows" }\r
{ $code\r
"USE: io.monitors"\r
": watch-loop ( monitor -- )"\r
- " dup next-change . . nl nl flush watch-loop ;"\r
+ " dup next-change . nl nl flush watch-loop ;"\r
""\r
": watch-directory ( path -- )"\r
" [ t [ watch-loop ] with-monitor ] with-monitors"\r
continuations namespaces concurrency.count-downs kernel io
threads calendar prettyprint destructors io.timeouts
io.files.temp io.directories io.directories.hierarchy
-io.pathnames ;
+io.pathnames accessors ;
os { winnt linux macosx } member? [
[
"b" get count-down
[
- "m" get next-change drop
+ "m" get next-change path>>
dup print flush
dup parent-directory
[ trim-right-separators "xyz" tail? ] either? not
"c1" get count-down
[
- "m" get next-change drop
+ "m" get next-change path>>
dup print flush
dup parent-directory
[ trim-right-separators "yxy" tail? ] either? not
! Non-recursive
[ ] [ "monitor-timeout-test" temp-file f <monitor> "m" set ] unit-test
[ ] [ 3 seconds "m" get set-timeout ] unit-test
- [ [ t ] [ "m" get next-change 2drop ] [ ] while ] must-fail
+ [ [ t ] [ "m" get next-change drop ] [ ] while ] must-fail
[ ] [ "m" get dispose ] unit-test
! Recursive
[ ] [ "monitor-timeout-test" temp-file t <monitor> "m" set ] unit-test
[ ] [ 3 seconds "m" get set-timeout ] unit-test
- [ [ t ] [ "m" get next-change 2drop ] [ ] while ] must-fail
+ [ [ t ] [ "m" get next-change drop ] [ ] while ] must-fail
[ ] [ "m" get dispose ] unit-test
] with-monitors
] when
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: io.backend kernel continuations destructors namespaces
sequences assocs hashtables sorting arrays threads boxes
-io.timeouts accessors concurrency.mailboxes
+io.timeouts accessors concurrency.mailboxes fry
system vocabs.loader combinators ;
IN: io.monitors
swap >>queue
swap >>path ; inline
+TUPLE: file-change path changed monitor ;
+
: queue-change ( path changes monitor -- )
3dup and and
- [ [ 3array ] keep queue>> mailbox-put ] [ 3drop ] if ;
+ [ [ file-change boa ] keep queue>> mailbox-put ] [ 3drop ] if ;
HOOK: (monitor) io-backend ( path recursive? mailbox -- monitor )
: <monitor> ( path recursive? -- monitor )
<mailbox> (monitor) ;
-: next-change ( monitor -- path changed )
- [ queue>> ] [ timeout ] bi mailbox-get-timeout first2 ;
+: next-change ( monitor -- change )
+ [ queue>> ] [ timeout ] bi mailbox-get-timeout ;
SYMBOL: +add-file+
SYMBOL: +remove-file+
: with-monitor ( path recursive? quot -- )
[ <monitor> ] dip with-disposal ; inline
+: run-monitor ( path recursive? quot -- )
+ '[ [ @ t ] loop ] with-monitor ; inline
+
+: spawn-monitor ( path recursive? quot -- )
+ [ '[ _ _ _ run-monitor ] ] [ 2drop "Monitoring " prepend ] 3bi
+ spawn drop ;
{
{ [ os macosx? ] [ "io.monitors.macosx" require ] }
{ [ os linux? ] [ "io.monitors.linux" require ] }
{ [ os winnt? ] [ "io.monitors.windows.nt" require ] }
- [ ]
+ { [ os bsd? ] [ ] }
} cond
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors sequences assocs arrays continuations
destructors combinators kernel threads concurrency.messaging
bi ;
: stop-pump ( -- )
- monitor tget children>> [ nip dispose ] assoc-each ;
+ monitor tget children>> values dispose-each ;
: pump-step ( msg -- )
- first3 path>> swap [ prepend-path ] dip monitor tget 3array
- monitor tget queue>>
- mailbox-put ;
+ [ [ monitor>> path>> ] [ path>> ] bi append-path ] [ changed>> ] bi
+ monitor tget queue-change ;
: child-added ( path monitor -- )
path>> prepend-path add-child-monitor ;
path>> prepend-path remove-child-monitor ;
: update-hierarchy ( msg -- )
- first3 swap [
+ [ path>> ] [ monitor>> ] [ changed>> ] tri [
{
{ +add-file+ [ child-added ] }
{ +remove-file+ [ child-removed ] }
-! Copyright (C) 2008 Slava Pestov.\r
+! Copyright (C) 2008, 2009 Slava Pestov.\r
! See http://factorcode.org/license.txt for BSD license.\r
USING: threads io.files io.pathnames io.monitors init kernel\r
vocabs vocabs.loader tools.vocabs namespaces continuations\r
sequences splitting assocs command-line concurrency.messaging\r
-io.backend sets tr ;\r
+io.backend sets tr accessors ;\r
IN: tools.vocabs.monitor\r
\r
TR: convert-separators "/\\" ".." ;\r
: monitor-loop ( -- )\r
#! On OS X, monitors give us the full path, so we chop it\r
#! off if its there.\r
- receive first path>vocab changed-vocab\r
+ receive path>> path>vocab changed-vocab\r
reset-cache\r
monitor-loop ;\r
\r
": forever ( quot -- ) '[ @ t ] loop ; inline"
""
"\"/tmp\" t <monitor>"
- "'[ _ next-change . . ] forever"
+ "'[ _ next-change . ] forever"
}
}
{ $slide "Example: time server"
[ print read-lines ] [ 2drop flush ] if ;\r
\r
: tail-file-loop ( stream monitor -- )\r
- dup next-change 2drop over read-lines tail-file-loop ;\r
+ dup next-change drop over read-lines tail-file-loop ;\r
\r
: tail-file ( file -- )\r
dup utf8 <file-reader> dup read-lines\r