Slide 1

Slide 1 text

Prettier for Ruby github.com/prettier/plugin-ruby twitter.com/kddeisz

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

github.com/prettier/plugin-ruby twitter.com/kddeisz What is prettier? • A language-agnostic framework for building formatters • A set of language-specific parsers that build a prettier- specific intermediate representation (IR) • A printer for printing out prettier IR

Slide 4

Slide 4 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Language support • JavaScript (JSX, Flow, TypeScript, JSON) • HTML (Vue, Angular) • CSS (Less, SCSS, styled-components, styled-jsx) • Markdown (MDX, YAML)

Slide 5

Slide 5 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Plugin support • Java (community) • PHP (official) • PostgreSQL (community) • Ruby (official) • Swift (official) • TOML (community)

Slide 6

Slide 6 text

github.com/prettier/plugin-ruby twitter.com/kddeisz @prettier/plugin-ruby • A ruby gem and a node module • 612 GitHub stars, 2905 downloads/week on npm • Active development

Slide 7

Slide 7 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Ruby to prettier IR • Parse the Ruby source using ripper • Convert the ripper output to JSON and return to node • Walk the ripper tree with node to generate prettier IR • Ripper::SCANNER_EVENTS.size = 52 • Ripper::PARSER_EVENTS.size = 132

Slide 8

Slide 8 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Prettier IR to source • Walk the prettier IR and print nodes as you go • At each node, call the correct print function for that node from the necessary plugin/printer • If you hit the line limit, break the outermost group

Slide 9

Slide 9 text

github.com/prettier/plugin-ruby twitter.com/kddeisz d=[30644250780,9003106878, 30636278846,66641217692,4501790980, 671_24_603036,131_61973916,66_606629_920, 30642677916,30643069058];a,s=[],$*[0] s.each_byte{|b|a<<("%036b"%d[b. chr.to_i]).scan(/\d{6}/)} a.transpose.each{ |a| a.join.each_byte{\ |i|print i==49?\ ($*[1]||"#")\ :32.chr} puts }

Slide 10

Slide 10 text

github.com/prettier/plugin-ruby twitter.com/kddeisz d = [ 30_644_250_780, 9_003_106_878, 30_636_278_846, 66_641_217_692, 4_501_790_980, 671_24_603036, 131_61973916, 66_606629_920, 30_642_677_916, 30_643_069_058 ] a, s = [], $*[0] s.each_byte { |b| a << ('%036b' % d[b.chr.to_i]).scan(/\d{6}/) } a.transpose.each do |a| a.join.each_byte { |i| print i == 49 ? ($*[1] || '#') : 32.chr } puts end

Slide 11

Slide 11 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Ruby choices • For the most part, consistent with rubocop • Run on the same input it will generate the same output • It will never change the meaning of your program* *Probably

Slide 12

Slide 12 text

github.com/prettier/plugin-ruby twitter.com/kddeisz alias with bare words class Foo alias :foo :bar alias bar baz end

Slide 13

Slide 13 text

github.com/prettier/plugin-ruby twitter.com/kddeisz class Foo alias foo bar alias bar baz end alias with bare words

Slide 14

Slide 14 text

github.com/prettier/plugin-ruby twitter.com/kddeisz array literals %w[alpha beta gamma delta epsilon] %i[alpha beta gamma delta epsilon] ['alpha', 'beta', 'gamma', 'delta', 'epsilon'] [:alpha, :beta, :gamma, :delta, :epsilon]

Slide 15

Slide 15 text

github.com/prettier/plugin-ruby twitter.com/kddeisz %w[alpha beta gamma delta epsilon] %i[alpha beta gamma delta epsilon] %w[alpha beta gamma delta epsilon] %i[alpha beta gamma delta epsilon] array literals

Slide 16

Slide 16 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Symbol#to_proc [1, 2, 3, 4, 5].map do |item| item.to_s end

Slide 17

Slide 17 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Symbol#to_proc [1, 2, 3, 4, 5].map(&:to_s)

Slide 18

Slide 18 text

github.com/prettier/plugin-ruby twitter.com/kddeisz do…end and {} blocks [1, 2, 3, 4, 5].each do |item| item.to_s(:format) end

Slide 19

Slide 19 text

github.com/prettier/plugin-ruby twitter.com/kddeisz do…end and {} blocks [1, 2, 3, 4, 5].each { |item| item.to_s(:format) }

Slide 20

Slide 20 text

github.com/prettier/plugin-ruby twitter.com/kddeisz ternaries foo = if bar 1 else 2 end

Slide 21

Slide 21 text

github.com/prettier/plugin-ruby twitter.com/kddeisz ternaries foo = bar ? 1 : 2

Slide 22

Slide 22 text

github.com/prettier/plugin-ruby twitter.com/kddeisz rescues foo rescue nil

Slide 23

Slide 23 text

github.com/prettier/plugin-ruby twitter.com/kddeisz rescues begin foo rescue StandardError nil end

Slide 24

Slide 24 text

github.com/prettier/plugin-ruby twitter.com/kddeisz strings 'foo' "foo" 'foo\n' "foo\n" 'foo #{bar} baz' "foo #{bar} baz" 'foo \M-\C-a' "foo \M-\C-a" "#@foo" "#@@foo" "#$foo" ?f

Slide 25

Slide 25 text

github.com/prettier/plugin-ruby twitter.com/kddeisz strings 'foo' 'foo' 'foo\n' "foo\n" 'foo #{bar} baz' "foo #{bar} baz" 'foo \M-\C-a' "foo \M-\C-a" "#{@foo}" "#{@@foo}" "#{$foo}" 'f'

Slide 26

Slide 26 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Ruby choices • break, next, yield, return don’t use parentheses
 (super will sometimes get parentheses) • no nested ternaries • decimal numbers will get underscores after 3 digits
 octal numbers will have an “o” added if it’s not there • {} lambdas for single line, do…end for multi-line • … and many more!

Slide 27

Slide 27 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Prettier options • Increase adoption • No longer done • Great demand from the community • Time to entrench • Compatibility reasons

Slide 28

Slide 28 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Ruby options • --add-trailing-commas = false • --inline-conditionals = true • --inline-loops = true • --prefer-hash-labels = true • --prefer-single-quotes = true

Slide 29

Slide 29 text

github.com/prettier/plugin-ruby twitter.com/kddeisz Future work • Better comment handling • Better support for method chaining • Template language support (ERB, HAML, etc.)

Slide 30

Slide 30 text

Prettier for Ruby github.com/prettier/plugin-ruby twitter.com/kddeisz