diff --git a/.gitignore b/.gitignore
index 2f565e7..d5130d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ geo-shell.iml
geo-shell.log
dependency-reduced-pom.xml
examples/raster.tif.aux.xml
+src/main/docs/output
diff --git a/pom.xml b/pom.xml
index 4b24b90..5156897 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,6 +9,10 @@
http://maven.apache.org
UTF-8
+ 1.5.7.1
+ 1.6.1
+ 1.5.0-alpha.16
+ 9.2.5.0
@@ -205,6 +209,77 @@
+
+ org.asciidoctor
+ asciidoctor-maven-plugin
+ ${asciidoctor.maven.plugin.version}
+
+
+ org.asciidoctor
+ asciidoctorj-pdf
+ ${asciidoctorj.pdf.version}
+
+
+ org.jruby
+ jruby-complete
+ ${jruby.version}
+
+
+ org.asciidoctor
+ asciidoctorj
+ ${asciidoctorj.version}
+
+
+
+ src/main/docs
+
+
+
+ output-html
+ package
+
+ process-asciidoc
+
+
+ html5
+ coderay
+ true
+ ./images
+
+ ${project.basedir}/src/main/groovy
+ ${project.basedir}/src/main/docs
+ ./images
+ left
+ 4
+ font
+ true
+
+ -
+ true
+
+
+
+
+ generate-pdf-doc
+ package
+
+ process-asciidoc
+
+
+ pdf
+ rouge
+
+ ${project.basedir}/src/main/groovy
+ font
+
+
+
+ -
+
+
+
+
+
diff --git a/src/main/docs/index.adoc b/src/main/docs/index.adoc
new file mode 100644
index 0000000..929c646
--- /dev/null
+++ b/src/main/docs/index.adoc
@@ -0,0 +1,8 @@
+= geo-shell
+Jared Erickson
+v0.7-SNAPSHOT
+ifndef::imagesdir[:imagesdir: images]
+
+include::intro.adoc[]
+
+include::workspace.adoc[]
\ No newline at end of file
diff --git a/src/main/docs/intro.adoc b/src/main/docs/intro.adoc
new file mode 100644
index 0000000..c9e4713
--- /dev/null
+++ b/src/main/docs/intro.adoc
@@ -0,0 +1,20 @@
+ifndef::imagesdir[:imagesdir: images]
+
+== Introduction
+
+geo-shell is an interactive shell for geospatial analysis.
+
+geo-shell has modules for dealing with *vectors*, *rasters*, *tiles*, *maps*, and *styles*.
+
+For *vector* layers, you can use *workspace* commands access layers of spatial data
+in datasets like shapefiles, geopackages, or postgis databases. With *layer* commands
+you can perform geoprocessing functions like calculating centroids or buffer features.
+
+For *raster* layers, you can use *format* commands access individual rasters from geotifs or world images.
+With *raster* commands you can perform mosaic, raster algebra, or crop functions.
+
+The *tile* commands let you create tile layers, get tiles, and get rasters from tiles.
+
+The *style* commands let you create styles for vector layers and raster.
+
+The *map* commands allow you to visualize vector, raster, and tile layers.
\ No newline at end of file
diff --git a/src/main/docs/workspace.adoc b/src/main/docs/workspace.adoc
new file mode 100644
index 0000000..02a7ec7
--- /dev/null
+++ b/src/main/docs/workspace.adoc
@@ -0,0 +1,46 @@
+ifndef::imagesdir[:imagesdir: images]
+
+== Workspace
+
+Workspaces hold vector layers. A Workspace can be a GeoPackage database,
+a directory of Shapefiles, or a PostGIS database.
+
+=== Basics
+
+You can open, close, and list Workspaces. The eariest Workspace to open
+is an in memory Workspace.
+
+.Open a Workspace
+include::output/workspace_basics_open_command.txt[]
+include::output/workspace_basics_open_result.txt[]
+
+You can open a Workspace with --params or connection parameters.
+You can give it a name with --name flag.
+
+.List open Workspaces
+include::output/workspace_basics_list_command.txt[]
+include::output/workspace_basics_list_result.txt[]
+
+Listing open Workspaces give you the name and the type Workspace.
+
+.Close a Workspace
+include::output/workspace_basics_close_command.txt[]
+include::output/workspace_basics_close_result.txt[]
+
+Once you close a Workspace by name it will no longer appear with the list command.
+
+=== Layers
+
+In this example, we will open a GeoPackage database filled with data from Natural Earth.
+
+.Open a Workspace
+include::output/workspace_layers_open_command.txt[]
+include::output/workspace_layers_open_result.txt[]
+
+.List open Workspaces
+include::output/workspace_layers_layers_command.txt[]
+include::output/workspace_layers_layers_result.txt[]
+
+.Close a Workspace
+include::output/workspace_layers_close_command.txt[]
+include::output/workspace_layers_close_result.txt[]
\ No newline at end of file
diff --git a/src/test/groovy/org/geoshell/docs/WorkspaceDocTest.groovy b/src/test/groovy/org/geoshell/docs/WorkspaceDocTest.groovy
new file mode 100644
index 0000000..8c64d79
--- /dev/null
+++ b/src/test/groovy/org/geoshell/docs/WorkspaceDocTest.groovy
@@ -0,0 +1,95 @@
+package org.geoshell.docs
+
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.springframework.shell.Bootstrap
+import org.springframework.shell.core.CommandResult
+import org.springframework.shell.core.JLineShellComponent
+
+class WorkspaceDocTest {
+
+ private JLineShellComponent shell;
+
+ @Before
+ void before() throws InterruptedException {
+ Bootstrap bootstrap = new Bootstrap()
+ shell = bootstrap.getJLineShellComponent()
+ }
+
+ @After
+ void after() {
+ shell.stop()
+ }
+
+
+ @Test
+ void workspaceOpenListClose() {
+ run([
+ "workspace_basics_open": "workspace open --name mem --params memory",
+ "workspace_basics_list": "workspace list",
+ "workspace_basics_close": "workspace close --name mem"
+ ])
+ }
+
+ @Test
+ void workspaceLayers() {
+ run([
+ "workspace_layers_open": "workspace open --name naturalearth --params src/test/resources/naturalearth.gpkg",
+ "workspace_layers_layers": "workspace layers --name naturalearth",
+ "workspace_layers_close": "workspace close --name naturalearth"
+ ])
+ }
+
+ void run(Map commands) {
+ commands.each { String name, String command ->
+ run(name, command)
+ }
+ }
+
+ String run(String name, String cmd) {
+ CommandResult result = shell.executeCommand(cmd)
+ writeFile("${name}_command", processCommand(cmd))
+ writeFile("${name}_result", processOutput(result.result.toString()))
+ }
+
+ void writeFile(String name, String text) {
+ File dir = new File("src/main/docs/output")
+ if (!dir.exists()) {
+ dir.mkdir()
+ }
+ File file = new File(dir, "${name}.txt")
+ file.text = text
+ }
+
+ String processCommand(String cmd) {
+
+ String name
+ String params
+
+ int firstParam = cmd.indexOf("--")
+ if (firstParam > -1) {
+ name = cmd.substring(0,firstParam).trim()
+ params = cmd.substring(firstParam).trim()
+ } else {
+ name = cmd.trim()
+ params = ""
+ }
+ String styledName = "[navy]*${name}*"
+ String styleParams = params.trim() == "" ? "" : params.split(" ").collect { String param ->
+ param = param.trim()
+ if (param.startsWith("--")) {
+ "[gray]#${param}#"
+ } else {
+ "[silver]#${param}#"
+ }
+ }.join(' ')
+
+ "[blue]#geo-shell># ${styledName} ${styleParams} +"
+ }
+
+ String processOutput(String output) {
+ output.split("\n").collect { "[green]#${it}# +" }.join("\n")
+ }
+
+}
diff --git a/src/test/resources/naturalearth.gpkg b/src/test/resources/naturalearth.gpkg
new file mode 100644
index 0000000..9d849e5
Binary files /dev/null and b/src/test/resources/naturalearth.gpkg differ