Upgrade to Pro — share decks privately, control downloads, hide ads and more …

My daily life on Ruby

My daily life on Ruby

Slides for my RubyCon 2026 talk "My daily life on Ruby" https://rubycon.it/schedule/

Avatar for Akira Matsuda

Akira Matsuda

May 11, 2026

More Decks by Akira Matsuda

Other Decks in Programming

Transcript

  1. self 🍕 Ruby committer 🍕 Rails committer 🍕 Gem author

    🍕 Kaminari, active_decorator, action_args, jb, stateful_enum, database_rewinder, gem_src, traceroute, routes_lazy_routes, lightweight_attributes, everywhere, hocus_pocus, erd, i18n_generators, html5_validators, motorhead, heavens_door, still_life, roundabout... 🍕 Gem maintainer 🍕 Haml, SimpleCov, test-unit-rails, md2key, cfp-app... 3 / 213
  2. self 🍕 Chief Organizer of RubyKaigi (since 2015) 🍕 Founder

    of Asakusa.rb (since 2008) 🍕 Ruby Hero (2016) 🍕 Rails Luminary (2024) 🍕 Loves 🇮🇹 Rock in '70s 🍕 Premiata Forneria Marconi, New Trolls, Area, Banco del Mutuo Soccorso, Arti e Mestieri, Semiramis, Biglietto per l'Inferno, Il Balletto di Bronzo, Museo Rosenbach, Formula 3, Jacula... 4 / 213
  3. Layered into each software stack 🍕 We can choose one

    from each layer and combine them 13 / 213
  4. The kitty text sizing protocol 🍕 https://github.com/kovidgoyal/kitty/issues/8226 🍕 Proposed and

    implemented last year 🍕 We can enlarge text size via OSC Escape Code (OSC 66) 21 / 213
  5. mkd 🍕 github.com/amatsuda/mkd 🍕 A Markdown viewer written in pure

    Ruby 🍕 By me 🍕 Renders Markdown nicely on terminals that support OSC 66 28 / 213
  6. So we have to use kitty 🍕 If we want

    to try this feature 30 / 213
  7. Structure 🍕 parser.rb: Parses Markdown and builds the deck 🍕

    controller.rb: Accepts key inputs and executes the commands 🍕 terminal.rb: Renders on the terminal using io-console 39 / 213
  8. io-console 🍕 A Ruby stdlib 🍕 Maybe not that popular?

    🍕 A very few usages found on the web 🍕 A very handy tool to draw characters on console 🍕 Made by nobu, the patch monster 41 / 213
  9. @nobu (Nobuyoshi Nakada) 🍕 No.1 Ruby committer (in terms of

    numbers of commits) 🍕 aka "Patch Monster" (or "Pachimon") 🍕 Maintains everything in Ruby 42 / 213
  10. io-console 🍕 A Ruby stdlib 🍕 Maybe not that popular?

    🍕 A very few usages found on the web 🍕 A very handy tool to draw characters on console 🍕 Made by nobu, the patch monster 43 / 213
  11. What does GNU Readline do? 🍕 It bridges between users'

    key inputs and the terminal/shell 49 / 213
  12. Readline 🍕 Super legacy 🍕 Often fails to install for

    some reasons 🍕 Lacks some features that Ruby needs for irb 50 / 213
  13. @keiju (Keiju Ishitsuka) 🍕 The godfather of Ruby 🍕 It

    was keiju who gave the name "Ruby" to Matz's language (1993) 🍕 Was Matz's colleague at that time 🍕 The author of irb 🍕 The author or Reish 53 / 213
  14. Reish 🍕 And so he started from reinventing Readline in

    pure Ruby 🍕 Which was named Reidline 56 / 213
  15. Reline 🍕 Pure Ruby Readline implementation 🍕 Created by itoyanagi

    🍕 Inspired by keiju's unfinished work "Reidine" 59 / 213
  16. Reline 🍕 Totally replaced Readline (2019) 🍕 irb's backend today

    🍕 Maintained by the irb team today 🍕 tompng, ima1zumi, st0012, and hasumikin 60 / 213
  17. @itoyanagi (Itoyanagi) 🍕 An adventurer 🍕 A legacy killer in

    Ruby 🍕 Killed RDoc's own parser in favor of Ripper 🍕 Created Reline 🍕 Achieved a big refactoring on irb on top of Reline 62 / 213
  18. Pure Ruby Readline equivalent has done 🍕 So it's time

    to create a pure Ruby shell on top of it? 🍕 As keiju planned? 64 / 213
  19. zsh 🍕 The ultimate modern shell 🍕 bash compatible 🍕

    Highly customizable 🍕 Advanced completion system 🍕 Brought the "plugin system" to the shell world 70 / 213
  20. Limitations 🍕 Because it's pipeline-based 🍕 All inputs and outputs

    are strings 🍕 test commands does all the hard works under the hood 73 / 213
  21. test command basics % test 1 = 1 % echo

    $? 0 % test 1 = 2 % echo $? 1 74 / 213
  22. A tricky alias for test, [ % if [ "$FOO"

    = "hello" ]; then > echo true > fi 75 / 213
  23. Trickiest part in sh languages 🍕 Does all the heavy

    liftings when comparing things 🍕 I won't go into details, but it has too many features and too many options 🍕 This makes even a simple if or loop statements hard to write 76 / 213
  24. Too many options 🍕 -b, -c, -d, -e, -f, -g,

    -h, -k, -n, -p, -r, -s, -t, 🍕 -u, -w, -x, -z, -L, -O, -G, -S, 🍕 file1 -nt file2, file1 -ot file2, file1 -ef file2, 🍕 string, s1 = s2, s1 != s2, s1 < s2, s1 > s2, 🍕 n1 -eq n2, n1 -ne n2, n1 -gt n2, n1 -ge n2, n1 -lt n2, n1 -le n2 77 / 213
  25. fish 🍕 More modernized shell than zsh 🍕 Very much

    opinionated 🍕 Strong functions 🍕 Aggressive completion 🍕 Just works without lots of configurations 🍕 Unlike zsh 79 / 213
  26. The fish language 🍕 Trying to improve bash usability 🍕

    I can understand the motivation 🍕 But the language design is... still not intuitive 🍕 I mean it doesn't feel like "my language" 82 / 213
  27. fish 🍕 So it failed to dominate the market 🍕

    Many people are still living with zsh 83 / 213
  28. The feature that we need for our endgame shell 🍕

    Ruby as the scripting language! 86 / 213
  29. Reish again 🍕 Even the creator of irb couldn't finish

    it 🍕 Why did I thought that I can do it? 88 / 213
  30. History 🍕 I started working on it from 1st, January

    this year 🍕 Roughly done in about two weeks 🍕 It's been my main login shell since then 90 / 213
  31. Features 🍕 Written in pure Ruby 🍕 bash compatible 🍕

    All existing bash scripts should just work 🍕 Ruby-flavored extended syntax 🍕 Covers most of zsh features 🍕 Just works without lots of configurations 91 / 213
  32. Demo (completion) % cd % cd ~ % git %

    gem % bundle % rbenv 92 / 213
  33. Ruby flavored language 🍕 if, elif, fi => if, elsif,

    end 🍕 Blocks 🍕 Method chaining 🍕 lambda literal 🍕 p command for inspecting in Ruby level 🍕 Ruby constant reference 🍕 Use of Ruby Threads for background processing 🍕 And many more experimental features 93 / 213
  34. Blocks 🍕 if/loop commands take { } block that is

    evaled in Ruby 🍕 We can forget the test command 🍕 Enumerator 🍕 each, select, map 🍕 it is available 94 / 213
  35. Demo if { 1 + 1 == 2 } echo

    "1 + 1 is 2" end 95 / 213
  36. Method chaining 🍕 Commands take () like methods 🍕 So

    pipelines can be written as method chaining 97 / 213
  37. Ruby constant reference 🍕 There's no command or feature that

    starts with a Capital letter in UNIX 🍕 So, we can assume that if it starts with A-Z, it must be a Ruby constant 101 / 213
  38. Implementation 🍕 Reline based, like irb, as I told you

    🍕 And heavily relies on the Ruby stdlibs 109 / 213
  39. Standing on the shoulders of giant Ruby ecosystem 🍕 Reline

    🍕 FileUtils 🍕 Open3 🍕 Thread 🍕 did_you_mean etc. 110 / 213
  40. Naming software is hard... 🍕 The gem name "rubish" was

    already taken... 🍕 Installable via homebrew for now... 113 / 213
  41. The "system ruby" problem 🍕 A shell has to be

    loaded before loading rbenv or such 🍕 So the shell runs on "system Ruby" 🍕 Which is still 2.6 on Mac 🍕 Which is very old 114 / 213
  42. The "system ruby" problem => Resolved! 🍕 Fixed by changing

    the executable to a bash script that detects other rubies 🍕 (This slide was added after the talk) 115 / 213
  43. And so I started making another thing with Ruby 🍕

    On top of Reline again 117 / 213
  44. Textbringer 🍕 shugo's editor in pure Ruby 🍕 Built on

    top of Curses 🍕 Emacs clone 122 / 213
  45. @shugo (Shugo Maeda) 🍕 Creator of lots of weird (and

    lots of useful) features of Ruby 🍕 Creator of protected scope 🍕 Creator of callcc 🍕 Creator of Refinements 🍕 Creator of eruby (ERB specification) 🍕 Creator of mod_ruby (Apache module) 🍕 Creator of net-ftp/net-imap 🍕 Maintainer of Curses 🍕 Matz's boss at his company, NaCl 123 / 213
  46. Curses 🍕 Ruby binding for curses, Ncurses, and PDCurses 🍕

    For building richer TUI tools 🍕 Like tetris 🍕 Or text editor 🍕 shugo maintains this so his text editor keeps working 124 / 213
  47. I once made a filer with Ruby Curses 🍕 And

    it beautifully works! 125 / 213
  48. rfd 🍕 https://github.com/amatsuda/rfd 🍕 "FD" (a legendary Japanes filer for

    MS-DOS) clone 🍕 Vim-ish UI 🍕 Pure Ruby 🍕 On top of Curses 126 / 213
  49. Features 🍕 Covers most of basic features of NeoVim 🍕

    Some critical features like async, LSP, and tree sitter are not supported yet 🍕 Covers most of settings (:set) 🍕 Kind of emulates VimScript 🍕 Executes Lua scripts! 133 / 213
  50. Running Lua scripts from Ruby 🍕 I'm just using rufus-lua

    gem 🍕 And it magically works! 134 / 213
  51. rufus-lua 🍕 A Ruby binding that calls Lua engine via

    FFI 🍕 Created by jmettraux 135 / 213
  52. @jmettraux (John Mettraux) 🍕 A gentleman from Switzerland 🍕 Lives

    in Hiroshima, Japan 🍕 Author of rufus-scheduler and the family 136 / 213
  53. That's everything that I wrote in my proposal 🍕 A

    pure Ruby UNIX shell 🍕 A pure Ruby text editor 138 / 213
  54. Missing features 🍕 Terminal integration 🍕 Like moving cursor and

    copy & paste with keyboard shortcuts 🍕 Like GNU Screen 145 / 213
  55. That's something beyond shell's domain 🍕 That's terminal emulators' territory

    🍕 For instance, kitty implements them on its own 146 / 213
  56. Python? 🍕 If there's a Python based terminal emulator 🍕

    There should be no reason we cannot do it in Ruby!💡 150 / 213
  57. And so I made it (and so this talk seems

    to continue a little bit more) 151 / 213
  58. Echoes 🍕 https://github.com/amatsuda/echoes 🍕 Pure Ruby terminal emulator 🍕 Native

    UI components 🍕 Not based on Reline here 🍕 Supports only macOS so far 🍕 So the UI is COCOA based 152 / 213
  59. Features 🍕 Any shell should work on it 🍕 Supports

    kitty text sizing protocol 🍕 So the presentation tool works on it 🍕 Supports image rendering 🍕 Even tetris works on it 🍕 Native UI based features 🍕 Native dialog! 🍕 Multiple fonts! 🍕 Multiple bg colors! 🍕 With gradations! 153 / 213
  60. A pure Ruby terminal emulator 🍕 TBH, it'd be hard

    to beat alacritty, Ghostty and such in rendering speed 155 / 213
  61. The CLI dev stack on which everyone lives today 🍕

    Terminal Emulator 🍕 Shell 🍕 Text Editor 158 / 213
  62. Connected with super legacy APIs 🍕 When the consoles displayed

    only 8 colors 🍕 When UNICODE was not a thing 🍕 When Ruby was not there yet 159 / 213
  63. NORMAL TERMINAL ⁶ SHELL pty (one byte stream, bidirectional) ┌───────────┐

    ◄─────────────────────►┌────────────┐ │ Terminal │ │ Shell │ │ │ keystroke bytes ──►│ │ │ - ANSI │ ◄─ echoed keystroke │- Reline │ │ parser │ + cursor ANSI │ parses │ │ - cell │ (round-trips) │ keys │ │ grid │ ◄─ prompt as │- prompt is │ │ │ ANSI bytes: │ formatted │ │ │ "\e[1;32m$\e[0m " │ as ANSI │ │ │ ◄─ completion list as │- completion│ │ │ text + ANSI │ pre-baked │ │ │ ◄─ command stdout │ to bytes │ └───────────┘ (also bytes) └────────────┘ 160 / 213
  64. NORMAL TERMINAL ⁶ SHELL Two parsers (one in each side).

    Every keystroke makes a round trip. Prompt / completion / cursor moves are all flattened to escape codes — the terminal can't distinguish "this byte is part of the prompt" from "this byte is part of command output". Just one big stream. 161 / 213
  65. So we have to perform a lot of String conversion

    dances 🍕 Here and there between the layers 🍕 Causes performance overhead 🍕 Causes mojibake 🍕 Causes exceptions, e.g. "invalid byte sequence in UTF-8" 163 / 213
  66. Integration 🍕 What if we run everything in one Ruby

    process? 🍕 We could skip all the abstractions and legacy APIs in favor of simple Ruby method calls! 164 / 213
  67. You know, that's called "full stack" 🍕 "full stack" is

    stronger than micro components 🍕 Ruby is good for building full stack software 🍕 The web framework proved it already 165 / 213
  68. Echoes integration 🍕 Echoes directly renders shell outputs via native

    API 🍕 Skipping legacy UNIX API 🍕 Skipping Reline as well! 167 / 213
  69. The text editor can be run there 🍕 Directly from

    with in the terminal emulator via one method call 🍕 Skipping the whole shell process 169 / 213
  70. So am I reinventing an IDE? 🍕 Like Rubymine or

    VSCode 🍕 Well, maybe... 173 / 213
  71. To build everything myself with my favorite language 🍕 Instead

    of just downloading and using an IDE that is built for general purpose 175 / 213
  72. I made pure Ruby dev tools for you! 🍕 Please

    try them, and give me feedbacks! 179 / 213
  73. I made pure Ruby dev tools for you! 🍕 Please

    try them, and give me feedbacks! 180 / 213
  74. I'm not a terminal pro 🍕 But AI made me

    possible to do this 184 / 213
  75. And so can you, of course 🍕 We live in

    such an exciting world as a programmer! 185 / 213
  76. Ruby can do anything 🍕 Ruby is not just a

    language that runs Rails on the servers 🍕 Ruby has a very rich ecosystem 🍕 And Ruby is your best friend! 189 / 213
  77. The land where every software that we use is written

    in Ruby 🍕 So that it's readable 🍕 So that it's maintainable 🍕 So that it's extendable 193 / 213
  78. Let's try using Ruby 🍕 For something that you've never

    tried 🍕 For tools that you actually use 🍕 For something that makes your life better 🍕 Or just for something fun 203 / 213
  79. Q: Why not Rust? Everyone creates such CLI tools with

    Rust (or zig or whatever) these days. Why don't you do so? 209 / 213
  80. A: Why not Ruby? Who decided that Ruby is not

    the language for that? 210 / 213