nrepl 0.0.1
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/.gitignore +18 -0
- data/.pryrc +3 -0
- data/.tm_properties +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +39 -0
- data/Rakefile +1 -0
- data/lib/nrepl.rb +9 -0
- data/lib/nrepl/core_ext/hash.rb +5 -0
- data/lib/nrepl/repl.rb +158 -0
- data/lib/nrepl/version.rb +3 -0
- data/nrepl.gemspec +25 -0
- metadata +122 -0
data/.gitignore
ADDED
data/.pryrc
ADDED
data/.tm_properties
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Scott Fleckenstein
|
2
|
+
|
3
|
+
MIT License
|
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.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Nrepl
|
2
|
+
|
3
|
+
Nrepl is a ruby library to communicate with a clojure nrepl
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'nrepl'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install nrepl
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Connecting to an existing repl
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
repl = Nrepl::Repl.connect(1234) # connect to port 1234
|
25
|
+
```
|
26
|
+
|
27
|
+
### Evaluating code in the repl
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
repl.eval "(+ 3 3)" # => an array of responses messages from the repl
|
31
|
+
```
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
1. Fork it
|
36
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/nrepl.rb
ADDED
data/lib/nrepl/repl.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'retriable'
|
3
|
+
require 'bencode'
|
4
|
+
|
5
|
+
|
6
|
+
module Nrepl
|
7
|
+
class Repl
|
8
|
+
attr_accessor :session
|
9
|
+
attr_accessor :debug
|
10
|
+
|
11
|
+
##
|
12
|
+
# Connects to an already running nrepl server
|
13
|
+
#
|
14
|
+
# @param [Fixnum] port The port the server is running on
|
15
|
+
# @return [Nrepl::Repl] a repl instance
|
16
|
+
def self.connect(port)
|
17
|
+
new(port)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Starts a new clojure process at the current working directory
|
22
|
+
#
|
23
|
+
# @param [Fixnum,nil] port An optional port number, otherwise leiningen
|
24
|
+
# will pick the port
|
25
|
+
# @return [Nrepl::Repl] a repl instance
|
26
|
+
def self.start(port=nil)
|
27
|
+
read, write = IO.pipe
|
28
|
+
|
29
|
+
pid = fork do
|
30
|
+
read.close
|
31
|
+
Process.setsid
|
32
|
+
STDOUT.reopen write
|
33
|
+
STDERR.reopen write
|
34
|
+
STDIN.reopen "/dev/null", "r"
|
35
|
+
exec "bash -c 'lein repl :headless :port #{port}'"
|
36
|
+
end
|
37
|
+
|
38
|
+
write.close
|
39
|
+
line = read.gets
|
40
|
+
case line
|
41
|
+
when /Address already in use/ ;
|
42
|
+
# no-op, just connect to existing repl
|
43
|
+
when /nREPL server started on port (\d+)/
|
44
|
+
port = $~[1].to_i
|
45
|
+
else
|
46
|
+
raise "Unknown error launching repl: #{line}"
|
47
|
+
Process.kill(pid)
|
48
|
+
Process.waitpid(pid)
|
49
|
+
end
|
50
|
+
read.close
|
51
|
+
|
52
|
+
new(port)
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(port)
|
56
|
+
@port = port
|
57
|
+
@session = nil
|
58
|
+
@debug = false
|
59
|
+
end
|
60
|
+
|
61
|
+
def debug!
|
62
|
+
@debug = true
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Returns true if we can get a socket connection to this repl
|
68
|
+
#
|
69
|
+
# @return [Boolean] true if running, false if not
|
70
|
+
def running?
|
71
|
+
!!get_socket(0)
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Clones the bindings for the provided session and sets the new session to
|
76
|
+
# current
|
77
|
+
#
|
78
|
+
# @param [String,nil] session The optional prototype session to clone from
|
79
|
+
# @return [String] the new session id
|
80
|
+
def clone_session(session=nil)
|
81
|
+
response = send(op:"clone", session:session).first
|
82
|
+
@session = response["new-session"]
|
83
|
+
@session
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Closes the provided sessions
|
88
|
+
#
|
89
|
+
# @param [String,nil] session An optional session identifier, otherwise the
|
90
|
+
# current session will be closed
|
91
|
+
def close_session(session=nil)
|
92
|
+
result = send(op:"close", session:session)
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Returns a list of sessions known to the repl
|
97
|
+
#
|
98
|
+
# @return [<String>] An array of session ids
|
99
|
+
def list_sessions
|
100
|
+
response = send(op:"ls-sessions").first
|
101
|
+
response["sessions"]
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Evaluates code on the repl, returning an array of responses
|
106
|
+
#
|
107
|
+
# @param [String] code The code to run
|
108
|
+
def eval(code, &block)
|
109
|
+
result = send(op:"eval", code:code, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Sends a raw command to the repl, returning an array of responses
|
114
|
+
#
|
115
|
+
def send(command)
|
116
|
+
command = command.reverse_merge(session: @session).delete_blank
|
117
|
+
|
118
|
+
sock = get_socket
|
119
|
+
|
120
|
+
sock.print command.bencode
|
121
|
+
|
122
|
+
puts ">>> #{command.inspect}" if @debug
|
123
|
+
|
124
|
+
responses = []
|
125
|
+
done = false
|
126
|
+
|
127
|
+
begin
|
128
|
+
until done
|
129
|
+
retriable timeout: 0.2, tries: 100 do
|
130
|
+
raw = sock.recv(100000) #TODO: figure out better way to ensure we've drained the receive buffer besides large magic number
|
131
|
+
decoded = raw.bdecode
|
132
|
+
|
133
|
+
puts "<<< #{decoded}" if @debug
|
134
|
+
responses << decoded
|
135
|
+
yield decoded if block_given?
|
136
|
+
|
137
|
+
status = responses.last["status"]
|
138
|
+
done = status.include?("done") || status.include?("error")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
rescue BEncode::DecodeError
|
142
|
+
# TODO
|
143
|
+
end
|
144
|
+
|
145
|
+
responses
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
def get_socket(tries = 3)
|
151
|
+
retriable on: [Errno::ECONNREFUSED], tries: tries, interval: 3 do
|
152
|
+
TCPSocket.new("localhost", @port)
|
153
|
+
end
|
154
|
+
rescue Errno::ECONNREFUSED
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/nrepl.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nrepl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "nrepl"
|
8
|
+
gem.version = Nrepl::VERSION
|
9
|
+
gem.authors = ["Scott Fleckenstein"]
|
10
|
+
gem.email = ["nullstyle@gmail.com"]
|
11
|
+
gem.description = %q{nrepl is a library used to connect a clojure nrepl}
|
12
|
+
gem.summary = %q{nrepl is a library used to connect a clojure nrepl}
|
13
|
+
gem.homepage = "https://github.com/nullstyle/nrepl"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "bencode", "~> 0.7.0"
|
21
|
+
gem.add_dependency "retriable", "~> 1.3.3"
|
22
|
+
gem.add_dependency "activesupport", "~> 3.2.11"
|
23
|
+
|
24
|
+
gem.add_development_dependency "pry", "~> 0.9.11.4"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nrepl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Scott Fleckenstein
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bencode
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.7.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.7.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: retriable
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.3.3
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activesupport
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.2.11
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.2.11
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pry
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.11.4
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.11.4
|
78
|
+
description: nrepl is a library used to connect a clojure nrepl
|
79
|
+
email:
|
80
|
+
- nullstyle@gmail.com
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .pryrc
|
87
|
+
- .tm_properties
|
88
|
+
- Gemfile
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- lib/nrepl.rb
|
93
|
+
- lib/nrepl/core_ext/hash.rb
|
94
|
+
- lib/nrepl/repl.rb
|
95
|
+
- lib/nrepl/version.rb
|
96
|
+
- nrepl.gemspec
|
97
|
+
homepage: https://github.com/nullstyle/nrepl
|
98
|
+
licenses: []
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.8.23
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: nrepl is a library used to connect a clojure nrepl
|
121
|
+
test_files: []
|
122
|
+
has_rdoc:
|