irb-history 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +16 -0
- data/README +63 -0
- data/Rakefile +61 -0
- data/THANKS +5 -0
- data/bin/irb-history-server +79 -0
- data/lib/irb/history.rb +5 -0
- data/lib/irb/history/base.rb +26 -0
- data/lib/irb/history/client.rb +36 -0
- data/lib/irb/history/server.rb +95 -0
- metadata +62 -0
data/LICENSE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Copyright (c) 2005 Sam Stephenson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
11
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
12
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
13
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
14
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
15
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
16
|
+
SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
= irb-history
|
2
|
+
|
3
|
+
irb-history gives IRB <b>persistent, shared Readline history</b> by way of
|
4
|
+
Distributed Ruby (DRb). What does that mean?
|
5
|
+
|
6
|
+
==== Persistent
|
7
|
+
|
8
|
+
<tt>irb-history-server</tt> stores its history in YAML in a file of your
|
9
|
+
choice (the default is <tt>~/.irb_history</tt>).
|
10
|
+
|
11
|
+
==== Shared
|
12
|
+
|
13
|
+
Load the irb-history client in your <tt>~/.irbrc</tt>, and you'll instantly
|
14
|
+
have access to the irb-history store. Every line you type is sent to the
|
15
|
+
server and will appear in other clients' histories immediately.
|
16
|
+
|
17
|
+
Because irb-history uses DRb, you can share your history with other IRB
|
18
|
+
sessions:
|
19
|
+
|
20
|
+
* on the same computer
|
21
|
+
* on other computers on your local network
|
22
|
+
* on computers connected to the Internet (fun, but not recommended :))
|
23
|
+
|
24
|
+
=== Installation and usage
|
25
|
+
|
26
|
+
It's a simple process:
|
27
|
+
|
28
|
+
1. <b>Install the gem</b>.
|
29
|
+
$ gem install irb-history
|
30
|
+
|
31
|
+
2. <b>Start a history server</b> listening on <tt>127.0.0.1</tt>,
|
32
|
+
port <tt>26501</tt> (see the {irb-history-server
|
33
|
+
documentation}[link:files/bin/irb-history-server.html] for more options).
|
34
|
+
$ irb-history-server -d
|
35
|
+
|
36
|
+
Note: If you wish to use irb-history on a network, you'll need to pass
|
37
|
+
the <tt>-h</tt> flag with an appropriate address to listen on.
|
38
|
+
|
39
|
+
3. <b>Add three lines to your <tt>~/.irbrc</tt></b>.
|
40
|
+
require 'rubygems'
|
41
|
+
require 'irb/history'
|
42
|
+
IRB::History.start_client
|
43
|
+
This connects to the history server on <tt>127.0.0.1</tt>, port
|
44
|
+
<tt>26501</tt>. If you need to specify a different host and/or port, just
|
45
|
+
pass a DRb URI to <tt>start_client</tt>. For example:
|
46
|
+
IRB::History.start_client 'druby://galt:4000'
|
47
|
+
connects to the history server on host <tt>galt</tt>, port <tt>4000</tt>.
|
48
|
+
|
49
|
+
=== Source code
|
50
|
+
|
51
|
+
Check out the darcs[http://darcs.net/] repository:
|
52
|
+
|
53
|
+
$ darcs get http://dev.conio.net/repos/irb-history
|
54
|
+
|
55
|
+
=== License
|
56
|
+
|
57
|
+
irb-history is freely distributable under the terms of a {MIT-style
|
58
|
+
license}[link:files/LICENSE.html].
|
59
|
+
|
60
|
+
=== Author
|
61
|
+
|
62
|
+
Sam Stephenson <{sam@conio.net}[mailto:sam@conio.net]>
|
63
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
class String
|
6
|
+
def unquote
|
7
|
+
self.gsub /^(['"])(.*)\1$/, '\2'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
PKG_NAME = 'irb-history'
|
12
|
+
PKG_VERSION = '1.0.0'
|
13
|
+
PKG_DESCRIPTION = 'Persistent, shared IRB Readline history'
|
14
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
15
|
+
PKG_DESTINATION = "pkg/#{PKG_NAME}"
|
16
|
+
PKG_AUTHOR = 'Sam Stephenson'
|
17
|
+
PKG_AUTHOR_EMAIL = 'sam@conio.net'
|
18
|
+
PKG_DOC_DIR = 'rdoc'
|
19
|
+
|
20
|
+
task :default => [:rdoc, :package]
|
21
|
+
|
22
|
+
SOURCE_FILES = FileList[
|
23
|
+
'[A-Z]*',
|
24
|
+
'bin/**',
|
25
|
+
'lib/**/*.rb'
|
26
|
+
].to_a
|
27
|
+
|
28
|
+
RDOC_FILES = SOURCE_FILES - %w(Rakefile)
|
29
|
+
|
30
|
+
desc 'Generate documentation'
|
31
|
+
rdoc = Rake::RDocTask.new do |rd|
|
32
|
+
rd.main = 'README'
|
33
|
+
rd.title = PKG_NAME
|
34
|
+
rd.rdoc_dir = PKG_DOC_DIR
|
35
|
+
rd.options += %w(--inline-source --line-numbers)
|
36
|
+
rd.rdoc_files.include RDOC_FILES
|
37
|
+
end
|
38
|
+
|
39
|
+
spec = Gem::Specification.new do |s|
|
40
|
+
s.name = PKG_NAME
|
41
|
+
s.version = PKG_VERSION
|
42
|
+
s.summary = PKG_DESCRIPTION
|
43
|
+
s.description = PKG_DESCRIPTION
|
44
|
+
s.author = PKG_AUTHOR
|
45
|
+
s.email = PKG_AUTHOR_EMAIL
|
46
|
+
|
47
|
+
s.files = SOURCE_FILES
|
48
|
+
s.bindir = 'bin'
|
49
|
+
s.require_path = 'lib'
|
50
|
+
s.executables = %w(irb-history-server)
|
51
|
+
|
52
|
+
s.has_rdoc = true
|
53
|
+
s.rdoc_options = rdoc.option_list.map {|o| o.unquote}
|
54
|
+
s.extra_rdoc_files = RDOC_FILES
|
55
|
+
end
|
56
|
+
|
57
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'Removes documentation and package files'
|
61
|
+
task :clean => [:clobber_rdoc, :clobber_package]
|
data/THANKS
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# = irb-history-server
|
4
|
+
#
|
5
|
+
# Manages an irb-history YAML store and starts a DRb service for irb-history
|
6
|
+
# clients.
|
7
|
+
#
|
8
|
+
# Usage: <tt>irb-history-server [options]</tt>
|
9
|
+
#
|
10
|
+
# -p, --port=port listen on the specified port
|
11
|
+
# (default: 26501)
|
12
|
+
# -h, --host=host bind to the specified host
|
13
|
+
# (default: "127.0.0.1")
|
14
|
+
# -f, --filename=filename use the specified history file
|
15
|
+
# (default: ~/.irb_history)
|
16
|
+
# -d, --daemon make irb-history-server run as a daemon
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'rubygems'
|
20
|
+
require 'irb/history'
|
21
|
+
rescue LoadError
|
22
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
23
|
+
require 'irb/history'
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'optparse'
|
27
|
+
|
28
|
+
OPTIONS = {
|
29
|
+
:port => IRB::History::DEFAULT_PORT,
|
30
|
+
:host => IRB::History::DEFAULT_HOST,
|
31
|
+
:file => IRB::History::DEFAULT_FILE,
|
32
|
+
:fork => false
|
33
|
+
}
|
34
|
+
|
35
|
+
SCRIPT_NAME = File.basename(__FILE__)
|
36
|
+
|
37
|
+
ARGV.options do |opts|
|
38
|
+
opts.banner = "Usage: #{SCRIPT_NAME} [options]"
|
39
|
+
|
40
|
+
opts.separator ''
|
41
|
+
|
42
|
+
opts.on('-p', '--port=port', Integer,
|
43
|
+
"listen on the specified port",
|
44
|
+
"(default: #{OPTIONS[:port]})") {|OPTIONS[:port]|}
|
45
|
+
opts.on('-h', '--host=host', String,
|
46
|
+
"bind to the specified host",
|
47
|
+
"(default: #{OPTIONS[:host].inspect})") {|OPTIONS[:host]|}
|
48
|
+
opts.on('-f', '--filename=filename', String,
|
49
|
+
"use the specified history file",
|
50
|
+
"(default: #{OPTIONS[:file]})") {|OPTIONS[:file]|}
|
51
|
+
opts.on('-d', '--daemon',
|
52
|
+
"make #{SCRIPT_NAME} run as a daemon") {|OPTIONS[:fork]|}
|
53
|
+
|
54
|
+
opts.separator ''
|
55
|
+
|
56
|
+
opts.on(nil, '--help', 'show this help message') {puts opts; exit}
|
57
|
+
|
58
|
+
opts.parse!
|
59
|
+
end
|
60
|
+
|
61
|
+
uri = "druby://#{OPTIONS[:host]}:#{OPTIONS[:port]}"
|
62
|
+
puts "*** #{SCRIPT_NAME} starting on #{uri}"
|
63
|
+
puts "*** history file: #{OPTIONS[:file]}"
|
64
|
+
|
65
|
+
if OPTIONS[:fork]
|
66
|
+
exit if fork
|
67
|
+
Process.setsid
|
68
|
+
exit if fork
|
69
|
+
Dir.chdir '/'
|
70
|
+
[STDIN, STDOUT, STDERR].each {|io| io.reopen('/dev/null', 'r+')}
|
71
|
+
else
|
72
|
+
trap :INT do
|
73
|
+
puts "*** #{SCRIPT_NAME} exiting"
|
74
|
+
exit!
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
IRB::History.start_server uri, OPTIONS[:file]
|
79
|
+
DRb.thread.join
|
data/lib/irb/history.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module IRB #:nododc:
|
2
|
+
module History
|
3
|
+
DEFAULT_HOST = '127.0.0.1'
|
4
|
+
DEFAULT_PORT = 26501
|
5
|
+
DEFAULT_URI = "druby://#{DEFAULT_HOST}:#{DEFAULT_PORT}"
|
6
|
+
DEFAULT_FILE = '~/.irb_history'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Kernel
|
11
|
+
# A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman.
|
12
|
+
#
|
13
|
+
# def foo
|
14
|
+
# returning values = [] do
|
15
|
+
# values << 'bar'
|
16
|
+
# values << 'baz'
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# foo # => ['bar', 'baz']
|
21
|
+
#
|
22
|
+
def returning(value)
|
23
|
+
yield
|
24
|
+
value
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'base')
|
2
|
+
|
3
|
+
module IRB #:nodoc:
|
4
|
+
module History
|
5
|
+
# Reconfigures a running IRB session to use the given remote history
|
6
|
+
# service specified by +uri+, initially retrieving +lines_to_recall+
|
7
|
+
# lines of history.
|
8
|
+
#
|
9
|
+
# Note: This method overrides +gets+ in IRB::ReadlineInputMethod; it
|
10
|
+
# can't be "stopped," and you shouldn't call it more than once.
|
11
|
+
#
|
12
|
+
def self.start_client(uri = DEFAULT_URI, lines_to_recall = 100)
|
13
|
+
require 'drb'
|
14
|
+
|
15
|
+
DRb.start_service
|
16
|
+
history = DRbObject.new nil, uri
|
17
|
+
|
18
|
+
IRB::ReadlineInputMethod.instance_eval do
|
19
|
+
alias_method :old_gets, :gets
|
20
|
+
|
21
|
+
define_method :gets do
|
22
|
+
returning old_gets do
|
23
|
+
line = Readline::HISTORY[-1]
|
24
|
+
history.remember line unless @eof rescue nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Readline::HISTORY.push *history.recall(lines_to_recall)
|
30
|
+
|
31
|
+
at_exit {history.unsubscribe_from Readline::HISTORY} if
|
32
|
+
history.subscribe_to Readline::HISTORY
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), 'base')
|
5
|
+
|
6
|
+
module IRB #:nodoc:
|
7
|
+
module History
|
8
|
+
class Server
|
9
|
+
attr_accessor :service
|
10
|
+
|
11
|
+
# Creates a new Server with the YAML history store file specified
|
12
|
+
# by +filename+.
|
13
|
+
def initialize(filename)
|
14
|
+
@filename = File.expand_path(filename)
|
15
|
+
@subscriptions = []
|
16
|
+
@mutex = Mutex.new
|
17
|
+
load
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the number of lines in the history store.
|
21
|
+
def length
|
22
|
+
@store.length
|
23
|
+
end
|
24
|
+
|
25
|
+
# Stores the given +values+ in the history store, saves the history
|
26
|
+
# store to disk, and notifies any subscribers of the added lines.
|
27
|
+
def remember(*values)
|
28
|
+
@mutex.synchronize do
|
29
|
+
@store += values
|
30
|
+
notify_subscriptions_with *values
|
31
|
+
save
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the last +limit+ history lines from the history store. If
|
36
|
+
# +limit+ is 0 (the default value), a copy of the entire history
|
37
|
+
# store is returned.
|
38
|
+
def recall(limit = 0)
|
39
|
+
@mutex.synchronize do
|
40
|
+
limit = length if limit > length
|
41
|
+
@store[-limit..-1] || []
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Subscribes to the given +readline_history+ (which can be any object
|
46
|
+
# that responds to +push+, but is intended to be used with the
|
47
|
+
# Readline::HISTORY object). When new history lines are added, they'll
|
48
|
+
# be pushed onto subscriptions.
|
49
|
+
def subscribe_to(readline_history)
|
50
|
+
@subscriptions |= [readline_history]
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
# Removes the given +readline_history+ object from the subscription
|
55
|
+
# list. This should be called from +at_exit+ in history clients.
|
56
|
+
def unsubscribe_from(readline_history)
|
57
|
+
@subscriptions -= [readline_history]
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
def load
|
63
|
+
@store = YAML.load_file(@filename) rescue []
|
64
|
+
end
|
65
|
+
|
66
|
+
def save
|
67
|
+
File.open(@filename, 'w+') {|file| file << YAML.dump(@store)}
|
68
|
+
end
|
69
|
+
|
70
|
+
def notify_subscriptions_with(*values)
|
71
|
+
@subscriptions.each do |readline_history|
|
72
|
+
Thread.new do
|
73
|
+
readline_history.push *values rescue nil or
|
74
|
+
unsubscribe_from readline_history
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Starts a Server on the given +uri+ and using the YAML history
|
81
|
+
# file specified by +store_path+. The Server object is instantiated,
|
82
|
+
# a DRb service is started on it, and the Server object is returned.
|
83
|
+
# The DRb service object is accessible via Server#service.
|
84
|
+
def self.start_server(uri = DEFAULT_URI, store_path = DEFAULT_FILE)
|
85
|
+
returning server = Server.new(store_path) do
|
86
|
+
server.service = DRb.start_service uri, server
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if __FILE__ == $0
|
93
|
+
IRB::History.start_server *ARGV
|
94
|
+
DRb.thread.join
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10
|
3
|
+
specification_version: 1
|
4
|
+
name: irb-history
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2005-06-17
|
8
|
+
summary: "Persistent, shared IRB Readline history"
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: sam@conio.net
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: "Persistent, shared IRB Readline history"
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Sam Stephenson
|
29
|
+
files:
|
30
|
+
- LICENSE
|
31
|
+
- Rakefile
|
32
|
+
- README
|
33
|
+
- THANKS
|
34
|
+
- bin/irb-history-server
|
35
|
+
- lib/irb/history.rb
|
36
|
+
- lib/irb/history/server.rb
|
37
|
+
- lib/irb/history/client.rb
|
38
|
+
- lib/irb/history/base.rb
|
39
|
+
test_files: []
|
40
|
+
rdoc_options:
|
41
|
+
- "--inline-source"
|
42
|
+
- "--line-numbers"
|
43
|
+
- "--main"
|
44
|
+
- README
|
45
|
+
- "--title"
|
46
|
+
- irb-history
|
47
|
+
- "-T"
|
48
|
+
- html
|
49
|
+
extra_rdoc_files:
|
50
|
+
- LICENSE
|
51
|
+
- README
|
52
|
+
- THANKS
|
53
|
+
- bin/irb-history-server
|
54
|
+
- lib/irb/history.rb
|
55
|
+
- lib/irb/history/server.rb
|
56
|
+
- lib/irb/history/client.rb
|
57
|
+
- lib/irb/history/base.rb
|
58
|
+
executables:
|
59
|
+
- irb-history-server
|
60
|
+
extensions: []
|
61
|
+
requirements: []
|
62
|
+
dependencies: []
|