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.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ lib/nrepl/snippets.rb
data/.pryrc ADDED
@@ -0,0 +1,3 @@
1
+ require 'nrepl'
2
+
3
+ include Nrepl
@@ -0,0 +1,2 @@
1
+ projectDirectory = $CWD
2
+ include = "{$include,.pryrc,.gitignore}"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nrepl.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ require "nrepl/version"
2
+
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/object'
5
+ require 'nrepl/core_ext/hash'
6
+
7
+ module Nrepl
8
+ autoload :Repl, 'nrepl/repl'
9
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def delete_blank
3
+ delete_if{|k, v| v.blank? or (v.instance_of?(Hash) && v.delete_blank.empty?)}
4
+ end
5
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Nrepl
2
+ VERSION = "0.0.1"
3
+ end
@@ -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: