diff --git a/.doc.template b/.doc.template
new file mode 100644
index 0000000..99a6163
--- /dev/null
+++ b/.doc.template
@@ -0,0 +1,40 @@
+{{with .PDoc}}{{if $.IsMain}}> {{ base .ImportPath }}
+{{comment_md .Doc}}{{else}}# {{ .Name }}
+[](https://godoc.org/github.com/sbrow/{{ .Name }}) [](https://travis-ci.org/sbrow/{{ .Name }}) [](https://coveralls.io/github/sbrow/{{ .Name }}?branch=master) [](https://goreportcard.com/report/{{ .ImportPath }})
+
+`import "{{.ImportPath}}"`
+
+* [Overview](#pkg-overview)
+* [Installation](pkg-installation){{if $.Dirs}}
+* [Subdirectories](#pkg-subdirectories){{end}}{{ with .Notes}}{{ range $marker, $content := .}}
+* [{{$marker}}](#pkg-note-{{$marker}}){{end}}
+{{- end}}
+* [Documentation](#pkg-doc)
+
+## Overview
+{{comment_md .Doc}}
+{{example_html $ ""}}
+
+
+## Installation
+```sh
+$ go get -u {{ .ImportPath }}
+```
+
+
+{{ with .Notes}}
+{{ range $marker, $content := .}}
+## {{$marker}}
+{{ range $key, $value := .}}
+`{{ $value.UID }}:` {{ $value.Body }}{{end}}{{end}}{{end}}
+## Documentation
+For full Documentation please visit https://godoc.org/{{.ImportPath}}
+- - -
+{{end}}
+
+Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
diff --git a/.godocdown.template b/.godocdown.template
deleted file mode 100644
index 9b3ade2..0000000
--- a/.godocdown.template
+++ /dev/null
@@ -1,9 +0,0 @@
-# {{ .Name }}
-[](https://godoc.org/github.com/sbrow/{{ .Name }}) [](https://travis-ci.org/sbrow/{{ .Name }}) [](https://coveralls.io/github/sbrow/{{ .Name }}?branch=master) [](https://goreportcard.com/report/github.com/sbrow/{{ .Name }})
-
-{{ .EmitSynopsis }}
-
-## Installation
-```bash
-$ go get -u {{ .ImportPath }}
-```
\ No newline at end of file
diff --git a/README.md b/README.md
index afc4a43..76b194e 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,54 @@
# ps
[](https://godoc.org/github.com/sbrow/ps) [](https://travis-ci.org/sbrow/ps) [](https://coveralls.io/github/sbrow/ps?branch=master) [](https://goreportcard.com/report/github.com/sbrow/ps)
-Package ps is a rudimentary API between Adobe Photoshop CS5 and Golang. The
-interaction between the two is implemented using Javascript/VBScript.
+`import "github.com/sbrow/ps"`
+
+* [Overview](#pkg-overview)
+* [Installation](pkg-installation)
+* [Subdirectories](#pkg-subdirectories)
+* [TODO](#pkg-note-TODO)
+* [Documentation](#pkg-doc)
+
+## Overview
+Package ps is a rudimentary API between Adobe Photoshop CS5 and Golang.
+The interaction between the two is implemented using Javascript/VBScript.
+
+Use it to control Photoshop, edit documents, and perform batch operations.
Currently only supports Photoshop CS5 Windows x86_64.
-## Installation
-```bash
+
+
+
+
+## Installation
+```sh
$ go get -u github.com/sbrow/ps
```
+
+
+
+
+## TODO
+
+`sbrow:` (2) Make TextLayer a subclass of ArtLayer.
+
+`sbrow:` Reduce cylcomatic complexity
+
+`sbrow:` Does funky things when passed invalid layername.
+
+`sbrow:` Move to Document
+
+`sbrow:` get rid of the semicolon.
+
+## Documentation
+For full Documentation please visit https://godoc.org/github.com/sbrow/ps
+- - -
+
+
+Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
diff --git a/artlayer.go b/artlayer.go
index 332e685..7f91086 100644
--- a/artlayer.go
+++ b/artlayer.go
@@ -11,7 +11,7 @@ import (
// ArtLayer reflects some values from an Art Layer in a Photoshop document.
//
-// TODO: (2) Make TextLayer a subclass of ArtLayer.
+// TODO(sbrow): (2) Make TextLayer a subclass of ArtLayer.
type ArtLayer struct {
name string // The layer's name.
bounds [2][2]int // The corners of the layer's bounding box.
@@ -200,9 +200,9 @@ func (a *ArtLayer) Path() string {
}
// SetVisible makes the layer visible.
-func (a *ArtLayer) SetVisible(b bool) {
+func (a *ArtLayer) SetVisible(b bool) error {
if a.visible == b {
- return
+ return nil
}
a.visible = b
switch b {
@@ -214,8 +214,10 @@ func (a *ArtLayer) SetVisible(b bool) {
js := fmt.Sprintf("%s.visible=%v;",
strings.TrimRight(JSLayer(a.Path()), ";"), b)
if byt, err := DoJS("compilejs.jsx", js); err != nil {
- log.Println(string(byt), err)
+ log.Println(string(byt))
+ return err
}
+ return nil
}
// Visible returns whether or not the layer is currently hidden.
diff --git a/document.go b/document.go
index 1f66482..eec026b 100644
--- a/document.go
+++ b/document.go
@@ -71,6 +71,23 @@ func (d *Document) Height() int {
return d.height
}
+// ArtLayer returns the first top level ArtLayer matching
+// the given name.
+func (d *Document) ArtLayer(name string) *ArtLayer {
+ for _, lyr := range d.artLayers {
+ if lyr.name == name {
+ if Mode == 0 && !lyr.current {
+ err := lyr.Refresh()
+ if err != nil {
+ log.Panic(err)
+ }
+ }
+ return lyr
+ }
+ }
+ return nil
+}
+
// ArtLayers returns this document's ArtLayers, if any.
func (d *Document) ArtLayers() []*ArtLayer {
return d.artLayers
@@ -99,7 +116,7 @@ func (d *Document) LayerSet(name string) *LayerSet {
// ActiveDocument returns document currently focused in Photoshop.
//
-// TODO: Reduce cylcomatic complexity
+// TODO(sbrow): Reduce cylcomatic complexity
func ActiveDocument() (*Document, error) {
log.Println("Loading ActiveDoucment")
d := &Document{}
@@ -111,26 +128,32 @@ func ActiveDocument() (*Document, error) {
d.name = strings.TrimRight(string(byt), "\r\n")
if Mode != Safe {
err = d.Restore()
- return d, err
+ switch {
+ case os.IsNotExist(err):
+ log.Println("Previous version not found.")
+ case err == nil:
+ return d, err
+ default:
+ return nil, err
+
+ }
}
log.Println("Loading manually (This could take awhile)")
byt, err = DoJS("getActiveDoc.jsx")
if err != nil {
- log.Panic(err)
+ return nil, err
}
- err = json.Unmarshal(byt, &d)
- if err != nil {
+ if err = json.Unmarshal(byt, &d); err != nil {
d.Dump()
- log.Panic(err)
+ return nil, err
}
for _, lyr := range d.artLayers {
lyr.SetParent(d)
}
for i, set := range d.layerSets {
var s *LayerSet
- s, err = NewLayerSet(set.Path()+"/", d)
- if err != nil {
- log.Fatal(err)
+ if s, err = NewLayerSet(set.Path()+"/", d); err != nil {
+ return nil, err
}
d.layerSets[i] = s
s.SetParent(d)
@@ -190,3 +213,20 @@ func (d *Document) Dump() {
log.Println(err)
}
}
+
+// MustExist returns a Layer from the set with the given name, and
+// panics if it doesn't exist.
+//
+// If there is a LayerSet and an ArtLayer with the same name,
+// it will return the LayerSet.
+func (d *Document) MustExist(name string) Layer {
+ set := d.LayerSet(name)
+ if set == nil {
+ lyr := d.ArtLayer(name)
+ if lyr == nil {
+ log.Panicf("no Layer found at \"%s%s\"", d.Path(), name)
+ }
+ return lyr
+ }
+ return set
+}
diff --git a/interfaces.go b/interfaces.go
new file mode 100644
index 0000000..e454760
--- /dev/null
+++ b/interfaces.go
@@ -0,0 +1,31 @@
+package ps
+
+// Group represents a Document or LayerSet.
+type Group interface {
+ Name() string
+ Parent() Group
+ SetParent(Group)
+ Path() string
+ ArtLayer(name string) *ArtLayer
+ LayerSet(name string) *LayerSet
+ ArtLayers() []*ArtLayer
+ LayerSets() []*LayerSet
+ MustExist(name string) Layer
+ MarshalJSON() ([]byte, error)
+ UnmarshalJSON(b []byte) error
+}
+
+// Layer represents an ArtLayer or LayerSet Object.
+type Layer interface {
+ Bounds() [2][2]int
+ MarshalJSON() ([]byte, error)
+ Name() string
+ Parent() Group
+ Path() string
+ Refresh() error
+ SetParent(g Group)
+ SetPos(x, y int, bound string)
+ SetVisible(b bool) error
+ UnmarshalJSON(b []byte) error
+ Visible() bool
+}
diff --git a/layerset.go b/layerset.go
index 6a17e79..8628c6f 100644
--- a/layerset.go
+++ b/layerset.go
@@ -2,24 +2,11 @@ package ps
import (
"encoding/json"
- "errors"
"fmt"
"log"
"strings"
)
-// Group represents a Document or LayerSet.
-type Group interface {
- Name() string
- Parent() Group
- SetParent(Group)
- Path() string
- ArtLayers() []*ArtLayer
- LayerSets() []*LayerSet
- MarshalJSON() ([]byte, error)
- UnmarshalJSON(b []byte) error
-}
-
// LayerSet holds a group of Layer objects and a group of LayerSet objects.
type LayerSet struct {
name string
@@ -95,7 +82,6 @@ func (l *LayerSet) ArtLayers() []*ArtLayer {
// ArtLayer returns the first top level ArtLayer matching
// the given name.
-// TODO: Does funky things when passed invalid layername.
func (l *LayerSet) ArtLayer(name string) *ArtLayer {
for _, lyr := range l.artLayers {
if lyr.name == name {
@@ -113,12 +99,7 @@ func (l *LayerSet) ArtLayer(name string) *ArtLayer {
return lyr
}
}
- lyr := l.ArtLayer(name)
- fmt.Println(lyr)
- if lyr == nil {
- log.Panic(errors.New("layer not found"))
- }
- return lyr
+ return nil
}
// LayerSets returns the LayerSets contained within
@@ -138,6 +119,23 @@ func (l *LayerSet) LayerSet(name string) *LayerSet {
return nil
}
+// MustExist returns a Layer from the set with the given name, and
+// panics if it doesn't exist.
+//
+// If there is a LayerSet and an ArtLayer with the same name,
+// it will return the LayerSet.
+func (l *LayerSet) MustExist(name string) Layer {
+ set := l.LayerSet(name)
+ if set == nil {
+ lyr := l.ArtLayer(name)
+ if lyr == nil {
+ log.Panicf("no Layer found at \"%s%s\"", l.Path(), name)
+ }
+ return lyr
+ }
+ return set
+}
+
// Bounds returns the furthest corners of the LayerSet.
func (l LayerSet) Bounds() [2][2]int {
return l.bounds
@@ -165,7 +163,6 @@ func (l *LayerSet) Path() string {
func NewLayerSet(path string, g Group) (*LayerSet, error) {
path = strings.Replace(path, "//", "/", -1)
byt, err := DoJS("getLayerSet.jsx", JSLayer(path), JSLayerMerge(path))
- fmt.Println(JSLayer(path), JSLayerMerge(path))
if err != nil {
return nil, err
}
@@ -300,3 +297,10 @@ func (l *LayerSet) Refresh() error {
l.current = true
return nil
}
+
+func (l *LayerSet) Set(ll *LayerSet) {
+ if ll == nil {
+ panic("AHHHHHH")
+ }
+ l = ll
+}
diff --git a/ps.go b/ps.go
index 559383d..d895e92 100644
--- a/ps.go
+++ b/ps.go
@@ -1,8 +1,10 @@
-//go:generate godocdown -output=README.md
+//go:generate sh -c "godoc2md -template ./.doc.template github.com/sbrow/ps > README.md"
// Package ps is a rudimentary API between Adobe Photoshop CS5 and Golang.
// The interaction between the two is implemented using Javascript/VBScript.
//
+// Use it to control Photoshop, edit documents, and perform batch operations.
+//
// Currently only supports Photoshop CS5 Windows x86_64.
package ps
@@ -38,7 +40,7 @@ func ApplyDataset(name string) error {
}
// Close closes the active document in Photoshop, using the given save option.
-// TODO: Move to Document
+// TODO(sbrow): Move to Document
func Close(save SaveOption) error {
_, err := runner.Run("close", fmt.Sprint(save))
return err
@@ -104,7 +106,7 @@ func Init() error {
// The output always ends with a semicolon, so if you want to access a specific
// property of the layer, you'll have to trim the output before concatenating.
//
-// TODO: get rid of the semicolon.
+// TODO(sbrow): get rid of the semicolon.
func JSLayer(path string) string {
pth := strings.Split(path, "/")
js := "app.activeDocument"
@@ -138,7 +140,7 @@ func Open(path string) error {
return err
}
-// Quit exits Photoshop, closing all open docuemnts using the given save option.
+// Quit exits Photoshop, closing all open documents using the given save option.
func Quit(save SaveOption) error {
_, err := runner.Run("quit", fmt.Sprint(save))
return err
diff --git a/ps_test.go b/ps_test.go
index 66a431b..df85904 100644
--- a/ps_test.go
+++ b/ps_test.go
@@ -1,19 +1,14 @@
-// TODO: Update package tests.
+// TODO(sbrow): Update package tests.
package ps
import (
- "encoding/json"
"fmt"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "regexp"
"testing"
"github.com/sbrow/ps/runner"
)
+/*
var testDoc string
func init() {
@@ -34,7 +29,9 @@ func TestInit(t *testing.T) {
if testing.Short() {
t.Skip("Skipping \"TestStart\"")
}
- Quit(2)
+ if err := Quit(2); err != nil {
+ log.Println("error:", err)
+ }
if err := Init(); err != nil {
t.Error(err)
}
@@ -44,6 +41,9 @@ func TestOpen(t *testing.T) {
if testing.Short() {
t.Skip("Skipping \"TestOpen\"")
}
+ if err := Init(); err != nil {
+ t.Fatal(err)
+ }
if err := Open(testDoc); err != nil {
log.Println(testDoc)
t.Fatal(err)
@@ -54,8 +54,12 @@ func TestClose(t *testing.T) {
if testing.Short() {
t.Skip("Skipping \"TestClose\"")
}
- err := Close(DoNotSaveChanges)
- if err != nil {
+ var err error
+ if err = Open(testDoc); err != nil {
+ log.Println(testDoc)
+ t.Fatal(err)
+ }
+ if err = Close(DoNotSaveChanges); err != nil {
t.Fatal(err)
}
}
@@ -139,6 +143,9 @@ func TestLayerSet(t *testing.T) {
}
}
func TestMove(t *testing.T) {
+ if err := Open(testDoc); err != nil {
+ t.Fatal(err)
+ }
d, err := ActiveDocument()
if err != nil {
t.Fatal(err)
@@ -282,19 +289,18 @@ func TestTextItem(t *testing.T) {
}
}
- /* byt := []byte(`{"Name": "lyr", "TextItem": {"Contents": "lyr", "Size": 12.000, "Font": "ArialItalic"}}`)
- lyr := &ArtLayer{}
- // byt := []byte(`{"Name": "lyr"}`)
- // lyr := &TextItem{}
- err := lyr.UnmarshalJSON(byt)
- fmt.Printf("%+v\n", lyr)
- fmt.Println(lyr.TextItem)
- if err != nil {
- t.Fatal(err)
- }
- */
+ byt := []byte(`{"Name": "lyr", "TextItem": {"Contents": "lyr", "Size": 12.000, "Font": "ArialItalic"}}`)
+ lyr := &ArtLayer{}
+ // byt := []byte(`{"Name": "lyr"}`)
+ // lyr := &TextItem{}
+ err := lyr.UnmarshalJSON(byt)
+ fmt.Printf("%+v\n", lyr)
+ fmt.Println(lyr.TextItem)
+ if err != nil {
+ t.Fatal(err)
+ }
}
-
+*/
func BenchmarkDoc_Go(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := ActiveDocument()
diff --git a/runner/README.md b/runner/README.md
index db98fe5..ae56712 100644
--- a/runner/README.md
+++ b/runner/README.md
@@ -1,11 +1,35 @@
# runner
-[](https://godoc.org/github.com/sbrow/runner) [](https://travis-ci.org/sbrow/runner) [](https://coveralls.io/github/sbrow/runner?branch=master) [](https://goreportcard.com/report/github.com/sbrow/runner)
+[](https://godoc.org/github.com/sbrow/runner) [](https://travis-ci.org/sbrow/runner) [](https://coveralls.io/github/sbrow/runner?branch=master) [](https://goreportcard.com/report/github.com/sbrow/ps/runner)
-Package runner runs the non-go code that Photoshop understands, and passes it to
-back to the go program. Currently, this is primarily implemented through Adobe
-Extendscript, but hopefully in the future it will be upgraded to a C++ plugin.
+`import "github.com/sbrow/ps/runner"`
-## Installation
-```bash
+* [Overview](#pkg-overview)
+* [Installation](pkg-installation)
+* [Documentation](#pkg-doc)
+
+## Overview
+Package runner runs the non-go code that Photoshop understands,
+and passes it to back to the go program. Currently, this is
+primarily implemented through Adobe Extendscript, but hopefully
+in the future it will be upgraded to a C++ plugin.
+
+
+
+
+
+## Installation
+```sh
$ go get -u github.com/sbrow/ps/runner
```
+
+
+
+## Documentation
+For full Documentation please visit https://godoc.org/github.com/sbrow/ps/runner
+- - -
+
+
+Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
diff --git a/runner/runner.go b/runner/runner.go
index ac30e51..5d62c08 100644
--- a/runner/runner.go
+++ b/runner/runner.go
@@ -1,4 +1,4 @@
-//go:generate godocdown -template ../.godocdown.template -output=README.md
+//go:generate sh -c "godoc2md -template ../.doc.template github.com/sbrow/ps/runner > README.md"
// Package runner runs the non-go code that Photoshop understands,
// and passes it to back to the go program. Currently, this is
@@ -16,7 +16,8 @@ import (
"strings"
)
-// Windows is the runner for Visual Basic Scripts.
+// Windows is the runner Windows Operating Systems.
+// It runs Visual Basic Scripts.
var Windows = Runner{
Cmd: "cscript.exe",
Args: []string{"/nologo"},