");
20 | };
21 |
22 | $.ws = function() { return ws };
23 | $.ws.nirvanaComplete = function(val) { ws.send(':AUTOCOMPLETE: '+val); };
24 | })(jQuery);
25 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT LICENSE
2 |
3 | Copyright (c) 2010 Gabriel Horner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | require 'rubygems' unless Object.const_defined?(:Gem)
3 | require File.dirname(__FILE__) + "/lib/nirvana/version"
4 |
5 | Gem::Specification.new do |s|
6 | s.name = "nirvana"
7 | s.version = Nirvana::VERSION
8 | s.authors = ["Gabriel Horner"]
9 | s.email = "gabriel.horner@gmail.com"
10 | s.homepage = "http://github.com/cldwalker/nirvana"
11 | s.summary = "A ruby web shell that is very ape and very nice"
12 | s.description = "A ruby web shell that has autocompletion and readline behavior. It uses websockets, repl.js, readline.js and ripl for the shell engine."
13 | s.required_rubygems_version = ">= 1.3.6"
14 | s.rubyforge_project = 'tagaholic'
15 | s.executables = ['nirvana', 'nirvana-websocket']
16 | s.add_dependency 'ripl', '>= 0.3.0'
17 | s.add_dependency 'escape_utils', '>= 0.1.8'
18 | s.add_dependency 'json_pure', '>= 1.4.3'
19 | s.add_dependency 'em-websocket', '>= 0.1.4'
20 | s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} **/deps.rip]) + %w{Rakefile .gemspec}
21 | s.files += Dir.glob('lib/**/*.{css,html,js,gif}')
22 | s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
23 | s.license = 'MIT'
24 | end
25 |
--------------------------------------------------------------------------------
/lib/nirvana/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | nirvana
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
29 |
30 |
31 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/lib/nirvana/shell.rb:
--------------------------------------------------------------------------------
1 | require 'json'
2 | require 'ripl/completion'
3 |
4 | module Nirvana
5 | # Included into Ripl::Shell at runtime
6 | module Shell
7 | def web_loop_once(input)
8 | super
9 | @eval_error = nil
10 | @input[/^:AUTOCOMPLETE:/] ? get_completions(@input) : loop_once
11 | rescue Exception => e
12 | exit if e.message[/^uncaught throw `ripl_exit'/]
13 | html_error(e, "Internal #{@name} error: ")
14 | end
15 |
16 | def print_result(result)
17 | @eval_error || format_result(@result)
18 | end
19 |
20 | def loop_eval(str)
21 | @stdout, @stderr, result = Util.capture_all { super(str) }
22 | result
23 | end
24 |
25 | def print_eval_error(error)
26 | @eval_error = html_error(error, '')
27 | end
28 |
29 | def format_result(result)
30 | stdout, stderr, output = Util.capture_all { super }
31 | @stdout << (stdout.empty? ? output : stdout)
32 | @stderr << stderr
33 | output = Util.format_output @stdout
34 | output = "
#{@stderr}
" + output unless @stderr.to_s.empty?
35 | output
36 | end
37 |
38 | protected
39 | def html_error(error, message)
40 | "#{Util.format_output(message + format_error(error))}"
41 | end
42 |
43 | def get_completions(input)
44 | arr = completions input.sub(/^:AUTOCOMPLETE:\s*/, '')
45 | ':AUTOCOMPLETE: ' + JSON.generate(arr)
46 | end
47 |
48 | def completions(line_buffer)
49 | input = line_buffer[/([^#{Bond::Readline::DefaultBreakCharacters}]+)$/,1]
50 | arr = Bond.agent.call(input || line_buffer, line_buffer)
51 | return [] if arr[0].to_s[/^Bond Error:/] #silence bond debug errors
52 | return arr if input == line_buffer
53 | chopped_input = line_buffer.sub(/#{Regexp.quote(input.to_s)}$/, '')
54 | arr.map {|e| chopped_input + e }
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | == Description
2 | A ruby web shell that has autocompletion and readline behavior. It uses
3 | websockets, repl.js, readline.js and ripl for the shell engine.
4 |
5 | == Install
6 | Install the gem with:
7 |
8 | sudo gem install nirvana
9 |
10 | == Usage
11 |
12 | Your browser must have html5 websockets support.
13 |
14 | To use, start a websocket server and open nirvana in a tab
15 |
16 | # On a mac
17 | $ nirvana
18 |
19 | # Everywhere else
20 | $ nirvana | command_to_browser_path
21 |
22 | If you close the tab, the path to nirvana's html page is (for reopening)
23 |
24 | $ echo $(dirname $(gem which nirvana))/nirvana/public/index.html
25 |
26 | To see what options nirvana takes (mostly options like ripl):
27 |
28 | $ nirvana -h
29 |
30 | Once you're in the nirvana web shell, autocompletion should work better than irb's (argument
31 | autocompletion):
32 |
33 | >> Bo[TAB]
34 | >> Bond
35 | >> Bond.const[TAB]
36 | Bond.const_defined?
37 | Bond.const_get
38 | Bond.const_missing
39 | Bond.const_set
40 | Bond.constants
41 | >> Bond.const_g[TAB]
42 | >> Bond.const_get :Ag[TAB]
43 | >> Bond.const_get :Agent
44 |
45 | Also notice that a subset of readline's functionality is available. Try C-l, C-r or C-p and they
46 | should do what readline normally does. For more keybindings, see
47 | {readline.js}[http://github.com/cldwalker/readline.js].
48 |
49 | == Customize
50 | Since nirvana uses ripl under the hood, most shell behavior is customizable with ripl plugins which
51 | get loaded from ~/.riplrc. See {ripl}[http://github.com/cldwalker/ripl] for more.
52 |
53 | == Links
54 | * {ripl}[http://github.com/cldwalker/ripl]
55 | * {readline.js}[http://github.com/cldwalker/readline.js]
56 | * {repl.js}[http://github.com/cldwalker/repl.js]
57 |
58 | == Bugs/Issues
59 | Please report them {on github}[http://github.com/cldwalker/nirvana/issues]. For javascript issues,
60 | report them on {readline.js}[http://github.com/cldwalker/readline.js/issues] or
61 | {repl.js}[http://github.com/cldwalker/repl.js/issues] as appropriate.
62 |
63 | == Credits
64 | * {rkh's brirb}[http://github.com/rkh/brirb]: Original prototype which inspired this project
65 |
66 | == License
67 | nirvana is MIT licensed. nirvana comes bundled with other libraries which have the following
68 | licenses: jquery (GPL2 and MIT), jquery.hotkeys plugin (no license), repl.js jquery plugin (MIT) and
69 | readline.js jquery plugin (MIT).
70 |
71 | == Todo
72 | * Tests
73 | * Easier way to reopen an existing session
74 | * Load ~/.irb_history into readline.js
75 | * Customizable html and js
76 | * Use text area for multi-line input
77 | * See readline.js and repl.js todos for javascript todos
78 | * Possible plugins for sinatra and em-websocket-server
79 |
--------------------------------------------------------------------------------
/lib/nirvana/public/js/jquery.repl.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | var screen, input, spinner_id, resultPrompt, prompt_id;
3 | var spinner = "