Skip to content

Commit

Permalink
feat: implement copy + paste command (#376)
Browse files Browse the repository at this point in the history
* feat: implement copy and paste commands
---------

Co-authored-by: Maas Lalani <[email protected]>
  • Loading branch information
Delta456 and maaslalani authored Oct 3, 2023
1 parent c059a98 commit 643733a
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ frames/
manpages
completions
dist
vhs
vhs
.idea/
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ There are a few basic types of VHS commands:
* [`Hide`](#hide): hide commands from output
* [`Show`](#show): stop hiding commands from output
* [`Screenshot`](#screenshot): screenshot the current frame
* [`Copy/Paste`](#copy--paste): copy and paste text from clipboard.

### Output

Expand Down Expand Up @@ -714,6 +715,17 @@ The `Screenshot` command captures the current frame (png format).
Screenshot examples/screenshot.png
```

### Copy / Paste

The `Copy` and `Paste` copy and paste the string from clipboard.

```elixir
Copy "https://github.com/charmbracelet"
Type "open "
Sleep 500ms
Paste
```

***

## Continuous Integration
Expand Down
25 changes: 25 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"github.com/atotto/clipboard"

Check failure on line 6 in command.go

View workflow job for this annotation

GitHub Actions / lint

File is not `goimports`-ed (goimports)
"io"
"os"
"os/exec"
Expand Down Expand Up @@ -42,6 +43,8 @@ var CommandTypes = []CommandType{ //nolint: deadcode
UP,
SOURCE,
SCREENSHOT,
COPY,
PASTE,
}

// String returns the string representation of the command.
Expand Down Expand Up @@ -81,6 +84,8 @@ var CommandFuncs = map[CommandType]CommandFunc{
ALT: ExecuteAlt,
ILLEGAL: ExecuteNoop,
SCREENSHOT: ExecuteScreenshot,
COPY: ExecuteCopy,
PASTE: ExecutePaste,
}

// Command represents a command with options and arguments.
Expand Down Expand Up @@ -259,6 +264,26 @@ func ExecuteOutput(c Command, v *VHS) {
}
}

func ExecuteCopy(c Command, _ *VHS) {

Check warning on line 267 in command.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported function ExecuteCopy should have comment or be unexported (revive)
_ = clipboard.WriteAll(c.Args)
}

func ExecutePaste(_ Command, v *VHS) {

Check warning on line 271 in command.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported function ExecutePaste should have comment or be unexported (revive)
clip, err := clipboard.ReadAll()
if err != nil {
return
}
for _, r := range clip {
k, ok := keymap[r]
if ok {
_ = v.Page.Keyboard.Type(k)
} else {
_ = v.Page.MustElement("textarea").Input(string(r))
v.Page.MustWaitIdle()
}
}
}

// Settings maps the Set commands to their respective functions.
var Settings = map[string]CommandFunc{
"FontFamily": ExecuteSetFontFamily,
Expand Down
Binary file added examples/clipboard.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions examples/clipboard.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Output examples/commands/clipboard.gif

Set FontSize 42
Set Height 225

Copy "https://github.com/charmbracelet"
Type "open "
Sleep 500ms
Paste
Sleep 3s
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
require (
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/caarlos0/sshmarshal v0.1.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
Expand Down
2 changes: 2 additions & 0 deletions man.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ The following is a list of all possible commands in VHS:
* %Space% [repeat]
* %Source% <path>.tape
* %Screenshot% <path>.png
* %Copy% "<string>"
* %Paste%
`

manOutput = `The Output command instructs VHS where to save the output of the recording.
Expand Down
42 changes: 42 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ func (p *Parser) parseCommand() Command {
return p.parseSource()
case SCREENSHOT:
return p.parseScreenshot()
case COPY:
return p.parseCopy()
case PASTE:
return p.parsePaste()
default:
p.errors = append(p.errors, NewError(p.cur, "Invalid command: "+p.cur.Literal))
return Command{Type: ILLEGAL}
Expand Down Expand Up @@ -395,6 +399,44 @@ func (p *Parser) parseType() Command {
return cmd
}

// parseCopy parses a copy command
// A copy command takes a string to the clipboard
//
// Copy "string"
func (p *Parser) parseCopy() Command {
cmd := Command{Type: COPY}

if p.peek.Type != STRING {
p.errors = append(p.errors, NewError(p.peek, p.cur.Literal+" expects string"))
}
for p.peek.Type == STRING {
p.nextToken()
cmd.Args += p.cur.Literal

// If the next token is a string, add a space between them.
// Since tokens must be separated by a whitespace, this is most likely
// what the user intended.
//
// Although it is possible that there may be multiple spaces / tabs between
// the tokens, however if the user was intending to type multiple spaces
// they would need to use a string literal.

if p.peek.Type == STRING {
cmd.Args += " "
}
}
return cmd
}

// parsePaste parses paste command
// Paste Command the string from the clipboard buffer.
//
// Paste
func (p *Parser) parsePaste() Command {
cmd := Command{Type: PASTE}
return cmd
}

// parseSource parses source command.
// Source command takes a tape path to include in current tape.
//
Expand Down
23 changes: 13 additions & 10 deletions token.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ const (
RIGHT = "RIGHT"
UP = "UP"

HIDE = "HIDE"
OUTPUT = "OUTPUT"
REQUIRE = "REQUIRE"
SET = "SET"
SHOW = "SHOW"
SOURCE = "SOURCE"
TYPE = "TYPE"
SCREENSHOT = "SCREENSHOT"

HIDE = "HIDE"
OUTPUT = "OUTPUT"
REQUIRE = "REQUIRE"
SET = "SET"
SHOW = "SHOW"
SOURCE = "SOURCE"
TYPE = "TYPE"
SCREENSHOT = "SCREENSHOT"
COPY = "COPY"
PASTE = "PASTE"
SHELL = "SHELL"
FONT_FAMILY = "FONT_FAMILY" //nolint:revive
FONT_SIZE = "FONT_SIZE" //nolint:revive
Expand Down Expand Up @@ -142,6 +143,8 @@ var keywords = map[string]TokenType{
"true": BOOLEAN,
"false": BOOLEAN,
"Screenshot": SCREENSHOT,
"Copy": COPY,
"Paste": PASTE,
}

// IsSetting returns whether a token is a setting.
Expand All @@ -163,7 +166,7 @@ func IsCommand(t TokenType) bool {
case TYPE, SLEEP,
UP, DOWN, RIGHT, LEFT, PAGEUP, PAGEDOWN,
ENTER, BACKSPACE, DELETE, TAB,
ESCAPE, HOME, INSERT, END, CTRL, SOURCE, SCREENSHOT:
ESCAPE, HOME, INSERT, END, CTRL, SOURCE, SCREENSHOT, COPY, PASTE:
return true
default:
return false
Expand Down

0 comments on commit 643733a

Please sign in to comment.