# Method\_missing for command shell?

**URL:** <https://www.ruby-forum.com/t/method-missing-for-command-shell/176727>\
**Category:** Ruby\
**Created:** [October 5, 2009, 2:33pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727 "2009-10-05T14:33:54Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 2:33pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/1 "2009-10-05T14:33:54Z")

</div>

Hi all. My bash-fu is a little bit lacking, so here’s my question.

I’m wondering if anybody knows of a shell that can be programmed to  
“guess” what you meant when you type in a command errantly, like (kind  
of a bad example, but…)

$ git dif

(it runs git dif, fails, then, in method\_missing style, I can tell it  
“oh what I always means when I run git dif is git diff” so it correct  
its for me and runs it).

Any pointers on where to go there?  
Thanks.  
-r

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 3:05pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/2 "2009-10-05T15:05:39Z")

</div>

Try zsh  
-Mario.

–  
I want to change the world but they won’t give me the source code.

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 7:16pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/3 "2009-10-05T19:16:14Z")

</div>

Mario C. wrote:

> Try zsh

Interesting. Seeing the syntax that zsh uses makes me want to rewrite  
the whole thing just so I can use ruby for command completions LOL 🙂

-r

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 8:27pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/4 "2009-10-05T20:27:58Z")

</div>

Roger P. wrote:

> Mario C. wrote:
> 
> > Try zsh
> 
> Interesting. Seeing the syntax that zsh uses makes me want to rewrite  
> the whole thing just so I can use ruby for command completions LOL 🙂
> 
> -r

You’re welcome to write your own shell in Ruby 😉

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 8:31pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/5 "2009-10-05T20:31:12Z")

</div>

On Oct 5, 8:33 am, Roger P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> its for me and runs it).
> 
> Any pointers on where to go there?

I’m writing a ruby command/task execution gem which could allow for  
easy ruby wrapping of system commands and method\_missing-fu for  
subcommands: [GitHub - cldwalker/boson: A command/task framework similar to rake and thor built with extendability in mind.](http://github.com/cldwalker/boson)

I already do subcommand method\_missing with boson, not for guessing  
but for smart aliasing:  
[http://github.com/cldwalker/irbfiles/blob/master/boson/commands/boson\_method\_missing.rb#L10-25](http://github.com/cldwalker/irbfiles/blob/master/boson/commands/boson_method_missing.rb#L10-25)

Here’s how you could define a simple Boson library that wraps git  
subcommands:

module Git  
%w{add checkout diff rm merge pull push}.each do |e|  
define\_method(e) do |\*args|  
system(‘git’, e, \*args)  
end  
end  
end

With boson you would be able to execute these subcommands from the  
commandline or irb as follows:

bash\> boson git.diff  
irb\>\> git.diff

With the above method\_missing library you could execute these as git.d  
or git.dif

Unfortunately Boson isn’t ready yet. Hopefully within the week. In the  
mean time you could take that example  
module and use it within irb:

def git  
@git ||= Object.new.extend Git  
end

class \<\< git  
def method\_missing(meth, \*args, &block)  
if !(meths = Git.instance\_methods.sort.grep(/^#{meth}/)).empty?  
send(meths[0].to\_sym, \*args, &block)  
else  
super  
end  
end  
end

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 8:35pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/6 "2009-10-05T20:35:53Z")

</div>

On Mon, Oct 5, 2009 at 11:28 AM, Aldric G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > Interesting. Seeing the syntax that zsh uses makes me want to rewrite  
> > the whole thing just so I can use ruby for command completions LOL 🙂

> You’re welcome to write your own shell in Ruby 😉

or start with [http://rush.heroku.com/](http://rush.heroku.com/)

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 11:10pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/7 "2009-10-05T23:10:28Z")

</div>

Roger P. wrote:

> Any pointers on where to go there?  
> Well, kind of. You might use PROMPT\_COMMAND in bash to react if  
> the last command failed (as in the above case of a misspelled  
> second argument). Or you could use a command\_not\_found\_handle  
> function (new in bash 4.0, see the manual) as a hook for a  
> misspelled binary name, and go from there. Maybe both.

Here’s something I hacked together using the first method. It  
works a bit different from your suggestion in that it uses compgen  
to guess the possible corrections for the second argument  
(checking first if there is a completion function for this  
command), then uses the builtin select command to query the user  
for a correction, and then runs the corrected command. So it will  
ask you if you meant “git diff” or “git difftool” in the case of  
“git dif” failing. (Note that git’s completion already asks a “did  
you mean” question, so it’s a little redundant here…)

Not exactly what you asked for (still fails for “git dfif”), and  
probably not perfect, but maybe it’s a pointer to start from 😉

So, here’s the code to source into bash:

last\_commandline () {

# fetch the last commandline from the history

local histtimeformat=$HISTTIMEFORMAT  
unset HISTTIMEFORMAT

[[$(history 1) =~ \ +[0-9]+?\ +(.+?) ]]  
local commandline=${BASH\_REMATCH[1]}

if [[“$histtimeformat” != “”]]; then  
HISTTIMEFORMAT=$histtimeformat  
fi  
echo “$commandline”  
}

correct () {  
args=($\*)  
rest="${args[@]:2}" # third to last arg

if type -t “\_$1” &\>/dev/null; then  
# there’s a completion function for this command  
# get possible completions for the incomplete second argument  
comps=($(compgen -W “$(compgen -F \_$1 2\>/dev/null)” – $2))

```
# let the user choose, then run the corrected command
select choice in ${comps[@]}; do
  echo "running corrected command: $1 $choice $rest";
  $1 $choice $rest
  break;
done

```

fi  
}

# we’ll use the prompt command as a hook for failed commands

PROMPT\_COMMAND=’[[! $? -eq 0]] && correct $(last\_commandline)’

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 6, 2009, 1:21pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/8 "2009-10-06T13:21:31Z")

</div>

> Here’s something I hacked together using the first method. It  
> …

> Not exactly what you asked for (still fails for “git dfif”), and  
> probably not perfect, but maybe it’s a pointer to start from 😉

Nice.

…

> yeah and let me know when it’s done and has the same feature set as Bash  
> …

what feature set would you require?

-r

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/45deac/32.png) [@rogerdpack](https://www.ruby-forum.com/u/rogerdpack)\
**Post date:** [October 5, 2009, 8:32pm UTC](https://www.ruby-forum.com/t/method-missing-for-command-shell/176727/9 "2009-10-05T20:32:58Z")

</div>

yeah and let me know when it’s done and has the same feature set  
as bash, then I’ll come over and kiss your feet and pay you a drink  
😉

Greetz!
