ruby -run, again

Previously we learned about a tool in Ruby's standard library called un. After some consideration it occurred to me some might wonder, "How does this work?" We learned that we can type something like ruby -run -e httpd . to start a web server that will serve all the files in our current directory over HTTP. But we said the name of the library is "un" what's with ruby -run? Well, why don't we try asking ruby? We can do so by making use of its help flag. Just type ruby -h and you should see something like this on your screen: There are a lot of options here, but if you squint you'll notice just past the middle an option called -rlibrary. It says it's used to "require the library before executing your script". That's what we're using. "un" is the name of the library so when it's paired with -r it spells -run. That's clever! View Source Let's not stop there. What else can we learn? Let's checkout the source code. We can find it in this repository on Github: https://github.com/ruby/un. Let's check it out. When you do you'll notice that there's a lib directory. That's usually were source code goes for Ruby libraries. Let's see what's in there. It's a single file. Interesting. If you open it and scan through it slowly to the bottom you'll notice that it just contains a few functions. Now scrolling back toward the top the first function is setup. If you scroll down to the next function cp. You'll notice that it uses setup. If you go back up to setup you'll notice that it's parsing the command line flags that we've passed it using a class called OptionParser. In the final line of setup it uses the Ruby keyword yield to pass the parsed arguments to a block that get's passed to it. Now when we look at each of the other functions cp, ln, mv, etc. they each use setup this way. That's a neat trick! Come Together That's interesting and all but we still haven't quite eplained how ruby -run -e httpd . works. It seems like the missing piece is -e. Let's ask ruby again. There it is, toward the top, -e 'command', "one line of script". Hmm. Let's try it out: ruby -e "puts 'Hi'". My console kindly greets me with "Hi". Is that what you see? Cool. So this allows us to execute arbitrary Ruby code....I think I get it! When I load the library "un" with -run I can call any of those functions in lib/un.rb! Let's test out this theory by doing something crazy. ruby -run -e 'setup() { puts "Hi" }' Did your console greet you like mine did? That-is-cool. Now I get how ruby -run -e httpd . works. Now I just need to understand the httpd function. That'll have to wait. I could use a snack about now, but this was fun. Later!

Jan 15, 2025 - 21:08
ruby -run, again

Previously we learned about a tool in Ruby's standard library called un. After some consideration it occurred to me some might wonder, "How does this work?"

We learned that we can type something like ruby -run -e httpd . to start a web server that will serve all the files in our current directory over HTTP. But we said the name of the library is "un"
what's with ruby -run?

Well, why don't we try asking ruby? We can do so by making use of its help flag. Just type ruby -h and you should see something like this on your screen:

Usage: /Users/delon/.asdf/installs/ruby/2.7.5/bin/ruby [switches] [--] [programfile] [arguments]<br>
  -0[octal]       specify record separator (\0, if no argument)<br>
  -a              autosplit mode with -n or -p (splits $_ into $F)<br>
  -c              check syntax only<br>
  -Cdirectory     cd to directory before executing your script<br>
  -d              set debugging flags (set $DEBUG to true)<br>
  -e 'command'    one line of script. Several -e's allowed. Omit [programfile]<br>
  -Eex[:in]       specify the default external and internal character encodings<br>
  -Fpattern       split() pattern for autosplit (-a)<br>
  -i[extension]   edit ARGV files in place (make backup if extension supplied)<br>
  -Idirectory     specify $LOAD_PATH directory (may be used more than once)<br>
  -l              enable line ending processing<br>
  -n              assume 'while gets(); ... end' loop around your script<br>
  -p              assume loop like -n but print line also like sed<br>
  -rlibrary       require the library before executing your script<br>
  -s              enable some switch parsing for switches after script name<br>
  -S              look for the script using PATH environment variable<br>
  -v              print the version number, then turn on verbose mode<br>
  -w              turn warnings on for your script<br>
  -W[level=2|:category]     set warning level; 0=silence, 1=medium, 2=verbose<br>
  -x[directory]   strip off text before #!ruby line and perhaps cd to directory<br>
  --jit           enable JIT with default options (experimental)<br>
  --jit-[option]  enable JIT with an option (experimental)<br>
  -h              show this message, --help for more info

There are a lot of options here, but if you squint you'll notice just past the middle an option called -rlibrary. It says it's used to "require the library before executing your script". That's what we're using. "un" is the name of the library so when it's paired with -r it spells -run. That's clever!

View Source

Let's not stop there. What else can we learn? Let's checkout the source code. We can find it in this repository on Github: https://github.com/ruby/un. Let's check it out.

When you do you'll notice that there's a lib directory. That's usually were source code goes for Ruby libraries. Let's see what's in there. It's a single file. Interesting.

If you open it and scan through it slowly to the bottom you'll notice that it just contains a few functions. Now scrolling back toward the top the first function is setup. If you scroll down to the next function cp. You'll notice that it uses setup. If you go back up to setup you'll notice that it's parsing the command line flags that we've passed it using a class called OptionParser.

In the final line of setup it uses the Ruby keyword yield to pass the parsed arguments to a block that get's passed to it. Now when we look at each of the other functions cp, ln, mv, etc. they each use setup this way. That's a neat trick!

Come Together

That's interesting and all but we still haven't quite eplained how ruby -run -e httpd . works. It seems like the missing piece is -e. Let's ask ruby again.

Usage: /Users/delon/.asdf/installs/ruby/2.7.5/bin/ruby [switches] [--] [programfile] [arguments]<br>
  -0[octal]       specify record separator (\0, if no argument)<br>
  -a              autosplit mode with -n or -p (splits $_ into $F)<br>
  -c              check syntax only<br>
  -Cdirectory     cd to directory before executing your script<br>
  -d              set debugging flags (set $DEBUG to true)<br>
  -e 'command'    one line of script. Several -e's allowed. Omit [programfile]<br>
  -Eex[:in]       specify the default external and internal character encodings<br>
  -Fpattern       split() pattern for autosplit (-a)<br>
  -i[extension]   edit ARGV files in place (make backup if extension supplied)<br>
  -Idirectory     specify $LOAD_PATH directory (may be used more than once)<br>
  -l              enable line ending processing<br>
  -n              assume 'while gets(); ... end' loop around your script<br>
  -p              assume loop like -n but print line also like sed<br>
  -rlibrary       require the library before executing your script<br>
  -s              enable some switch parsing for switches after script name<br>
  -S              look for the script using PATH environment variable<br>
  -v              print the version number, then turn on verbose mode<br>
  -w              turn warnings on for your script<br>
  -W[level=2|:category]     set warning level; 0=silence, 1=medium, 2=verbose<br>
  -x[directory]   strip off text before #!ruby line and perhaps cd to directory<br>
  --jit           enable JIT with default options (experimental)<br>
  --jit-[option]  enable JIT with an option (experimental)<br>
  -h              show this message, --help for more info

There it is, toward the top, -e 'command', "one line of script". Hmm. Let's try it out: ruby -e "puts 'Hi'". My console kindly greets me with "Hi". Is that what you see? Cool. So this allows us to execute arbitrary Ruby code....I think I get it! When I load the library "un" with -run I can call any of those functions in lib/un.rb!

Let's test out this theory by doing something crazy.

ruby -run -e 'setup() { puts "Hi" }'

Did your console greet you like mine did? That-is-cool. Now I get how ruby -run -e httpd . works. Now I just need to understand the httpd function. That'll have to wait. I could use a snack about now, but this was fun. Later!