Carolyn Van Slyck
Senior Software Engineer at Microsoft
$ emote add emoticon gopher --value ʕ •ᴥ•ʔ
added custom emoticon "gopher"
$ emote delete emoticon anxious
deleted custom emoticon "anxious"
$ emote add repo funk https://x.com/funk.json 🤔
$ emote add repo https://x.com/funk.json funk 😅
$ emote add repo funk --url https://x.com/funk.json ✅
$ emote repo delete funk moar-funk
deleted funk and moar-funk
$ emote list repos --output json
[
{
"name":"funk",
"url":"https://example.com/funk.json",
"size":100,
"created":"2019-07-15T14:32:22Z"
}
]
$ emote list repos
NAME CREATED SIZE
funk 2019-07-15T14:32:22Z 10
$ emote list repos
NAME CREATED SIZE
funk 10 days ago 10
$ emote list
NAME VALUE
shrug ¯\_(ツ)_/¯
tableflip (╯°□°)╯︵ ┻━┻
monocle ಠ_ರೃ
$ emote emoticon list
NAME VALUE
shrug ¯\_(ツ)_/¯
tableflip (╯°□°)╯︵ ┻━┻
monocle ಠ_ರೃ
$ emote --help
emote helps you react in realtime
Resources:
emoticons
repos
Aliased Commands:
list List emoticons
$ emote shrug
¯\_(ツ)_/¯ copied to the clipboard
$ emote shrug --dest slack
Your slack status is now ¯\_(ツ)_/¯
Use your judgement about the domain when breaking with the grammar
$ travis encrypt MY_SECRET_ENV=super_secret --add env
$ travis pubkey | jq -r .key > mykey.pub
$ echo 'MY_SECRET_ENV=super_secret' \
| openssl rsautl -encrypt -pubin -inkey mykey.pub \
| travis env add
$ emote shrug
¯\_(ツ)_/¯
The final code is available at github.com/carolynvs/emote
package main
import (
"fmt"
"os"
"github.com/atotto/clipboard"
"github.com/spf13/cobra"
)
func main() {
cmd := buildEmoteCommand()
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
func buildEmoteCommand() *cobra.Command {
emote := &cobra.Command{
Use: "emote",
}
emote.AddCommand(buildShrugCommand())
return emote
}
func buildShrugCommand() *cobra.Command {
var dest string
shrug := &cobra.Command{
Use: "shrug",
Run: func(cmd *cobra.Command, args []string) {
const emoticon = `¯\_(ツ)_/¯`
switch dest {
case "clipboard":
clipboard.WriteAll(emoticon)
fmt.Println(emoticon, "was copied to the clipboard")
default:
fmt.Println(emoticon)
}
},
}
shrug.Flags().StringVar(&dest, "dest", "clipboard", "Where to send your emoticon")
return shrug
}
package emoticons
import (
"fmt"
"github.com/atotto/clipboard"
)
type App struct {}
func (a *App) Shrug(dest string) {
const emoticon = `¯\_(ツ)_/¯`
switch dest {
case "clipboard":
clipboard.WriteAll(emoticon)
fmt.Println(emoticon, "was copied to the clipboard")
default:
fmt.Println(emoticon)
}
}
shrug := &cobra.Command{
Use: "shrug",
Run: func(cmd *cobra.Command, args []string) {
// Much Better! 👍
app := emoticons.App{}
app.Shrug(dest)
},
}
dest = "slack"
[emoticon]
shrug = '¯\_(ツ)_/¯'
tableflip = '(╯°□°)╯︵ ┻━┻'
dest: "slack"
emoticon:
shrug: '¯\_(ツ)_/¯'
tableflip: '(╯°□°)╯︵ ┻━┻'
{
"dest": "slack",
"emoticon": {
"shrug": "¯\_(ツ)_/¯",
"tableflip": "(╯°□°)╯︵ ┻━┻"
}
}
import "github.com/spf13/viper"
type App struct {
viper *viper.Viper
}
func New() (*App, error) {
v := viper.New()
v.AddConfigPath(".")
err := v.ReadInConfig()
if err != nil {
return nil, err
}
return &App{viper: v}, nil
}
func (a *App) Emote(name string, dest string) {
emoticon := a.viper.GetString("emoticon." + name)
...
}
func buildEmoteCommand() *cobra.Command {
app, err := emoticons.New()
if err != nil {
log.Fatal(err)
}
var dest string
emote := &cobra.Command{
Use: "emote",
Run: func(cmd *cobra.Command, args []string) {
emoticonName := args[0]
app.Emote(emoticonName, dest)
},
Args: cobra.ExactArgs(1),
}
...
package config
import (
"github.com/spf13/viper"
)
type Config struct {
Emoticon map[string]string
}
func Load() (*Config, error) {
v := viper.New()
v.AddConfigPath(".")
err := v.ReadInConfig()
if err != nil {
return nil, err
}
c := &Config{}
err = v.Unmarshal(c)
return c, err
}
type App struct {
Config *config.Config
}
func New() (*App, error) {
c, err := config.Load()
if err != nil {
return nil, err
}
return &App{Config: c}, nil
}
func (a *App) Emote(name string, dest string) {
// Yay! This feels more intuitive 👍
emoticon := a.Config.Emoticon[name]
type Config struct {
Dest string // Set by --dest or config file if not present
Emoticon map[string]string
}
func (c *Config) Load(cmd *cobra.Command) error {
...
// Bind the cobra flags to our config file
v.BindPFlags(cmd.Flags())
...
}
func buildEmoteCommand() *cobra.Command {
app := emoticons.New()
emote := &cobra.Command{
Use: "emote",
PreRunE: func(cmd *cobra.Command, args []string) error {
return app.Config.Load(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
emoticonName := args[0]
app.Emote(emoticonName)
},
Args: cobra.ExactArgs(1),
}
emote.Flags().StringVar(&app.Config.Dest, "dest", "clipboard", "Where to send your emoticon")
return emote
}
package emoticons
import (
"bytes"
"testing"
"github.com/carolynvs/emote/config"
"github.com/stretchr/testify/assert"
)
func TestApp_Emote(t *testing.T) {
const shrugEmoticon = `¯\_(ツ)_/¯`
out := &bytes.Buffer{}
app := &App{
Out: out,
Config: &config.Config{
Emoticon: map[string]string{"shrug": shrugEmoticon},
},
}
app.Emote("shrug")
assert.Contains(t, out.String(), shrugEmoticon)
}
Gopher artwork by Ashley McNamara
licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 License
Thank you, Steve Francia! 💖