(まとめ) Terminal 周辺をうろうろする ニャ （自分用です）


![title.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106271/53531909-13bc-0e7c-519e-2361a0cff845.gif)



## 制御コード

![color.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106271/e17d8fc5-15fc-cf90-b5e8-ad71e8851da0.gif)



```sh
# format
Esc[xxxx
 \   `--- Sequences
  `--- Escape

# Set Graphics Mode:
Esc[Value;Value;Valuem
     `--- TextAttribute: 0-8
          ForegroundColor: 0-255
          BackgroundColor: 0-255
          ※ 8, 16, 256 色の指定方法で変わる

# Cursor:
Esc[ValueA/B/C/D
     \     `- A CursorUp/B CursorDown
      \       /C CursorForward/D CursorBackward
       `--- numboer of line or column
```


### 色と装飾

**256色**

```go
// ForegroundColor
print(fmt.Sprintf("\u001b[38;5;%dm %-4d", code, code))

// BackgroundColor
print(fmt.Sprintf("\u001b[48;5;%dm %-4d", code, code))
```

**装飾**

```go
println("\u001b[1m BOLD \u001b[0m\u001b[4m Underline \u001b[0m\u001b[7m Reversed \u001b[0m")
```



```go
import "fmt"

func main() {
	colors := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
	println("\u001b[31mHelloWorld")


	println("\u001b[31mForeground")
	for _, n := range colors {
		for _, m := range colors {
			code := 16 * n + m
			print(fmt.Sprintf("\u001b[38;5;%dm %-4d", code, code))
		}
		Println("\u001b[0m")
	}

	println("\u001b[31mHelloWorld")
	for _, n := range colors {
		for _, m := range colors {
			code := 16 * n + m
			print(fmt.Sprintf("\u001b[48;5;%dm %-4d", code, code))
		}
		println("\u001b[0m")
	}


	println("Text Decoration")
	println("\u001b[1m BOLD \u001b[0m\u001b[4m Underline \u001b[0m\u001b[7m Reversed \u001b[0m")

}
```

### Cursor

![cursor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106271/f3558a59-42cc-7e06-a142-1a7d645ee2f7.gif)


**数字**

```go
func loading(inc, max int) {
	num := 0
	for num <= max {
		print("\u001b[1000D")
		time.Sleep(500 * time.Millisecond)
		print(" ", num, "%")
		num += inc
	}
}
```

**プログレスバー**

```go
func barLoading(inc, max int) {
	num := 0
	charWidth := 25
	barSize := 4
	for num < max {
		time.Sleep(100 * time.Millisecond)
		width := (num + 1) / barSize
		bar := "[" + strings.Repeat("#", width) + strings.Repeat(" ", (charWidth-width)) + "]"
		print("\u001b[1000D" + bar)
		num += inc
	}
}
```

**複数行**

```go
type Progress struct {
	Percent int
	Max     int
}

func (p *Progress) Up(n int) {
	if p.Done() {
		return
	}
	p.Percent = int(math.Min(float64(p.Percent+n), float64(p.Max)))
}

func (p *Progress) Done() bool { return p.Percent >= p.Max }
func (p *Progress) Bar(charWidth int) string {
	width := int(math.Min(float64(p.Percent)/float64(p.Max)*float64(charWidth), float64(p.Max)))
	//print("Max>>", p.Max, ",Per:", p.Percent, ",Width>>", width)
	return "[" + strings.Repeat("#", width) + strings.Repeat(" ", (charWidth-width)) + "]"
}

type RunProgress []*Progress

func (p RunProgress) Unfinished() RunProgress {
	var rp RunProgress
	for _, ps := range p {
		if !ps.Done() {
			rp = append(rp, ps)
		}
	}
	return rp
}

func (p RunProgress) Done() bool { return len(p.Unfinished()) == 0 }
func (p RunProgress) Bar(charWidth int) {
	for _, ps := range p {
		println("\u001b[1000D" + ps.Bar(charWidth))
	}
}

func barsLoading(count, max int) {
	charWidth := 25
	inc := 10
	rps := make(RunProgress, count)
	for i, _ := range rps {
		rps[i] = &Progress{0, max}
	}
	rand.Seed(time.Now().UnixNano())
	println("Count:", count)
	rps.Bar(charWidth)
	for !rps.Done() {
		time.Sleep(100 * time.Millisecond)
		for _, ps := range rps.Unfinished() {
			ps.Up(rand.Intn(inc))
		}

		// move cursor
		print("\u001b[1000D")
		print(fmt.Sprintf("\u001b[%dA", count))
		// write
		rps.Bar(charWidth)
	}
}
```


## レコード

上記のgif は ttyrec, termrec で作っているのでここはasciinema を貼り付ける

<script id="asciicast-rtSmwB3JcfHbyHprahDsopmAj" src="https://asciinema.org/a/rtSmwB3JcfHbyHprahDsopmAj.js" async></script>

※ script タグだと左にプレビューしないので気をつけよう

### ttyrec

```bash
# record
$ ttyrec record.file.name
# play
$ ttyplay record.file.name
# to gif
$ ttygif -in record.file.name -out record.gif
```

### asciinema

```bash
# record
$ asciinema rec command.cast
# play
$ asciinema rec command.cast
# publish to asciinema (before run asciinema auth)
$ asciinema upload command.cast
```

### termrec

```bash
# record
$ termrec -f ttyrec rec.filename
# play
$ termplay -f ttycec rec.filename
# to git
$ ttygif -in rec.filename -out command.gif
```

## 画像表示

### Terminal で解決する

**Terminology**

```bash
# tycat <image file>
$ tycat free.png
```

※ terminal の recorder では無理

![tycat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106271/26badecc-2ecc-6501-ab74-76f10741961e.png)


**iTerm2**

macOS じゃないとだめなので省略



### Sixel

セットアップなどは[Sixel 情報 - ダメ出し Blog](https://fumiyas.github.io/vt/sixel.html)から深堀してください

**動作確認**

```bash
# img2sixel <file name>
$ img2sixel free.png
```

動作確認では xterm は動いている様子だが `img2sixel` では表示されず

![sixel-check.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106271/58a8a08a-0139-5cae-bf64-bf9988515621.png)


## Recap

- Windows 10 を買おうっと

## Reference

制御コード関連
- [ascii-table](http://ascii-table.com/ansi-escape-sequences.php)
- [Build your own Command Line with ANSI escape codes](http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html)

レコード関連
- [10 Best Free Linux Terminal Recorders](https://www.linuxlinks.com/terminalrecorders/)
- [ttyrec](http://0xcc.net/ttyrec/)
- [termrec](https://github.com/kilobyte/termrec)
- [asciinema](https://asciinema.org/)
- [ttygif](https://github.com/sugyan/ttygif)

ターミナルで画像表示関連
- [libsixel](https://github.com/saitoha/libsixel)
- [Sixel 情報 - ダメ出し Blog](https://fumiyas.github.io/vt/sixel.html)
- [【iTerm2】ターミナル上で画像を表示する方法](https://qiita.com/noraworld/items/ea59c37e48ac0977cc72)
- [hyper](https://hyper.is/)
- [terminology](http://www.enlightenment.org/about-terminology.md)