relisp 0.9.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/CHANGELOG +4 -0
- data/COPYING +674 -0
- data/Manifest +18 -0
- data/README +171 -0
- data/Rakefile +50 -0
- data/examples/elisp_master/elisp_master.el +54 -0
- data/examples/elisp_master/ruby_slave +19 -0
- data/examples/ruby_master/ruby_master_example +27 -0
- data/lib/relisp/editing_types.rb +86 -0
- data/lib/relisp/programming_types.rb +293 -0
- data/lib/relisp/slaves.rb +365 -0
- data/lib/relisp.rb +30 -0
- data/setup.rb +1599 -0
- data/src/relisp.el +264 -0
- data/src/relisp.elc +0 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +279 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/test_editing_types.rb +43 -0
- data/test/test_programming_types.rb +275 -0
- data/test/test_slaves.rb +84 -0
- metadata +110 -0
data/src/relisp.el
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
;;; relisp.el --- library for ruby/elisp interaction
|
2
|
+
|
3
|
+
;; Copyright (C) 2009 <don@ohspite.net>
|
4
|
+
|
5
|
+
;; This file is part of Relisp.
|
6
|
+
|
7
|
+
;; Relisp is free software; you can redistribute it and/or modify it
|
8
|
+
;; under the terms of the GNU General Public License as published by
|
9
|
+
;; the Free Software Foundation; either version 2 of the License, or
|
10
|
+
;; (at your option) any later version.
|
11
|
+
|
12
|
+
;; Relisp is distributed in the hope that it will be useful, but
|
13
|
+
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
;; General Public License for more details.
|
16
|
+
|
17
|
+
;; You should have received a copy of the GNU General Public License
|
18
|
+
;; along with this program; if not, write to the Free Software
|
19
|
+
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
20
|
+
;; 02110-1301 USA
|
21
|
+
|
22
|
+
|
23
|
+
;; TODO:
|
24
|
+
;; signal errors when ruby returns an error?
|
25
|
+
|
26
|
+
|
27
|
+
;;; first, some general string functions
|
28
|
+
|
29
|
+
(defun relisp-trim-leading-whitespace (str)
|
30
|
+
"Remove leading whitespace characters from STR."
|
31
|
+
(let ((s (if (symbolp str)(symbol-name str) str))
|
32
|
+
(whitespace-regexp "\\( \\|\f\\|\t\\|\n\\)"))
|
33
|
+
(save-excursion
|
34
|
+
(while (and
|
35
|
+
(not (null (string-match (concat "^" whitespace-regexp) s)))
|
36
|
+
(> (length s) (string-match (concat "^" whitespace-regexp) s)))
|
37
|
+
(setq s (replace-match "" t nil s))))
|
38
|
+
s))
|
39
|
+
|
40
|
+
(defun relisp-trim-trailing-whitespace (str)
|
41
|
+
"Remove trailing whitespace characters from STR."
|
42
|
+
(let ((s (if (symbolp str)(symbol-name str) str))
|
43
|
+
(whitespace-regexp "\\( \\|\f\\|\t\\|\n\\)"))
|
44
|
+
(save-excursion
|
45
|
+
(while (and
|
46
|
+
(not (null (string-match (concat whitespace-regexp "$") s)))
|
47
|
+
(> (length s) (string-match (concat whitespace-regexp "$") s)))
|
48
|
+
(setq s (replace-match "" t nil s))))
|
49
|
+
s))
|
50
|
+
|
51
|
+
(defun relisp-strip (str)
|
52
|
+
"Remove leading and trailing whitespace from STR."
|
53
|
+
(relisp-trim-leading-whitespace (relisp-trim-trailing-whitespace str)))
|
54
|
+
|
55
|
+
;;; now real stuff
|
56
|
+
|
57
|
+
(defvar relisp-slave-name "relisp-slave" "Name of the relisp ruby slave process.")
|
58
|
+
(defvar relisp-buffer-name "*Relisp*" "Name of the relisp output buffer.")
|
59
|
+
|
60
|
+
;; to prohibit free variable warnings
|
61
|
+
(defvar relisp-emacs-master-p t)
|
62
|
+
(defvar relisp-slave-process)
|
63
|
+
(defvar relisp-ruby-output)
|
64
|
+
(defvar relisp-question-code)
|
65
|
+
(defvar relisp-answer-code)
|
66
|
+
(defvar relisp-error-code)
|
67
|
+
(defvar relisp-ruby-return)
|
68
|
+
(defvar relisp-previous-result)
|
69
|
+
|
70
|
+
(defun relisp-log (text)
|
71
|
+
"Insert TEXT at the end of `relisp-buffer-name', unless emacs is the slave."
|
72
|
+
(when relisp-emacs-master-p
|
73
|
+
(get-buffer-create relisp-buffer-name)
|
74
|
+
(unless (string-match (relisp-endofmessage-regexp) (relisp-strip text))
|
75
|
+
(set-buffer relisp-buffer-name)
|
76
|
+
(goto-char (point-max))
|
77
|
+
(insert text "\n"))))
|
78
|
+
|
79
|
+
(defun relisp-write-to-ruby (message)
|
80
|
+
"Send MESSAGE to the ruby process."
|
81
|
+
(if relisp-emacs-master-p
|
82
|
+
(process-send-string relisp-slave-process (concat message "\n"))
|
83
|
+
(message message)))
|
84
|
+
|
85
|
+
(defun relisp-read-from-ruby nil
|
86
|
+
"Accept ruby input, stopping at a match to `relisp-endofmessage-regexp'."
|
87
|
+
(if relisp-emacs-master-p
|
88
|
+
(relisp-accept-slave-output)
|
89
|
+
(relisp-accept-master-output)))
|
90
|
+
|
91
|
+
(defun relisp-accept-slave-output nil
|
92
|
+
"Accept a full ruby message when ruby is the slave process."
|
93
|
+
(while (and (relisp-slave-alive-p)
|
94
|
+
(null (string-match (relisp-endofmessage-regexp)
|
95
|
+
relisp-ruby-output)))
|
96
|
+
(accept-process-output))
|
97
|
+
(let ((val relisp-ruby-output))
|
98
|
+
(setq relisp-ruby-output "")
|
99
|
+
val))
|
100
|
+
|
101
|
+
(defun relisp-accept-master-output nil
|
102
|
+
"Accept a full ruby message when emacs is the slave process."
|
103
|
+
(let ((output "")
|
104
|
+
(output-line ""))
|
105
|
+
(while (null (string-match (relisp-endofmessage-regexp) output-line))
|
106
|
+
(setq output-line (read-from-minibuffer ""))
|
107
|
+
(setq output (concat output output-line)))
|
108
|
+
output))
|
109
|
+
|
110
|
+
(defun relisp-endofmessage-regexp nil
|
111
|
+
"Return a regexp that matches codes indicating a message termination."
|
112
|
+
(concat "\\(" relisp-question-code
|
113
|
+
"\\|" relisp-answer-code
|
114
|
+
"\\|" relisp-error-code
|
115
|
+
"\\)"
|
116
|
+
"[[:space:]]*"))
|
117
|
+
|
118
|
+
(defun ruby-eval (ruby-code)
|
119
|
+
"Have ruby evaluate RUBY-CODE and return the result.
|
120
|
+
The result is an elisp object equivalent to the ruby result of
|
121
|
+
RUBY-CODE. Reads input from the minibuffer unless an argument is
|
122
|
+
given."
|
123
|
+
(interactive "sruby> ")
|
124
|
+
(let (message result)
|
125
|
+
(if (and relisp-emacs-master-p (not (relisp-slave-alive-p)))
|
126
|
+
(relisp-start-slave))
|
127
|
+
(relisp-log (concat "lisp?> " ruby-code))
|
128
|
+
(relisp-write-to-ruby (relisp-form-question ruby-code))
|
129
|
+
(setq message (relisp-read-from-ruby))
|
130
|
+
(while (string-match relisp-question-code message)
|
131
|
+
(relisp-answer-ruby message)
|
132
|
+
(setq message (relisp-read-from-ruby)))
|
133
|
+
(setq relisp-ruby-return (relisp-strip (car (split-string message relisp-answer-code))))
|
134
|
+
(relisp-log (concat "ruby=> " relisp-ruby-return "\n"))
|
135
|
+
(setq result (if (string-match (concat "\n?" relisp-error-code "[[:space:]]*") relisp-ruby-return)
|
136
|
+
(concat "RUBY ERROR: " (replace-match "" nil t relisp-ruby-return))
|
137
|
+
(eval (read (relisp-trim-trailing-whitespace relisp-ruby-return)))))
|
138
|
+
(if (interactive-p)
|
139
|
+
(message (prin1-to-string result)))
|
140
|
+
result))
|
141
|
+
|
142
|
+
(defun relisp-answer-ruby (question)
|
143
|
+
"Evaluate the QUESTION from ruby and send ruby the result."
|
144
|
+
(setq question (relisp-strip (car (split-string question relisp-question-code))))
|
145
|
+
(relisp-log (concat "ruby?> " question))
|
146
|
+
(setq question (read question))
|
147
|
+
(condition-case error-description
|
148
|
+
(progn
|
149
|
+
(set relisp-previous-result (eval question))
|
150
|
+
(relisp-log (concat "lisp=> " (prin1-to-string (type-of (eval relisp-previous-result)))))
|
151
|
+
(relisp-log (concat " ... " (prin1-to-string (eval relisp-previous-result))))
|
152
|
+
(relisp-write-to-ruby (prin1-to-string (type-of (eval relisp-previous-result))))
|
153
|
+
(relisp-write-to-ruby (relisp-form-answer (eval relisp-previous-result))))
|
154
|
+
(error (relisp-write-to-ruby
|
155
|
+
(relisp-form-error
|
156
|
+
(error-message-string error-description))))))
|
157
|
+
|
158
|
+
(defun relisp-form-question (code)
|
159
|
+
"Return a string that tells ruby to evaluate CODE."
|
160
|
+
(unless (stringp code)
|
161
|
+
(setq code (prin1-to-string code)))
|
162
|
+
(concat code "\n" relisp-question-code))
|
163
|
+
|
164
|
+
(defun relisp-form-answer (code)
|
165
|
+
"Return a string that tells ruby that CODE is the answer to its query."
|
166
|
+
(setq code (prin1-to-string code))
|
167
|
+
(concat code "\n" relisp-answer-code))
|
168
|
+
|
169
|
+
(defun relisp-form-error (code)
|
170
|
+
"Return a string that tells ruby that CODE is an error message."
|
171
|
+
(setq code (prin1-to-string code))
|
172
|
+
(concat code "\n" relisp-error-code))
|
173
|
+
|
174
|
+
(defun relisp-to-ruby (object)
|
175
|
+
"Return a string that, when evaluated in ruby, results in OBJECT."
|
176
|
+
(let ((var (ruby-eval "new_elisp_variable")))
|
177
|
+
(set var object)
|
178
|
+
(concat "elisp_eval('" (prin1-to-string var) "')")))
|
179
|
+
|
180
|
+
(defun relisp-start-slave nil
|
181
|
+
"Start a ruby slave process to do emacs's bidding.
|
182
|
+
If `relisp-ruby-slave-path' is bound, then that file is read and
|
183
|
+
the Relisp::RubySlave object must be started there. Otherwise
|
184
|
+
emacs starts a ruby process and starts a RubySlave on its own."
|
185
|
+
(interactive)
|
186
|
+
(setq relisp-emacs-master-p t)
|
187
|
+
(relisp-stop-slave)
|
188
|
+
(setq relisp-ruby-output "")
|
189
|
+
(if (and (boundp 'relisp-ruby-slave-path) (file-exists-p relisp-ruby-slave-path))
|
190
|
+
(setq relisp-slave-process (start-process relisp-slave-name nil "ruby" relisp-ruby-slave-path))
|
191
|
+
(setq relisp-slave-process (start-process relisp-slave-name nil
|
192
|
+
"ruby"
|
193
|
+
"-x"))
|
194
|
+
(process-send-string relisp-slave-name
|
195
|
+
(concat "#! ruby \n"
|
196
|
+
"$:.unshift File.join(File.dirname('" (symbol-file 'relisp-slave-name) "'), '../lib')\n"
|
197
|
+
"require 'rubygems'\n"
|
198
|
+
"require 'relisp'\n"
|
199
|
+
"Relisp::RubySlave.new.start\n"
|
200
|
+
"__END__\n")))
|
201
|
+
(set-process-filter relisp-slave-process 'relisp-slave-output-filter)
|
202
|
+
(relisp-write-to-ruby "")
|
203
|
+
(while (null (string-match "\n" relisp-ruby-output))
|
204
|
+
(accept-process-output))
|
205
|
+
(setq relisp-answer-code (relisp-strip relisp-ruby-output))
|
206
|
+
(setq relisp-ruby-output "")
|
207
|
+
(relisp-write-to-ruby "")
|
208
|
+
(while (null (string-match "\n" relisp-ruby-output))
|
209
|
+
(accept-process-output))
|
210
|
+
(setq relisp-question-code (relisp-strip relisp-ruby-output))
|
211
|
+
(setq relisp-ruby-output "")
|
212
|
+
(relisp-write-to-ruby "")
|
213
|
+
(while (null (string-match "\n" relisp-ruby-output))
|
214
|
+
(accept-process-output))
|
215
|
+
(setq relisp-error-code (relisp-strip relisp-ruby-output))
|
216
|
+
(setq relisp-ruby-output "")
|
217
|
+
(relisp-write-to-ruby "")
|
218
|
+
(while (null (string-match "\n" relisp-ruby-output))
|
219
|
+
(accept-process-output))
|
220
|
+
(setq relisp-previous-result (read (relisp-strip relisp-ruby-output)))
|
221
|
+
(setq relisp-ruby-output "")
|
222
|
+
relisp-slave-process)
|
223
|
+
|
224
|
+
(defun relisp-become-slave nil
|
225
|
+
"Convert the emacs process into a slave. Only called by ruby."
|
226
|
+
(setq relisp-emacs-master-p nil)
|
227
|
+
;; get constants
|
228
|
+
(message "SEND CONSTANTS")
|
229
|
+
(message "(prompt for answer code)")
|
230
|
+
(setq relisp-answer-code (read-from-minibuffer ""))
|
231
|
+
(message "(prompt for question code)")
|
232
|
+
(setq relisp-question-code (read-from-minibuffer ""))
|
233
|
+
(message "(prompt for error code)")
|
234
|
+
(setq relisp-error-code (read-from-minibuffer ""))
|
235
|
+
(message "(prompt for previous result variable)")
|
236
|
+
(setq relisp-previous-result (read (read-from-minibuffer "")))
|
237
|
+
(let (input input-line)
|
238
|
+
(while t ;; loop is only a CL function, I guess
|
239
|
+
(setq input "")
|
240
|
+
(setq input-line "")
|
241
|
+
(while (null (string-match relisp-question-code (relisp-strip input-line)))
|
242
|
+
(setq input-line (read-from-minibuffer ""))
|
243
|
+
(setq input (concat input input-line)))
|
244
|
+
(relisp-answer-ruby input))))
|
245
|
+
|
246
|
+
|
247
|
+
(defun relisp-slave-output-filter (process output-line)
|
248
|
+
"Listen to PROCESS and add each OUTPUT-LINE to `relisp-ruby-output'."
|
249
|
+
(setq relisp-ruby-output (concat relisp-ruby-output output-line)))
|
250
|
+
|
251
|
+
(defun relisp-stop-slave nil
|
252
|
+
"Kill the ruby slave process."
|
253
|
+
(if (boundp 'relisp-slave-process)
|
254
|
+
(delete-process relisp-slave-process)))
|
255
|
+
|
256
|
+
(defun relisp-slave-alive-p nil
|
257
|
+
"Return t if the ruby slave is alive and well."
|
258
|
+
(and (boundp 'relisp-slave-process)
|
259
|
+
(equal (process-status relisp-slave-process) 'run)
|
260
|
+
(boundp 'relisp-question-code)
|
261
|
+
(boundp 'relisp-answer-code)
|
262
|
+
(boundp 'relisp-error-code)))
|
263
|
+
|
264
|
+
(provide 'relisp)
|
data/src/relisp.elc
ADDED
Binary file
|
data/tasks/ann.rake
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'bones/smtp_tls'
|
4
|
+
rescue LoadError
|
5
|
+
require 'net/smtp'
|
6
|
+
end
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
namespace :ann do
|
10
|
+
|
11
|
+
# A prerequisites task that all other tasks depend upon
|
12
|
+
task :prereqs
|
13
|
+
|
14
|
+
file PROJ.ann.file do
|
15
|
+
ann = PROJ.ann
|
16
|
+
puts "Generating #{ann.file}"
|
17
|
+
File.open(ann.file,'w') do |fd|
|
18
|
+
fd.puts("#{PROJ.name} version #{PROJ.version}")
|
19
|
+
fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
|
20
|
+
fd.puts(" #{PROJ.url}") if PROJ.url.valid?
|
21
|
+
fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
|
22
|
+
fd.puts
|
23
|
+
fd.puts("== DESCRIPTION")
|
24
|
+
fd.puts
|
25
|
+
fd.puts(PROJ.description)
|
26
|
+
fd.puts
|
27
|
+
fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
|
28
|
+
fd.puts
|
29
|
+
ann.paragraphs.each do |p|
|
30
|
+
fd.puts "== #{p.upcase}"
|
31
|
+
fd.puts
|
32
|
+
fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
|
33
|
+
fd.puts
|
34
|
+
end
|
35
|
+
fd.puts ann.text if ann.text
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Create an announcement file"
|
40
|
+
task :announcement => ['ann:prereqs', PROJ.ann.file]
|
41
|
+
|
42
|
+
desc "Send an email announcement"
|
43
|
+
task :email => ['ann:prereqs', PROJ.ann.file] do
|
44
|
+
ann = PROJ.ann
|
45
|
+
from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
|
46
|
+
to = Array(ann.email[:to])
|
47
|
+
|
48
|
+
### build a mail header for RFC 822
|
49
|
+
rfc822msg = "From: #{from}\n"
|
50
|
+
rfc822msg << "To: #{to.join(',')}\n"
|
51
|
+
rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
|
52
|
+
rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
|
53
|
+
rfc822msg << "\n"
|
54
|
+
rfc822msg << "Date: #{Time.new.rfc822}\n"
|
55
|
+
rfc822msg << "Message-Id: "
|
56
|
+
rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
|
57
|
+
rfc822msg << File.read(ann.file)
|
58
|
+
|
59
|
+
params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
|
60
|
+
ann.email[key]
|
61
|
+
end
|
62
|
+
|
63
|
+
params[3] = PROJ.email if params[3].nil?
|
64
|
+
|
65
|
+
if params[4].nil?
|
66
|
+
STDOUT.write "Please enter your e-mail password (#{params[3]}): "
|
67
|
+
params[4] = STDIN.gets.chomp
|
68
|
+
end
|
69
|
+
|
70
|
+
### send email
|
71
|
+
Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
|
72
|
+
end
|
73
|
+
end # namespace :ann
|
74
|
+
|
75
|
+
desc 'Alias to ann:announcement'
|
76
|
+
task :ann => 'ann:announcement'
|
77
|
+
|
78
|
+
CLOBBER << PROJ.ann.file
|
79
|
+
|
80
|
+
# EOF
|
data/tasks/bones.rake
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
if HAVE_BONES
|
3
|
+
|
4
|
+
namespace :bones do
|
5
|
+
|
6
|
+
desc 'Show the PROJ open struct'
|
7
|
+
task :debug do |t|
|
8
|
+
atr = if t.application.top_level_tasks.length == 2
|
9
|
+
t.application.top_level_tasks.pop
|
10
|
+
end
|
11
|
+
|
12
|
+
if atr then Bones::Debug.show_attr(PROJ, atr)
|
13
|
+
else Bones::Debug.show PROJ end
|
14
|
+
end
|
15
|
+
|
16
|
+
end # namespace :bones
|
17
|
+
|
18
|
+
end # HAVE_BONES
|
19
|
+
|
20
|
+
# EOF
|
data/tasks/gem.rake
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
|
2
|
+
require 'find'
|
3
|
+
require 'rake/packagetask'
|
4
|
+
require 'rubygems/user_interaction'
|
5
|
+
require 'rubygems/builder'
|
6
|
+
|
7
|
+
module Bones
|
8
|
+
class GemPackageTask < Rake::PackageTask
|
9
|
+
# Ruby GEM spec containing the metadata for this package. The
|
10
|
+
# name, version and package_files are automatically determined
|
11
|
+
# from the GEM spec and don't need to be explicitly provided.
|
12
|
+
#
|
13
|
+
attr_accessor :gem_spec
|
14
|
+
|
15
|
+
# Tasks from the Bones gem directory
|
16
|
+
attr_reader :bones_files
|
17
|
+
|
18
|
+
# Create a GEM Package task library. Automatically define the gem
|
19
|
+
# if a block is given. If no block is supplied, then +define+
|
20
|
+
# needs to be called to define the task.
|
21
|
+
#
|
22
|
+
def initialize(gem_spec)
|
23
|
+
init(gem_spec)
|
24
|
+
yield self if block_given?
|
25
|
+
define if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Initialization tasks without the "yield self" or define
|
29
|
+
# operations.
|
30
|
+
#
|
31
|
+
def init(gem)
|
32
|
+
super(gem.name, gem.version)
|
33
|
+
@gem_spec = gem
|
34
|
+
@package_files += gem_spec.files if gem_spec.files
|
35
|
+
@bones_files = []
|
36
|
+
|
37
|
+
local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
|
38
|
+
if !test(?e, local_setup)
|
39
|
+
Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create the Rake tasks and actions specified by this
|
44
|
+
# GemPackageTask. (+define+ is automatically called if a block is
|
45
|
+
# given to +new+).
|
46
|
+
#
|
47
|
+
def define
|
48
|
+
super
|
49
|
+
task :prereqs
|
50
|
+
task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
|
51
|
+
file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
|
52
|
+
when_writing("Creating GEM") {
|
53
|
+
chdir(package_dir_path) do
|
54
|
+
Gem::Builder.new(gem_spec).build
|
55
|
+
verbose(true) {
|
56
|
+
mv gem_file, "../#{gem_file}"
|
57
|
+
}
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
file package_dir_path => bones_files do
|
63
|
+
mkdir_p package_dir rescue nil
|
64
|
+
|
65
|
+
gem_spec.files = (gem_spec.files +
|
66
|
+
bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
|
67
|
+
|
68
|
+
bones_files.each do |fn|
|
69
|
+
base_fn = File.join('tasks', File.basename(fn))
|
70
|
+
f = File.join(package_dir_path, base_fn)
|
71
|
+
fdir = File.dirname(f)
|
72
|
+
mkdir_p(fdir) if !File.exist?(fdir)
|
73
|
+
if File.directory?(fn)
|
74
|
+
mkdir_p(f)
|
75
|
+
else
|
76
|
+
raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
|
77
|
+
safe_ln(fn, f)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def gem_file
|
84
|
+
if @gem_spec.platform == Gem::Platform::RUBY
|
85
|
+
"#{package_name}.gem"
|
86
|
+
else
|
87
|
+
"#{package_name}-#{@gem_spec.platform}.gem"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end # class GemPackageTask
|
91
|
+
end # module Bones
|
92
|
+
|
93
|
+
namespace :gem do
|
94
|
+
|
95
|
+
PROJ.gem._spec = Gem::Specification.new do |s|
|
96
|
+
s.name = PROJ.name
|
97
|
+
s.version = PROJ.version
|
98
|
+
s.summary = PROJ.summary
|
99
|
+
s.authors = Array(PROJ.authors)
|
100
|
+
s.email = PROJ.email
|
101
|
+
s.homepage = Array(PROJ.url).first
|
102
|
+
s.rubyforge_project = PROJ.rubyforge.name
|
103
|
+
|
104
|
+
s.description = PROJ.description
|
105
|
+
|
106
|
+
PROJ.gem.dependencies.each do |dep|
|
107
|
+
s.add_dependency(*dep)
|
108
|
+
end
|
109
|
+
|
110
|
+
PROJ.gem.development_dependencies.each do |dep|
|
111
|
+
s.add_development_dependency(*dep)
|
112
|
+
end
|
113
|
+
|
114
|
+
s.files = PROJ.gem.files
|
115
|
+
s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
|
116
|
+
s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
|
117
|
+
|
118
|
+
s.bindir = 'bin'
|
119
|
+
dirs = Dir["{#{PROJ.libs.join(',')}}"]
|
120
|
+
s.require_paths = dirs unless dirs.empty?
|
121
|
+
|
122
|
+
incl = Regexp.new(PROJ.rdoc.include.join('|'))
|
123
|
+
excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
|
124
|
+
excl = Regexp.new(excl.join('|'))
|
125
|
+
rdoc_files = PROJ.gem.files.find_all do |fn|
|
126
|
+
case fn
|
127
|
+
when excl; false
|
128
|
+
when incl; true
|
129
|
+
else false end
|
130
|
+
end
|
131
|
+
s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
|
132
|
+
s.extra_rdoc_files = rdoc_files
|
133
|
+
s.has_rdoc = true
|
134
|
+
|
135
|
+
if test ?f, PROJ.test.file
|
136
|
+
s.test_file = PROJ.test.file
|
137
|
+
else
|
138
|
+
s.test_files = PROJ.test.files.to_a
|
139
|
+
end
|
140
|
+
|
141
|
+
# Do any extra stuff the user wants
|
142
|
+
PROJ.gem.extras.each do |msg, val|
|
143
|
+
case val
|
144
|
+
when Proc
|
145
|
+
val.call(s.send(msg))
|
146
|
+
else
|
147
|
+
s.send "#{msg}=", val
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end # Gem::Specification.new
|
151
|
+
|
152
|
+
Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
|
153
|
+
pkg.need_tar = PROJ.gem.need_tar
|
154
|
+
pkg.need_zip = PROJ.gem.need_zip
|
155
|
+
end
|
156
|
+
|
157
|
+
desc 'Show information about the gem'
|
158
|
+
task :debug => 'gem:prereqs' do
|
159
|
+
puts PROJ.gem._spec.to_ruby
|
160
|
+
end
|
161
|
+
|
162
|
+
desc 'Write the gemspec '
|
163
|
+
task :spec => 'gem:prereqs' do
|
164
|
+
File.open("#{PROJ.name}.gemspec", 'w') do |f|
|
165
|
+
f.write PROJ.gem._spec.to_ruby
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
desc 'Install the gem'
|
170
|
+
task :install => [:clobber, 'gem:package'] do
|
171
|
+
sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
|
172
|
+
|
173
|
+
# use this version of the command for rubygems > 1.0.0
|
174
|
+
#sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
|
175
|
+
end
|
176
|
+
|
177
|
+
desc 'Uninstall the gem'
|
178
|
+
task :uninstall do
|
179
|
+
installed_list = Gem.source_index.find_name(PROJ.name)
|
180
|
+
if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
|
181
|
+
sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
desc 'Reinstall the gem'
|
186
|
+
task :reinstall => [:uninstall, :install]
|
187
|
+
|
188
|
+
desc 'Cleanup the gem'
|
189
|
+
task :cleanup do
|
190
|
+
sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
|
191
|
+
end
|
192
|
+
end # namespace :gem
|
193
|
+
|
194
|
+
|
195
|
+
desc 'Alias to gem:package'
|
196
|
+
task :gem => 'gem:package'
|
197
|
+
|
198
|
+
task :clobber => 'gem:clobber_package'
|
199
|
+
remove_desc_for_task 'gem:clobber_package'
|
200
|
+
|
201
|
+
# EOF
|
data/tasks/git.rake
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
if HAVE_GIT
|
3
|
+
|
4
|
+
namespace :git do
|
5
|
+
|
6
|
+
# A prerequisites task that all other tasks depend upon
|
7
|
+
task :prereqs
|
8
|
+
|
9
|
+
desc 'Show tags from the Git repository'
|
10
|
+
task :show_tags => 'git:prereqs' do |t|
|
11
|
+
puts %x/git tag/
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Create a new tag in the Git repository'
|
15
|
+
task :create_tag => 'git:prereqs' do |t|
|
16
|
+
v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
|
17
|
+
abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
|
18
|
+
|
19
|
+
tag = "%s-%s" % [PROJ.name, PROJ.version]
|
20
|
+
msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
|
21
|
+
|
22
|
+
puts "Creating Git tag '#{tag}'"
|
23
|
+
unless system "git tag -a -m '#{msg}' #{tag}"
|
24
|
+
abort "Tag creation failed"
|
25
|
+
end
|
26
|
+
|
27
|
+
if %x/git remote/ =~ %r/^origin\s*$/
|
28
|
+
unless system "git push origin #{tag}"
|
29
|
+
abort "Could not push tag to remote Git repository"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end # namespace :git
|
35
|
+
|
36
|
+
task 'gem:release' => 'git:create_tag'
|
37
|
+
|
38
|
+
end # if HAVE_GIT
|
39
|
+
|
40
|
+
# EOF
|
data/tasks/manifest.rake
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
require 'find'
|
3
|
+
|
4
|
+
namespace :manifest do
|
5
|
+
|
6
|
+
desc 'Verify the manifest'
|
7
|
+
task :check do
|
8
|
+
fn = PROJ.manifest_file + '.tmp'
|
9
|
+
files = manifest_files
|
10
|
+
|
11
|
+
File.open(fn, 'w') {|fp| fp.puts files}
|
12
|
+
lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
|
13
|
+
if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
|
14
|
+
lines.map! do |line|
|
15
|
+
case line
|
16
|
+
when %r/^(-{3}|\+{3})/; nil
|
17
|
+
when %r/^@/; ANSICode.blue line
|
18
|
+
when %r/^\+/; ANSICode.green line
|
19
|
+
when %r/^\-/; ANSICode.red line
|
20
|
+
else line end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
puts lines.compact
|
24
|
+
rm fn rescue nil
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Create a new manifest'
|
28
|
+
task :create do
|
29
|
+
files = manifest_files
|
30
|
+
unless test(?f, PROJ.manifest_file)
|
31
|
+
files << PROJ.manifest_file
|
32
|
+
files.sort!
|
33
|
+
end
|
34
|
+
File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
|
35
|
+
end
|
36
|
+
|
37
|
+
task :assert do
|
38
|
+
files = manifest_files
|
39
|
+
manifest = File.read(PROJ.manifest_file).split($/)
|
40
|
+
raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
|
41
|
+
end
|
42
|
+
|
43
|
+
end # namespace :manifest
|
44
|
+
|
45
|
+
desc 'Alias to manifest:check'
|
46
|
+
task :manifest => 'manifest:check'
|
47
|
+
|
48
|
+
# EOF
|
data/tasks/notes.rake
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
if HAVE_BONES
|
3
|
+
|
4
|
+
desc "Enumerate all annotations"
|
5
|
+
task :notes do |t|
|
6
|
+
id = if t.application.top_level_tasks.length > 1
|
7
|
+
t.application.top_level_tasks.slice!(1..-1).join(' ')
|
8
|
+
end
|
9
|
+
Bones::AnnotationExtractor.enumerate(
|
10
|
+
PROJ, PROJ.notes.tags.join('|'), id, :tag => true)
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :notes do
|
14
|
+
PROJ.notes.tags.each do |tag|
|
15
|
+
desc "Enumerate all #{tag} annotations"
|
16
|
+
task tag.downcase.to_sym do |t|
|
17
|
+
id = if t.application.top_level_tasks.length > 1
|
18
|
+
t.application.top_level_tasks.slice!(1..-1).join(' ')
|
19
|
+
end
|
20
|
+
Bones::AnnotationExtractor.enumerate(PROJ, tag, id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end # if HAVE_BONES
|
26
|
+
|
27
|
+
# EOF
|