Git Product home page Git Product logo

urchin's Introduction

Urchin
===

A Unix shell for Ruby programmers.

If you have any ideas for what you think this should mean, please submit a
ticket!

Urchin does not aim to be POSIX compliant, but is heavily influenced by Bash
and Zsh. Urchin aims to make Ruby a first class citizen in the shell and be a
good place for experimenting with new shell ideas.


Authors
===

Mark Somerville <[email protected]>
http://mark.scottishclimbs.com/
@_Spakman
Spakman on Freenode


Current status
===

Preparing to release version 0.2.0. On Linux this will be beta quality. It is
considerably less tested on other platforms. I have been using it as my login
shell since version 0.1.0 and it has been pretty stable.

Quite a lot of common Unix shell stuff is implemented: job control,
redirections, tilde expansion, aliasing, globbing and environment variables.
Functions are the most obvious thing missing from that list. These will most
likely appear in 0.3.0.

Straightforward inline Ruby is available! This was the original inspiration for
the project (although the vision has grown somewhat now). This allows writing
Ruby processes directly on the command line, without the need to escape special
characters. This will likely be expanded and improved upon in later releases.

I will create a gem for version 0.2.0.


Current problems
===

GitHub is used for ticket tracking: https://github.com/Spakman/urchin/issues


Requirements
===

Ruby
---
Tested with MRI 1.8.7, 1.9.2 and 1.9.3-dev on Linux.

If running using 1.9.2 on a laptop, be aware of bug #3436
(http://redmine.ruby-lang.org/issues/show/3436). This should be fixed when
1.9.3 is released.


rb-readline
---
Since version 0.2.0, Urchin relies on rb-readline. Use the latest version or
check it out from GitHub[1]. I'm one of the maintainers for rb-readline and
always check that Urchin works with the latest version.

1 - https://github.com/luislavena/rb-readline


ruby-termios
---
Tested with version 0.9.6.


Some examples that work
===

Pipelines:

	ls -la | head -n2

Calling a new Ruby process (~@ is the default delimiter):

	ls --no-color |~@ puts STDIN.read.reverse ~@ | sort
	ls --no-color |~@ o s.reverse ~@ | sort

Redirecting STDOUT, STDIN, STDERR:

	uptime > output
	uptime >> output
	ruby -e 'puts STDIN.read; STDERR.puts 33' < input > out_and_err 2>&1

Backgrounding jobs:

	sleep 60 &

Multiple jobs:

	sleep 60 & man sleep

	sleep 60; echo "it's over"

Quoted and unquoted parameters:

	grep -r '"hello"' .
	grep -r "\"hello\"" .
	ls my\ annoyingly\ named\ dir
	find . -name 'hello' -exec chmod 660 {} \;

Globbing:

	ls **/*.rb
	mv image?.{png,gif} images

Tilde expansion:

	ls ~/src/
	ls ~mark

Reading and setting environment variables:

	echo $PATH
	echo abx${HOME}xyz
	export HELLO="Yo man!"

Simple arithmetic (lines starting with a digit are eval-ed as Ruby):

	17 * 123

Command expansion:

	ps `pgrep urchin`

Job control (uses fg, bg and jobs builtins).

urchin's People

Contributors

spakman avatar euanmaxwell avatar

Stargazers

 avatar NNB avatar Nikolay Kolev avatar  avatar Vasudev Ram avatar Thomas avatar Kabir Goel avatar Gay Programmer avatar Anatoly Chernov avatar Brandon Zylstra avatar Jakob Gillich avatar Angus H. avatar Aaron Vinson avatar Amar Shah avatar Steven Hum avatar Craig Paterson avatar  avatar Rizo I avatar Nazeeruddin Ikram avatar  avatar masukomi (a.k.a. Kay Rhodes) avatar  avatar Misty De Méo avatar  avatar Christoph Grabo avatar brownman avatar Biao Xie avatar Patrick Bennett avatar Jan Lelis avatar  avatar Mike Harris avatar Jesse Storimer avatar  avatar Jens Wille avatar Ryan Stenhouse avatar  avatar

Watchers

 avatar  avatar Steven Hum avatar James Cloos avatar Anatoly Chernov avatar

Forkers

mharris717

urchin's Issues

Equals sign is able to crash Urchin

This gives an exception:

$ git co -b =
Urchin exited.

NoMethodError: undefined method `<<' for nil:NilClass
/home/mark/src/urchin/lib/parser.rb:195:in `arg_with_equals'
/home/mark/src/urchin/lib/parser.rb:281:in `words'
/home/mark/src/urchin/lib/parser.rb:142:in `parse_command'
/home/mark/src/urchin/lib/parser.rb:60:in `parse_job'
/home/mark/src/urchin/lib/parser.rb:28:in `jobs_from'
/home/mark/src/urchin/lib/shell.rb:59:in `parse_and_run'
/home/mark/src/urchin/lib/shell.rb:35:in `run'
/home/mark/src/urchin/bin/urchin:41:in `<main>'

Allow interaction with user before command is issued

Something I've often thought would be useful, when using commands I'm not intimately familiar with (or which have a bazillion options) is for the shell to be able to give feedback before I enter a command.

The most obvious, and probably most common, use for this would be giving information about command switches/options. If I'm using wget, for instance, if I type wget -m -k -p and then trigger feedback (either by a long pause, or a keystroke--whatever I've configured in .urchin_profile or whatever) I could get a brief one-line explanation of the last switch I entered, telling me that that causes wget to include related files like images and stylesheets and scripts related to the page being downloaded. This would be MUCH faster and easier for a user than opening a new terminal window and digging through a gigantic man page, or Googling, or testing the command and trying something else if it didn't work. Imagine if you had to lookup 10 different switches, which you could easily do with wget. Each might take a few seconds to try with this method, but might take a minute and a half each by Googling. That's 30 seconds versus 15 minutes. (The real value of speeding things up and smoothing them out is that you don't lose concentration, which is much more valuable than the time saved!)

Another example of how this could be used would be when sending commands to an ssh client. (Not ssh shell commands, but the commands you give the client after you type ~ to tell the client that what follows is not to be sent on the the machine you're connected to, but interpreted by the client itself.) Take a look at this question: http://serverfault.com/questions/435256/how-can-one-send-commands-to-the-inner-ssh-session/435262#435262 and imagine that you get feedback everytime you type ~ to tell you which machine's ssh client is going to receive the command.

What Urchin would provide would simply be a way of creating methods for intercepting and responding to incomplete commands, and a way of triggering the feedback. It would be a lot like command completion in bash or zsh in that some commands ship with the completions, and other times the user needs to write them, or find them on the web somewhere and install them. Urchin might initially include feedback methods for switches on a handful of commands, mostly as examples of how to write them, and to let people use them and see how they can be useful.

At some point some ambitious soul might do some metaprogramming to generate these feedback methods on the fly by parsing man pages. But that wouldn't be in the scope of the initial goals for this feature. Initially it's just about giving users a way to respond to not-yet-executed commands.

Perhaps like this (super-rough, off-the-top-of-my-head API example, probably terrible):

on_feedback_request_for /wget*-k/ do
  display_tip "Convert links for offline viewing"
end

on_feedback_request_for /rm -rf*/ do
  3.times { beep }
  display_tip "Whoooa!  Dude!  Think carefully!", { :box_color => :red, :text => yellow }
do

As far as I know this goes beyond what any other shell can do, and offers possibilities for interaction that don't exist in those other shells. (Or, if they are possible in the other shells, they almost certainly aren't easy to implement and certainly haven't been extensively taken advantage of. Zsh and bash command completion might possibly be capable of doing something like this, but not so easily.)

I can see this really making Urchin much more productive even for experienced shell users, as well as much more approachable for beginners.

Don't close Ruby reserved FDs in forked processes

Since MRI 1.9, a pipe has been used for internal signalling communication. A C API, rb_reserved_fd_p(), has been provided to check if a file descriptor is used by the VM or not.

Currently, Urchin closes all FDs > 2. For some reason, I haven't found this to be a problem under 1.9, but testing with Ruby 2.0.0-dev does give intermittent problems:

[ASYNC BUG] thread_timer: select
EBADF

ruby 2.0.0dev (2012-11-01 trunk 37411) [x86_64-linux]

Urchin should use the C API, either with a C extension or using FFI.

Track shell history in a database

Every piece of info tracked as part of history is basically another field, and the more flexibility offered to the user (in terms of what to include and what to exclude from history) the more complicated it gets to the developer of the shell, leaving them to basically build database functions from scratch, when they would more easily just use a database (probably SQLite).

Here are some of the fields that might be tracked as part of history:

  • command
  • start_time
  • stop_time
  • working_directory
  • date
  • command_id (integer starting at 1 and incrementing for each command: standard in most shells)

The killer feature to this, more than ease of development, would be the ability for the end user to define their own fields. For instance, if the working_directory field were defined by an end user, they would just have to specify the name (whatever name they wanted) and the command or value to run or evaluate on each command execution. In this case pwd or $PWD would both do nicely. Allowing the user to add arbitrary data to their command history would make this the most flexible and powerful command history EVAR. Or at least I'd bet $5 on that.

Exclude some commands from history

Allow some method of excluding commands from the history - explicit list of command, regex, etc... who knows.

The most obvious example is, of course:

rm -rf .

Make Urchin multi-line aware

Currently, a command like:

ls |<return>

will actually execute, rather than accept the next thing in the pipeline. Additionally, trying to enter inline Ruby on more than one line will raise an exception.

Making the parser multi-line aware is also the first step in being able to parse (nice) function definitions.

Load errors after installing gem

I tried building & installing the gem, (gem build urchin.gemspec, gem install urchin-0.1.0.90.gem) but when I run it, I get the following on a mac running 1.9.3 under rvm. Did I miss a step? I wasn't able to find any specific install instructions, and this does not seem to be in the gem repositories

looks like a great tool/eager to get it working!


Urchin exited.

LoadError: cannot load such file -- /usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/../boot
/usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in require' /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:inrequire'
/usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/urchin:15:in <top (required)>' /usr/local/rvm/gems/ruby-1.9.3-p194/bin/urchin:19:inload'
/usr/local/rvm/gems/ruby-1.9.3-p194/bin/urchin:19:in <main>' /usr/local/rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:ineval'
/usr/local/rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:in <main>' ^C/usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/urchin:54:ingets': Interrupt
from /usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/urchin:54:in gets' from /usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/urchin:54:inrescue in <top (required)>'
from /usr/local/rvm/gems/ruby-1.9.3-p194/gems/urchin-0.1.0.90/bin/urchin:6:in <top (required)>' from /usr/local/rvm/gems/ruby-1.9.3-p194/bin/urchin:19:inload'
from /usr/local/rvm/gems/ruby-1.9.3-p194/bin/urchin:19:in <main>' from /usr/local/rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:ineval'
from /usr/local/rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:in `

'

Can't redirect to a file that doesn't exist if the pathname contains a tilde

For example:

$ jruby --properties > ~/.jrubyrc 
/home/mark/src/urchin/lib/os_process.rb:20:in `reopen': No such file or directory - ~/.jrubyrc (Errno::ENOENT)
    from /home/mark/src/urchin/lib/os_process.rb:20:in `block in perform_redirects'
    from /home/mark/src/urchin/lib/os_process.rb:16:in `each'
    from /home/mark/src/urchin/lib/os_process.rb:16:in `perform_redirects'
    from /home/mark/src/urchin/lib/os_process.rb:26:in `execute'
    from /home/mark/src/urchin/lib/job.rb:77:in `block in fork_and_exec'
    from /home/mark/src/urchin/lib/job.rb:55:in `fork'
    from /home/mark/src/urchin/lib/job.rb:55:in `fork_and_exec'
    from /home/mark/src/urchin/lib/job.rb:106:in `block in run'
    from /home/mark/src/urchin/lib/job.rb:97:in `each'
    from /home/mark/src/urchin/lib/job.rb:97:in `each_with_index'
    from /home/mark/src/urchin/lib/job.rb:97:in `run'
    from /home/mark/src/urchin/lib/shell.rb:66:in `block in parse_and_run'
    from /home/mark/src/urchin/lib/shell.rb:62:in `each'
    from /home/mark/src/urchin/lib/shell.rb:62:in `parse_and_run'
    from /home/mark/src/urchin/lib/shell.rb:35:in `run'
    from /home/mark/src/urchin/bin/urchin:41:in `<main>'

Track location of command execution in history

When looking back through command history (not simply to repeat a recent command, but when excavating deeper into the past to figure out how you solved a problem that you now face again) it is often useful to know where you were when you executed a command. This would be much easier to reconstruct if the current working directory was available for each command, rather than only available by looking at cd commands previously made.

This could be implemented by itself, or it could be done with the issue "Track shell history in a database", which would (I think) make it much easier to implement, and make changes and configurations to history tracking cakewalk, since every piece of info tracked as part of history is basically another field, and the more flexibility offered to the user (in terms of what to include and what to exclude from history) the more complicated it gets to the developer of the shell, leaving them to basically build database functions from scratch, when they would more easily just use a database. More details in that issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.