mirror of
https://github.com/sbrow/ps.git
synced 2025-12-29 18:47:38 -05:00
Changed readme template
Updated documentation
This commit is contained in:
40
.doc.template
Normal file
40
.doc.template
Normal file
@@ -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)
|
||||
|
||||
## <a name="pkg-overview">Overview</a>
|
||||
{{comment_md .Doc}}
|
||||
{{example_html $ ""}}
|
||||
|
||||
|
||||
## <a name="pkg-installation">Installation</a>
|
||||
```sh
|
||||
$ go get -u {{ .ImportPath }}
|
||||
```
|
||||
<!---
|
||||
{{if $.Examples}}
|
||||
#### <a name="pkg-examples">Examples</a>{{- range $.Examples}}
|
||||
* [{{example_name .Name}}](example_{{.Name}}_test.go){{- end}}{{- end}}
|
||||
{{end}}
|
||||
--->
|
||||
|
||||
{{ with .Notes}}
|
||||
{{ range $marker, $content := .}}
|
||||
## <a name="pkg-note-{{$marker}}">{{$marker}}</a>
|
||||
{{ range $key, $value := .}}
|
||||
`{{ $value.UID }}:` {{ $value.Body }}{{end}}{{end}}{{end}}
|
||||
## <a name="pkg-doc">Documentation</a>
|
||||
For full Documentation please visit https://godoc.org/{{.ImportPath}}
|
||||
- - -
|
||||
{{end}}
|
||||
|
||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
||||
@@ -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 }}
|
||||
```
|
||||
50
README.md
50
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)
|
||||
|
||||
## <a name="pkg-overview">Overview</a>
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
## <a name="pkg-installation">Installation</a>
|
||||
```sh
|
||||
$ go get -u github.com/sbrow/ps
|
||||
```
|
||||
<!---
|
||||
|
||||
#### <a name="pkg-examples">Examples</a>
|
||||
* [JSLayer](example_JSLayer_test.go)
|
||||
|
||||
--->
|
||||
|
||||
|
||||
|
||||
## <a name="pkg-note-TODO">TODO</a>
|
||||
|
||||
`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.
|
||||
|
||||
## <a name="pkg-doc">Documentation</a>
|
||||
For full Documentation please visit https://godoc.org/github.com/sbrow/ps
|
||||
- - -
|
||||
|
||||
|
||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
||||
|
||||
10
artlayer.go
10
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.
|
||||
|
||||
58
document.go
58
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
|
||||
}
|
||||
|
||||
31
interfaces.go
Normal file
31
interfaces.go
Normal file
@@ -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
|
||||
}
|
||||
46
layerset.go
46
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
|
||||
}
|
||||
|
||||
10
ps.go
10
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
|
||||
|
||||
50
ps_test.go
50
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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
## <a name="pkg-overview">Overview</a>
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## <a name="pkg-installation">Installation</a>
|
||||
```sh
|
||||
$ go get -u github.com/sbrow/ps/runner
|
||||
```
|
||||
<!---
|
||||
|
||||
|
||||
--->
|
||||
|
||||
|
||||
## <a name="pkg-doc">Documentation</a>
|
||||
For full Documentation please visit https://godoc.org/github.com/sbrow/ps/runner
|
||||
- - -
|
||||
|
||||
|
||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
||||
|
||||
@@ -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"},
|
||||
|
||||
Reference in New Issue
Block a user