LoginSignup
67
7
この記事誰得? 私しか得しないニッチな技術で記事投稿!

( ´∀`) < モナーがechoしてくれる `monaco`って言うコマンドを作りました

Last updated at Posted at 2023-07-18

モナーって知ってますか?

モナーは某ネット掲示板の2ちゃんねる(今は5ちゃんねる)で愛されているアスキーアートの1つで
「お前が言うな」 や 「お前も一緒やろ」 的なニュアンスで使われているやつです

制作に至った経緯

〜ある日の深夜〜
私 「モナーがechoしたら面白いんじゃね?」
私 「モナーがecho、モナーがエコー、モナーエコー、モナコ、monaco でええやん」
と言う思いつきと深夜テンションのままに作ったコマンドになります
開発してから結構な日数が経っているんですが供養させてください👻

ただ、1つだけ問題がMSのOSSの Monaco Editor と名前が被ってるんですよね

リポジトリはこちら

インストール方法

インストールはGoからにしか対応していません...orz <スミマセン

go install github.com/chihiros/monaco@latest

使い方

$ monaco オマエモナー

 ∧___∧   /‾‾‾‾‾‾‾‾‾‾
( ´∀ `) < オマエモナー
(     )  \__________
|  |  |
(__)__)
  • 普通の echo と同じように変数の中身を表示することもできます
  • 会話の吹き出しなんですが、長い文章を入力した場合は長さが足らなくなる場合がありますm(_ _;)m
    • 特に日本語と英語が交じるとダメです
  • レイアウトが崩れるのを防ぐため、改行には対応できていませんm(_ _;)m
    image.png

技術スタック

言語:Go
フレームワーク:cobra

コードの概要

monacoの構成はざっくりとこのような感じになっています

image.png

asciiart/ascii_art.go ってやつでAAを作成しています
コード全体としてはこんな感じ

asciiart/ascii_art.go
package asciiart

import (
	"bytes"
	"embed"
	"fmt"
	"log"
	"os/exec"
	"text/template"
)

//go:embed template/*.tpl
var templates embed.FS

type AsciiArt struct {
	Name string
	Args []string
}

func NewAsciiArt(args []string) *AsciiArt {
	return &AsciiArt{
		Name: "mona_front",
		Args: args,
	}
}

func getAaTemplate() *template.Template {
	funcMap := template.FuncMap{
		"printOverLine": func(args []string) string {
			return printLine("‾", args)
		},
		"printUnderLine": func(args []string) string {
			return printLine("_", args)
		},
		"echo": func(args []string) string {
			cmd := exec.Command("echo", args...)
			var out bytes.Buffer
			cmd.Stdout = &out
			err := cmd.Run()
			if err != nil {
				log.Fatal(err)
			}
			return out.String()
		},
	}

	TEMPLATE_PATH := "template/*.tpl"
	tpl := template.Must(template.New("").Funcs(funcMap).ParseFS(templates, TEMPLATE_PATH))

	return tpl
}

func (a *AsciiArt) Print() {
	tpl := getAaTemplate()
	var buf bytes.Buffer

	err := tpl.ExecuteTemplate(&buf, a.Name, a.Args)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(buf.String())
}

部分的に解説

//go:embed template/*.tpl
var templates embed.FS
  • ビルドしたときに、テンプレートの中身をバイナリに入れ込みたいので go:embed しています
type AsciiArt struct {
	Name string
	Args []string
}
  • Name は何種類かのAAに対応させたかったので用意しています(用意しているだけですorz)
  • Args にはTerminalで入力された引数が入ります
funcMap := template.FuncMap{
    "printOverLine": func(args []string) string {
        return printLine("‾", args)
    },
    "printUnderLine": func(args []string) string {
        return printLine("_", args)
    },
    "echo": func(args []string) string {
        cmd := exec.Command("echo", args...)
        var out bytes.Buffer
        cmd.Stdout = &out
        err := cmd.Run()
        if err != nil {
            log.Fatal(err)
        }
        return out.String()
    },
}
  • テンプレート内で利用できる関数の定義をしています
{{ block "mona_front" . }}
 ∧___∧   /{{ printOverLine . }}
( ´∀ `) < {{ echo . -}}
(     )  \{{ printUnderLine . }}
|  |  |
(__)__)
{{ end }}
  • テンプレートの中ではこのような感じで関数を利用することができます
func (a *AsciiArt) Print() {
	tpl := getAaTemplate()
	var buf bytes.Buffer

	err := tpl.ExecuteTemplate(&buf, a.Name, a.Args)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(buf.String())
}
  • Printメソッド:AAの作成から表示まで行ってくれる関数です
cmd/root.go
aa := asciiart.NewAsciiArt(args)
aa.Print()
  • こちらのコードからPrintメソッドが読み出されてAAが表示されます

最後に

image.png

67
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
7