ripl-fresh 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemspec +19 -0
- data/CHANGELOG.rdoc +2 -0
- data/LICENSE +22 -0
- data/README.rdoc +76 -0
- data/Rakefile +28 -0
- data/bin/fresh +3 -0
- data/bin/ripl-fresh +5 -0
- data/deps.rip +1 -0
- data/lib/bond/completions/ripl-fresh.rb +17 -0
- data/lib/ripl-fresh/bond_workaround.rb +0 -0
- data/lib/ripl/fresh.rb +156 -0
- data/lib/ripl/fresh/commands.rb +32 -0
- metadata +93 -0
data/.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'rubygems' unless defined?(::Gem)
|
3
|
+
require File.dirname(__FILE__) + "/lib/ripl/fresh"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ripl-fresh"
|
7
|
+
s.version = Ripl::Fresh::VERSION
|
8
|
+
s.authors = ["Jan Lelis"]
|
9
|
+
s.email = "mail@janlelis.de"
|
10
|
+
s.homepage = "http://github.com/janlelis/fresh"
|
11
|
+
s.summary = "Fresh Ruby Enhanced SHell"
|
12
|
+
s.description = "Fresh Ruby Enhanced SHell automatically detects, if your current command should be Ruby or a system command."
|
13
|
+
s.required_rubygems_version = ">= 1.3.6"
|
14
|
+
s.executables = ['ripl-fresh', 'fresh']
|
15
|
+
s.add_dependency 'ripl', '>= 0.2.5'
|
16
|
+
s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} **/deps.rip]) + %w{Rakefile .gemspec}
|
17
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE"]
|
18
|
+
s.license = 'MIT'
|
19
|
+
end
|
data/CHANGELOG.rdoc
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2010 Jan Lelis
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
= Fresh Ruby Enhanced SHell
|
2
|
+
|
3
|
+
We love Ruby. We love the command line. So... the shell needs to be rubyfied ;).
|
4
|
+
|
5
|
+
== How does it work?
|
6
|
+
|
7
|
+
Basically, fresh is a Ruby console like irb: Enter a Ruby expression and it gets evaluated. But not everything is interpreted as Ruby: The input is thrown against a regular expression to determine if it is meant to be a Ruby or a system command.
|
8
|
+
|
9
|
+
May sound like voodoo, but works surprisingly well in practice ;).
|
10
|
+
|
11
|
+
== Get fresh
|
12
|
+
|
13
|
+
Install the gem with:
|
14
|
+
|
15
|
+
gem install ripl-fresh
|
16
|
+
|
17
|
+
Start it with:
|
18
|
+
|
19
|
+
ripl fresh
|
20
|
+
|
21
|
+
(or just <tt>fresh</tt>)
|
22
|
+
|
23
|
+
== Usage & configuration options
|
24
|
+
|
25
|
+
The main regexp to determine if the command should be interpreted as system command is similar to this one: <tt>/^[a-z_-]+\s+.*/i</tt> (match a single word followed by at least one space). It can be adjusted in <tt>Ripl.config[:fresh_system_regexp]</tt>.
|
26
|
+
|
27
|
+
Of course, there are also exceptions that should still get interpreted as Ruby (e.g. <tt>def </tt>). These can be found and modified in the <tt>Ripl.config[:fresh_ruby_words]</tt> array.
|
28
|
+
|
29
|
+
Single words get interpreted as Ruby by default. You can set your "single system words" in <tt>Ripl.config[:fresh_system_words]</tt> (e.g. <tt>ls</tt>).
|
30
|
+
|
31
|
+
There is also a third kind of command mode (besides <tt>:ruby</tt> and <tt>:system</tt>): <tt>:mixed</tt>. They look and feel like system commands, but redirect to the Ruby method described by the first word. You can register them in <tt> Ripl.config[:fresh_mixed_words]</tt> (e.g. +cd+).
|
32
|
+
|
33
|
+
Of course, there is a way to explicitly set your command mode: You can prefix your input with a space to force Ruby mode as well as you can prefix it with <tt>^</tt> to force system mode. The strings used for this can be customized in <tt>Ripl.config[:fresh_system_prefix]</tt> and <tt>Ripl.config[:fresh_ruby_prefix]</tt>.
|
34
|
+
|
35
|
+
You need to take a look at <tt>get_input</tt> method in the source file to 100% understand the command mode detection way.
|
36
|
+
|
37
|
+
=== Defaults
|
38
|
+
|
39
|
+
# prefixes
|
40
|
+
Ripl.config[:fresh_system_prefix] = %w[^]
|
41
|
+
Ripl.config[:fresh_ruby_prefix] = [' ']
|
42
|
+
# single words
|
43
|
+
Ripl.config[:fresh_system_words] = %w[top ls]
|
44
|
+
Ripl.config[:fresh_ruby_words] = %w[begin case class def for if module undef unless until while puts warn print p pp ap raise fail loop require load lambda proc system]
|
45
|
+
# catch mix words
|
46
|
+
Ripl.config[:fresh_mixed_words] = %w[cd]
|
47
|
+
# main regexp
|
48
|
+
Ripl.config[:fresh_system_regexp] = /^([a-z_-]+)\s+(?!(?:[=%*]|!=|\+=|-=|\/=))/i
|
49
|
+
|
50
|
+
== Customization
|
51
|
+
|
52
|
+
Besides customizing your fresh with the configuration options, you can further enhance it with Ruby plugins, because it's based on {ripl}[https://github.com/cldwalker/ripl]. Just install the <tt>ripl-plugin_name</tt> and add it to your <tt>.riplrc</tt> file:
|
53
|
+
|
54
|
+
require 'ripl/plugin_name'
|
55
|
+
|
56
|
+
Currently, most {plugins}[http://github.com/cldwalker/ripl-color_error] {enable}[http://github.com/janlelis/ripl-color_result] {colors}[http://github.com/janlelis/ripl-color_streams] and {IRB}[http://github.com/janlelis/ripl-multi_line] -{like}[http://github.com/cldwalker/ripl-commands] {features}[http://github.com/cldwalker/ripl-irb].
|
57
|
+
|
58
|
+
== TODO
|
59
|
+
|
60
|
+
There are lots of things which can get better:
|
61
|
+
|
62
|
+
* Improve auto-completion
|
63
|
+
* More cool (and colorful?) <tt>:mixed</tt> Ruby commands
|
64
|
+
* Improve interaction between system and ruby commands
|
65
|
+
* <tt>ripl-multi_line</tt> for system commands
|
66
|
+
* Result of system commands should be available for ruby, not only printed to stdout
|
67
|
+
* Improve default configuration
|
68
|
+
* Fresh ideas
|
69
|
+
|
70
|
+
Feel free to fork in your improvements ;)
|
71
|
+
|
72
|
+
== Copyright
|
73
|
+
|
74
|
+
Copyright (c) 2010 Jan Lelis <http://code-needs-smileys.com> released under the MIT license.
|
75
|
+
|
76
|
+
J-_-L
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
def gemspec
|
5
|
+
@gemspec ||= eval(File.read('.gemspec'), binding, '.gemspec')
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Build the gem"
|
9
|
+
task :gem=>:gemspec do
|
10
|
+
sh "gem build .gemspec"
|
11
|
+
FileUtils.mkdir_p 'pkg'
|
12
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Install the gem locally"
|
16
|
+
task :install => :gem do
|
17
|
+
sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Generate the gemspec"
|
21
|
+
task :generate do
|
22
|
+
puts gemspec.to_ruby
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Validate the gemspec"
|
26
|
+
task :gemspec do
|
27
|
+
gemspec.validate
|
28
|
+
end
|
data/bin/fresh
ADDED
data/bin/ripl-fresh
ADDED
data/deps.rip
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ripl >=0.2.5
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# no advanced auto completion, yet
|
2
|
+
# only do some file completion - because it's the most important completion ;)
|
3
|
+
|
4
|
+
require 'readline'
|
5
|
+
|
6
|
+
file_completion = proc{ |input|
|
7
|
+
::Readline::FILENAME_COMPLETION_PROC.call(input) || []
|
8
|
+
}
|
9
|
+
|
10
|
+
complete :on => Ripl.config[:fresh_system_regexp],
|
11
|
+
:search=>false,
|
12
|
+
&file_completion
|
13
|
+
|
14
|
+
# TODO fires only when space after ^
|
15
|
+
complete :on => Ripl::Fresh.option_array_to_regexp( Ripl.config[:fresh_system_prefix] ),
|
16
|
+
:search=>false,
|
17
|
+
&file_completion
|
File without changes
|
data/lib/ripl/fresh.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'ripl'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Ripl
|
5
|
+
module Fresh
|
6
|
+
VERSION = '0.1.0'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# helper to parse options
|
10
|
+
def option_array_to_regexp(option)
|
11
|
+
case option
|
12
|
+
when Regexp # note: some options still _have_ to be arrays
|
13
|
+
option
|
14
|
+
when Array, Set
|
15
|
+
/^(#{
|
16
|
+
option.map{ |char|
|
17
|
+
Regexp.escape char.to_s
|
18
|
+
}*'|'
|
19
|
+
})/
|
20
|
+
else
|
21
|
+
option.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Shell
|
27
|
+
# setup Fresh
|
28
|
+
def before_loop
|
29
|
+
@command_mode = :ruby
|
30
|
+
super
|
31
|
+
# register bond completion
|
32
|
+
Ripl.config[:completion][:gems] ||= []
|
33
|
+
Ripl.config[:completion][:gems] << 'ripl-fresh'
|
34
|
+
# load :mixed commands
|
35
|
+
require File.dirname(__FILE__) + '/fresh/commands'
|
36
|
+
end
|
37
|
+
|
38
|
+
# determine @command_mode
|
39
|
+
def get_input
|
40
|
+
input = super
|
41
|
+
|
42
|
+
return input if @buffer # ripl-multi_line
|
43
|
+
|
44
|
+
@command_mode = case input
|
45
|
+
# force system with a single ^
|
46
|
+
when Ripl::Fresh.option_array_to_regexp( Ripl.config[:fresh_system_prefix] )
|
47
|
+
input = input[$1.size..-1] # TODO refactor, too hacky?
|
48
|
+
:system
|
49
|
+
# force ruby with a space
|
50
|
+
when Ripl::Fresh.option_array_to_regexp( Ripl.config[:fresh_ruby_prefix] )
|
51
|
+
input = input[$1.size..-1]
|
52
|
+
:ruby
|
53
|
+
# single words
|
54
|
+
when /^\w+$/i
|
55
|
+
if Ripl.config[:fresh_ruby_words].include?($&)
|
56
|
+
:ruby
|
57
|
+
elsif Ripl.config[:fresh_mixed_words].include?($&)
|
58
|
+
:mixed
|
59
|
+
elsif Ripl.config[:fresh_system_words].include?($&)
|
60
|
+
:system
|
61
|
+
else
|
62
|
+
:ruby
|
63
|
+
end
|
64
|
+
# set of commands that call the ruby method but have command line style calling (args without "")
|
65
|
+
when Ripl::Fresh.option_array_to_regexp( Ripl.config[:fresh_mixed_words] )
|
66
|
+
:mixed
|
67
|
+
# here is the important magical regex for shell commands
|
68
|
+
when Ripl.config[:fresh_system_regexp]
|
69
|
+
if Ripl.config[:fresh_ruby_words].include? $1
|
70
|
+
:ruby
|
71
|
+
else
|
72
|
+
:system
|
73
|
+
end
|
74
|
+
# default is still ruby ;)
|
75
|
+
else
|
76
|
+
:ruby
|
77
|
+
end
|
78
|
+
|
79
|
+
input
|
80
|
+
end
|
81
|
+
|
82
|
+
# get result (depending on @command_mode)
|
83
|
+
def loop_eval(input)
|
84
|
+
if input == ''
|
85
|
+
@command_mode = :system and return
|
86
|
+
end
|
87
|
+
|
88
|
+
case @command_mode
|
89
|
+
when :system # execute command
|
90
|
+
ret = system input
|
91
|
+
case ret
|
92
|
+
when false
|
93
|
+
warn '[non-nil exit status]' # too verbose?
|
94
|
+
when nil
|
95
|
+
warn "[command error #{$?.exitstatus}]" # add message?
|
96
|
+
end
|
97
|
+
ret
|
98
|
+
|
99
|
+
when :mixed # call the ruby method, but with shell style arguments
|
100
|
+
m, *args = *input.split
|
101
|
+
super "#{m}(*#{args.to_s})"
|
102
|
+
|
103
|
+
else # good old :ruby
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# system commands don't have output values and Ruby is displayed normally
|
110
|
+
def print_result(result)
|
111
|
+
if @error_raised ||
|
112
|
+
@command_mode == :system ||
|
113
|
+
@command_mode == :mixed && (!result || result == '')
|
114
|
+
# don't display anything
|
115
|
+
else
|
116
|
+
super # puts(format_result(result))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# catch ctrl+c
|
121
|
+
def loop_once(*args)
|
122
|
+
super
|
123
|
+
rescue Interrupt
|
124
|
+
@buffer = @error_raised = nil
|
125
|
+
puts '[C]'
|
126
|
+
retry
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# hook in (and work around readline loading behaviour)
|
133
|
+
Ripl.config[:readline] = false
|
134
|
+
require 'ripl/readline'
|
135
|
+
Ripl::Shell.send :include, Ripl::Fresh::Shell
|
136
|
+
|
137
|
+
## fresh config ###
|
138
|
+
|
139
|
+
# prefixes
|
140
|
+
Ripl.config[:fresh_system_prefix] = %w[^]
|
141
|
+
Ripl.config[:fresh_ruby_prefix] = [' ']
|
142
|
+
# single words
|
143
|
+
Ripl.config[:fresh_system_words] = %w[top ls]
|
144
|
+
Ripl.config[:fresh_ruby_words] = %w[begin case class def for if module undef unless until while puts warn print p pp ap raise fail loop require load lambda proc system]
|
145
|
+
# catch mix words
|
146
|
+
Ripl.config[:fresh_mixed_words] = %w[cd]
|
147
|
+
# main regexp
|
148
|
+
Ripl.config[:fresh_system_regexp] = /^([a-z_-]+)\s+(?!(?:[=%*]|!=|\+=|-=|\/=))/i
|
149
|
+
# configure directory prompt
|
150
|
+
Ripl.config[:prompt] = proc{
|
151
|
+
path = FileUtils.pwd
|
152
|
+
path.gsub! /#{ File.expand_path('~') }/, '~'
|
153
|
+
path + '> '
|
154
|
+
}
|
155
|
+
|
156
|
+
# J-_-L
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'ripl'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Ripl
|
5
|
+
module Fresh
|
6
|
+
module Commands
|
7
|
+
=begin
|
8
|
+
def ls(path='.')
|
9
|
+
Dir[ File.join( path, '*' )].map{|res| res =~ /^#{path}\/?/; $' }
|
10
|
+
end
|
11
|
+
alias dir ls
|
12
|
+
=end
|
13
|
+
|
14
|
+
def cd( path = File.expand_path('~') )
|
15
|
+
new_last_path = FileUtils.pwd
|
16
|
+
if path == '-'
|
17
|
+
if @last_path
|
18
|
+
path = @last_path
|
19
|
+
else
|
20
|
+
warn 'Sorry, there is no previous directory.'
|
21
|
+
return
|
22
|
+
end
|
23
|
+
end
|
24
|
+
FileUtils.cd path
|
25
|
+
@last_path = new_last_path
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Ripl::Commands.send :include, Ripl::Fresh::Commands if defined? Ripl::Commands
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ripl-fresh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jan Lelis
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-24 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: ripl
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 2
|
31
|
+
- 5
|
32
|
+
version: 0.2.5
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Fresh Ruby Enhanced SHell automatically detects, if your current command should be Ruby or a system command.
|
36
|
+
email: mail@janlelis.de
|
37
|
+
executables:
|
38
|
+
- ripl-fresh
|
39
|
+
- fresh
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README.rdoc
|
44
|
+
- LICENSE
|
45
|
+
files:
|
46
|
+
- lib/ripl/fresh/commands.rb
|
47
|
+
- lib/ripl/fresh.rb
|
48
|
+
- lib/ripl-fresh/bond_workaround.rb
|
49
|
+
- lib/bond/completions/ripl-fresh.rb
|
50
|
+
- bin/fresh
|
51
|
+
- bin/ripl-fresh
|
52
|
+
- README.rdoc
|
53
|
+
- CHANGELOG.rdoc
|
54
|
+
- deps.rip
|
55
|
+
- Rakefile
|
56
|
+
- .gemspec
|
57
|
+
- LICENSE
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/janlelis/fresh
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 3
|
83
|
+
- 6
|
84
|
+
version: 1.3.6
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.7
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Fresh Ruby Enhanced SHell
|
92
|
+
test_files: []
|
93
|
+
|