diff --git a/README.txt b/README.txt index 754791aa1a..98616539d2 100755 --- a/README.txt +++ b/README.txt @@ -43,13 +43,10 @@ Compilation will yield an executable named 'factor' on Unix, For X11 support, you need recent development libraries for libc, Freetype, X11, OpenGL and GLUT. On a Debian-derived Linux distribution -(like Ubuntu), you can use the line +(like Ubuntu), you can use the following line to grab everything: sudo apt-get install libc6-dev libfreetype6-dev libx11-dev glutg3-dev -to grab everything (if you're on a non-debian-derived distro please tell -us what the equivalent command is on there and it can be added). - * Bootstrapping the Factor image Once you have compiled the Factor runtime, you must bootstrap the Factor diff --git a/basis/environment/environment.factor b/basis/environment/environment.factor index 492925c7c0..ca78c3efa7 100644 --- a/basis/environment/environment.factor +++ b/basis/environment/environment.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: assocs combinators kernel sequences splitting system -vocabs.loader ; +vocabs.loader init ; IN: environment HOOK: os-env os ( key -- value ) @@ -25,3 +25,8 @@ HOOK: (set-os-envs) os ( seq -- ) { [ os winnt? ] [ "environment.winnt" require ] } { [ os wince? ] [ ] } } cond + +[ + "FACTOR_ROOTS" os-env os windows? ";" ":" ? split + [ add-vocab-root ] each +] "environment" add-init-hook diff --git a/basis/help/cookbook/cookbook.factor b/basis/help/cookbook/cookbook.factor index a957cb3e72..65b40543af 100644 --- a/basis/help/cookbook/cookbook.factor +++ b/basis/help/cookbook/cookbook.factor @@ -266,7 +266,7 @@ $nl "To run a script, simply pass it as an argument to the Factor executable:" { $code "./factor cleanup.factor" } "The script may access command line arguments by inspecting the value of the " { $link command-line } " variable. It can also get its own path from the " { $link script } " variable." -$nl +{ $heading "Example: ls" } "Here is an example implementing a simplified version of the Unix " { $snippet "ls" } " command in Factor:" { $code <" USING: command-line namespaces io io.files io.files.listing @@ -282,6 +282,36 @@ command-line get [ } "You can put it in a file named " { $snippet "ls.factor" } ", and then run it, to list the " { $snippet "/usr/bin" } " directory for example:" { $code "./factor ls.factor /usr/bin" } +{ $heading "Example: grep" } +"The following is a more complicated example, implementing something like the Unix " { $snippet "grep" } " command:" +{ $code <" USING: kernel fry io io.files io.encodings.ascii sequences +regexp command-line namespaces ; +IN: grep + +: grep-lines ( pattern -- ) + '[ dup _ matches? [ print ] [ drop ] if ] each-line ; + +: grep-file ( pattern filename -- ) + ascii [ grep-lines ] with-file-reader ; + +: grep-usage ( -- ) + "Usage: factor grep.factor [...]" print ; + +command-line get [ + grep-usage +] [ + unclip swap [ + grep-lines + ] [ + [ grep-file ] with each + ] if-empty +] if-empty"> } +"You can run it like so," +{ $code "./factor grep.factor '.*hello.*' myfile.txt" } +"You'll notice this script takes a while to start. This is because it is loading and compiling the " { $vocab-link "regexp" } " vocabulary every time. To speed up startup, load the vocabulary into your image, and save the image:" +{ $code "USE: regexp" "save" } +"Now, the " { $snippet "grep.factor" } " script will start up much faster. See " { $link "images" } " for details." +{ $heading "Executable scripts" } "It is also possible to make executable scripts. A Factor file can begin with a comment like the following:" { $code "#! /usr/bin/env factor" } "If the text file is made executable, then it can be run, assuming the " { $snippet "factor" } " binary is in your " { $snippet "$PATH" } "." @@ -291,6 +321,7 @@ $nl { } "cli" "cookbook-application" + "images" } ; ARTICLE: "cookbook-philosophy" "Factor philosophy" @@ -344,15 +375,6 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid" { "If " { $link run-file } " throws a stack depth assertion, it means that the top-level form in the file left behind values on the stack. The stack depth is compared before and after loading a source file, since this type of situation is almost always an error. If you have a legitimate need to load a source file which returns data in some manner, define a word in the source file which produces this data on the stack and call the word after loading the file." } } ; -ARTICLE: "cookbook-images" "Image file cookbook" -"Factor has the ability to save the entire state of the system into an " { $emphasis "image file" } "." -$nl -"You can save a custom image if you find yourself loading the same libraries in every Factor session; some libraries take a little while to compile, so saving an image with those libraries loaded can save you a lot of time." -$nl -"For example, to save an image with the web framework loaded," -{ $code "USE: furnace" "save" } -"See " { $link "images" } " for details." ; - ARTICLE: "cookbook-next" "Next steps" "Once you have read through " { $link "first-program" } " and " { $link "cookbook" } ", the best way to keep learning Factor is to start looking at some simple example programs. Here are a few particularly nice vocabularies which should keep you busy for a little while:" { $list @@ -377,7 +399,6 @@ ARTICLE: "cookbook" "Factor cookbook" { $subsection "cookbook-application" } { $subsection "cookbook-scripts" } { $subsection "cookbook-compiler" } -{ $subsection "cookbook-images" } { $subsection "cookbook-philosophy" } { $subsection "cookbook-pitfalls" } { $subsection "cookbook-next" } ; diff --git a/basis/help/tutorial/tutorial.factor b/basis/help/tutorial/tutorial.factor index afa16bbf8a..9ed36ac77c 100644 --- a/basis/help/tutorial/tutorial.factor +++ b/basis/help/tutorial/tutorial.factor @@ -13,6 +13,8 @@ $nl { $code "\"resource:work\" \"palindrome\" scaffold-vocab" } "If you look at the output, you will see that a few files were created in your ``work'' directory. The following phrase will print the full path of your work directory:" { $code "\"work\" resource-path ." } +"The work directory is one of several " { $link "vocabs.roots" } " where Factor searches for vocabularies. It is possible to define new vocabulary roots; see " { $link "add-vocab-roots" } ". To keep things simple in this tutorial, we'll just use the work directory, though." +$nl "Open the work directory in your file manager, and open the subdirectory named " { $snippet "palindrome" } ". Inside this subdirectory you will see a file named " { $snippet "palindrome.factor" } ". We will be editing this file." $nl "Notice that the file ends with an " { $link POSTPONE: IN: } " form telling Factor that all definitions in this source file should go into the " { $snippet "palindrome" } " vocabulary using the " { $link POSTPONE: IN: } " word:" diff --git a/core/io/io-docs.factor b/core/io/io-docs.factor index c55377e4a0..02af963e1a 100644 --- a/core/io/io-docs.factor +++ b/core/io/io-docs.factor @@ -253,6 +253,10 @@ HELP: lines { $values { "stream" "an input stream" } { "seq" "a sequence of strings" } } { $description "Reads lines of text until the stream is exhausted, collecting them in a sequence of strings." } ; +HELP: each-line +{ $values { "quot" { $quotation "( str -- )" } } } +{ $description "Calls the quotatin with successive lines of text, until the current " { $link input-stream } " is exhausted." } ; + HELP: contents { $values { "stream" "an input stream" } { "str" string } } { $description "Reads the entire contents of a stream into a string." } @@ -364,6 +368,8 @@ ARTICLE: "stream-utils" "Stream utilities" $nl "First, a simple composition of " { $link stream-write } " and " { $link stream-nl } ":" { $subsection stream-print } +"Processing lines one by one:" +{ $subsection each-line } "Sluring an entire stream into memory all at once:" { $subsection lines } { $subsection contents } diff --git a/core/io/io.factor b/core/io/io.factor index d7d4edf49f..c1fd69a16a 100644 --- a/core/io/io.factor +++ b/core/io/io.factor @@ -99,6 +99,9 @@ SYMBOL: error-stream : lines ( stream -- seq ) [ [ readln dup ] [ ] [ drop ] produce ] with-input-stream ; +: each-line ( quot -- ) + [ [ readln dup ] ] dip [ drop ] while ; inline + : contents ( stream -- str ) [ [ 65536 read dup ] [ ] [ drop ] produce concat f like diff --git a/core/memory/memory-docs.factor b/core/memory/memory-docs.factor index 8f49d882ee..bfe26823be 100644 --- a/core/memory/memory-docs.factor +++ b/core/memory/memory-docs.factor @@ -68,14 +68,19 @@ HELP: count-instances } } ; ARTICLE: "images" "Images" -"The current image can be saved; the image contains a complete dump of all data and code in the current Factor instance:" +"Factor has the ability to save the entire state of the system into an " { $emphasis "image file" } ". The image contains a complete dump of all data and code in the current Factor instance." { $subsection save } { $subsection save-image } { $subsection save-image-and-exit } "To start Factor with a custom image, use the " { $snippet "-i=" { $emphasis "image" } } " command line switch; see " { $link "runtime-cli-args" } "." $nl +"One reason to save a custom image is if you find yourself loading the same libraries in every Factor session; some libraries take a little while to compile, so saving an image with those libraries loaded can save you a lot of time." +$nl +"For example, to save an image with the web framework loaded," +{ $code "USE: furnace" "save" } "New images can be created from scratch:" { $subsection "bootstrap.image" } -{ $see-also "tools.memory" "tools.deploy" } ; +"The " { $link "tools.deploy" } " tool creates stripped-down images containing just enough code to run a single application." +{ $see-also "tools.memory" } ; ABOUT: "images" diff --git a/core/vocabs/loader/loader-docs.factor b/core/vocabs/loader/loader-docs.factor index d658a8e033..bc57c48a62 100644 --- a/core/vocabs/loader/loader-docs.factor +++ b/core/vocabs/loader/loader-docs.factor @@ -2,6 +2,18 @@ USING: vocabs vocabs.loader.private help.markup help.syntax words strings io ; IN: vocabs.loader +ARTICLE: "add-vocab-roots" "Working with code outside of the Factor source tree" +"You can work with code outside of the Factor source tree by adding additional directories to the list of vocabulary roots." +$nl +"There are three ways of doing this." +$nl +"The first way is to use an environment variable. Factor looks at the " { $snippet "FACTOR_ROOTS" } " environment variable for a list of " { $snippet ":" } "-separated paths (on Unix) or a list of " { $snippet ";" } "-separated paths (on Windows)." +$nl +"The second way is to create a configuration file. You can list additional vocabulary roots in a file that Factor reads at startup:" +{ $subsection "factor-roots" } +"Finally, you can add vocabulary roots dynamically using a word:" +{ $subsection add-vocab-root } ; + ARTICLE: "vocabs.roots" "Vocabulary roots" "The vocabulary loader searches for it in one of the root directories:" { $subsection vocab-roots } @@ -12,12 +24,8 @@ ARTICLE: "vocabs.roots" "Vocabulary roots" { { $snippet "extra" } " - additional contributed libraries." } { { $snippet "work" } " - a root for vocabularies which are not intended to be contributed back to Factor." } } -"You can store your own vocabularies in the " { $snippet "work" } " directory. You can also store code outside of the Factor source tree by making Factor aware of it first. There are two ways of doing this." -$nl -"You can list additional vocabulary roots in a file that Factor reads at startup:" -{ $subsection "factor-roots" } -"Or you can add them dynamically using a word:" -{ $subsection add-vocab-root } ; +"You can store your own vocabularies in the " { $snippet "work" } " directory." +{ $subsection "add-vocab-roots" } ; ARTICLE: "vocabs.loader" "Vocabulary loader" "The vocabulary loader is defined in the " { $vocab-link "vocabs.loader" } " vocabulary."