Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
fmt
Search
ktr
January 25, 2018
Technology
0
3.7k
fmt
ktr
January 25, 2018
Tweet
Share
More Decks by ktr
See All by ktr
Designing libraries in Go way
ktr_0731
6
1.4k
Go Modules and Proxy Walkthrough
ktr_0731
8
26k
ソフトウェアの複雑さに立ち向かう技術 / Tackling software complexity
ktr_0731
0
160
Fuzzy finder as a Go library
ktr_0731
3
5.3k
つよくてニューゲーム / NewGame++
ktr_0731
0
890
やはり俺の Go アプリケーション設計はまちがっている。 / My Go Application Design Is Wrong, As I Expected
ktr_0731
13
3.4k
GopherCon2018
ktr_0731
2
1.7k
Evans: more expressive gRPC client
ktr_0731
2
410
自作 CLI ツールのワークフローとそれを支える技術 / the workflow of my CLI tool and technologies which supports it
ktr_0731
0
1.7k
Other Decks in Technology
See All in Technology
20240416_devopsdaystokyo
kzkmaeda
1
190
人間の尊厳、幸福、アクセシビリティ / 第116回「WEB TOUCH MEETING」アクセシビリティSP
nulabinc
PRO
2
180
疲弊しない!AWSセキュリティ統制の考え方 #devio_osakaday1
masahirokawahara
6
5.9k
Autonomous Database Cloud 技術詳細 / adb-s_technical_detail_jp
oracle4engineer
PRO
14
35k
「ふりかえりのふりかえり」をふりかえり、実のあるふりかえりにする
naitosatoshi
0
230
AWS を使う上で知っておきたいオンプレミス知識/aws-on-premise-essentials
emiki
1
4.2k
Discord とビルダー&チャットボットの使い方 / How to use Discord and Builder & Chatbots
ks91
PRO
0
130
ここが嬉しいABAC ここが辛いよABAC #再解説+補足編
masahirokawahara
1
230
プロデザ! BY リクルート vol.18_リクルートのリサーチ実践組織「リサーチブーストコミュニティ」
recruitengineers
PRO
3
240
ChatGPT for IT Service Management (IT Pro)
dahatake
4
260
GraphQL 成熟度モデルの紹介と、プロダクトに当てはめた事例 / GraphQL maturity model
mh4gf
4
190
Vertex AI を中心に 生成AIのアップデートを共有します
kaz1437
0
160
Featured
See All Featured
10 Git Anti Patterns You Should be Aware of
lemiorhan
646
57k
Web development in the modern age
philhawksworth
202
10k
Stop Working from a Prison Cell
hatefulcrawdad
266
19k
Building an army of robots
kneath
300
41k
WebSockets: Embracing the real-time Web
robhawkes
59
7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
20
1.6k
Build your cross-platform service in a week with App Engine
jlugia
225
17k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
186
16k
Intergalactic Javascript Robots from Outer Space
tanoku
266
26k
4 Signs Your Business is Dying
shpigford
175
21k
Fantastic passwords and where to find them - at NoRuKo
philnash
36
2.5k
Optimizing for Happiness
mojombo
370
69k
Transcript
fmt fmt 1
$ whoami $ whoami (id:|@)ktr_0731 サーバサイドエンジニ ア STEINS;GATE / 響け!ユーフォニア
ム 2
3
ktr0731/evans ktr0731/evans more expressive gRPC client more expressive gRPC client
4
fmt? fmt? コードフォーマッタ ソースコードを 強制的 に整形してくれ る 5
gofmt YAPF Prettier scalafmt etc. 6
gofmt を読む gofmt を読む golang/go/src/cmd/gofmt 7
前提環境 前提環境 golang/go master (157d8cfbc13fbc4c849075e905b0001fb248b5e6) 8
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go gofmtMain() gofmtMain() for i := 0; i <
flag.NArg(); i++ { path := flag.Arg(i) switch dir, err := os.Stat(path); { case err != nil: report(err) case dir.IsDir(): walkDir(path) // NOTE; call processFil default: if err := processFile(path, nil, os.St report(err) } } } 9
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() file, sourceAdj, indentAdj, err := parse(fileSet,
filename, sr if err != nil { return err } 10
cmd/gofmt/internal.go cmd/gofmt/internal.go parse() parse() parser.ParseFile file, err = parser.ParseFile(fset, filename,
psrc, parserMode) if err == nil { sourceAdj = func(src []byte, indent int) []byte { src = src[indent+len("package p\n"):] return bytes.TrimSpace(src) } 11
go/parser go/parser ParseFile() ParseFile() go/parser: 構文解析用パッケージ Go ソースコードから AST (
抽象構文木) を生 成 12
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() ast.SortImports(fileSet, file) if *simplifyAST { simplify(file)
} res, err := format(fileSet, file, sourceAdj, indentAdj, src, p if err != nil { return err } 13
cmd/gofmt/internal.go cmd/gofmt/internal.go format format var buf bytes.Buffer err := cfg.Fprint(&buf,
fset, file) if err != nil { return nil, err } return buf.Bytes(), nil 14
go/printer/printer.go go/printer/printer.go Fprint() → Fprint() → fprint() fprint() AST ノードを整形・出力するパッケージ
var p printer p.init(cfg, fset, nodeSizes) if err = p.printNode(node); err != nil { return } 15
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) case ast.Stmt: if _, ok := n.(*ast.LabeledStmt); ok { p.indent = 1 } p.stmt(n, false) case ast.Decl: p.decl(n) case ast.Spec: p.spec(n, 1, false) case []ast.Stmt: for _, s := range n { if _, ok := s.(*ast.LabeledStmt); ok { 16
printNode printNode AST を再帰的に辿り、 各ノードの持つ内容を整 形・出力する 17
例: 二項演算子のスペース 例: 二項演算子のスペース fmt.Println("Hello, "+"World") fmt.Println("Hello, " + "World")
18
AST AST の構造 の構造 0 *ast.CallExpr { 1 . Fun:
*ast.SelectorExpr { 2 . . X: *ast.Ident { 3 . . . NamePos: 1 4 . . . Name: "fmt" 5 . . . Obj: *ast.Object { 6 . . . . Kind: bad 7 . . . . Name: "" 8 . . . } 9 . . } 10 . . Sel: *ast.Ident { 11 . . . NamePos: 5 12 . . . Name: "Println" 13 . . } 14 . } 19
20
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) func (p *printer) expr(x ast.Expr) { const depth = 1 p.expr1(x, token.LowestPrec, depth) } 21
go/printer/nodes.go go/printer/nodes.go expr1() expr1() switch x := expr.(type) { case
*ast.BinaryExpr: if depth < 1 { p.internalError("depth < 1:", depth) depth = 1 } p.binaryExpr(x, prec1, cutoff(x, depth), depth) 22
go/printer/nodes.go go/printer/nodes.go binaryExpr() binaryExpr() ( 一部略) ( 一部略) // X
評価 p.expr1(x.X, prec, depth+diffPrec(x.X, prec)) if printBlank { // 追加 p.print(blank) } // "+" p.print(x.OpPos, x.Op) if printBlank { // 追加 p.print(blank) } // Y 評価 p.expr1(x.Y, prec+1, depth+1) 23
gofmt のフォーマットルール gofmt のフォーマットルール AST 生成までの過程で取り除かれるも の go/printer によって整形されるもの 24
AST AST 生成までの過程で取り除かれるもの 生成までの過程で取り除かれるもの 改行 スペー ス etc. 25
go/printer によって整形されるもの go/printer によって整形されるもの 二項演算子のスペース ( 前 述) 配列の最後の要素のカンマ etc.
[]string{"foo", "bar",} []string{"foo", "bar"} 26
似たようなのを実装してみる 似たようなのを実装してみる 27
ktr0731/markdownfmt ktr0731/markdownfmt 28
29
30
31
整形ルール 整形ルール 余計な改行・空白は取り除く テキストの最大長を 80 文字 に 32
整形ルール 整形ルール テキストの単語間のスペースは1つ に this is a text! this is
a text! 33
整形ルール 整形ルール 水平線 (hr) の上下に空 行 horizontal --- line horizontal
--- line 34
demo demo 35
これはデモ用のテキストです これはデモ用のテキストです this text is an example text for demonstration.
current version of markdownfmt accepts 80 charactors as the max width. so, maybe this text will be splitted to some lines. 36
まとめ まとめ AST なんでもできてすごい 特に Go は取得できる情報が多い AST を作れれば、フォーマットはそこまで難しく ない
意外と gofmt は読みやすい 37
参考 参考 printer - The Go Programming Language parser -
The Go Programming Language Go のための Go GitHub Flavored Markdown Spec 38