editorkicker 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +6 -0
- data/MIT-LICENSE +20 -0
- data/README.txt +133 -0
- data/editorkicker.gemspec +46 -0
- data/lib/editor_kicker.rb +104 -0
- data/plugin/rails/editorkicker/CHANGES.txt +6 -0
- data/plugin/rails/editorkicker/MIT-LICENSE +20 -0
- data/plugin/rails/editorkicker/README.txt +67 -0
- data/plugin/rails/editorkicker/init.rb +64 -0
- data/plugin/rails/editorkicker/lib/editor_kicker.rb +104 -0
- data/setup.rb +1585 -0
- metadata +66 -0
data/CHANGES.txt
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2008 kuwata-lab.com all rights reserved.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.txt
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
= README.txt for EditorKicker
|
2
|
+
|
3
|
+
Release: 0.1.0
|
4
|
+
|
5
|
+
http://editorkicker.rubyforge.org/
|
6
|
+
http://rubyforge.org/projects/editorkicker/
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
== About
|
11
|
+
|
12
|
+
EditorKicker is a pretty utility to invoke your favorite editor
|
13
|
+
and open errored file when CGI script or Rails program cause error.
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
== Install
|
18
|
+
|
19
|
+
(for Ruby on Rails)
|
20
|
+
|
21
|
+
$ ruby script/plugin install http://github.com/kwatch/editorkicker.git/ruby/plugin/rails/editorkicker
|
22
|
+
|
23
|
+
(for CGI/mod_ruby)
|
24
|
+
|
25
|
+
You must install CGI-Exception library, too.
|
26
|
+
|
27
|
+
## install EditorKicker
|
28
|
+
$ sudo gem install editorkicker
|
29
|
+
## or
|
30
|
+
$ cd /tmp
|
31
|
+
$ wget http://rubyforge.org/projects/editorkicker/.../editorkicker-XXX.tar.gz
|
32
|
+
$ tar xzf editorkicker-XXX.tar.gz
|
33
|
+
$ cd editorkicker-XXX/
|
34
|
+
$ sudo ruby install.rb
|
35
|
+
|
36
|
+
## install cgi-exception
|
37
|
+
$ sudo gem install cgi-exception
|
38
|
+
## or
|
39
|
+
$ cd /tmp
|
40
|
+
$ wget http://rubyforge.org/projects/cgi-exception
|
41
|
+
$ tar xzf cgi-exception-XXX.tar.gz
|
42
|
+
$ cd cgi-exception-XXX/
|
43
|
+
$ sudo ruby install.rb
|
44
|
+
|
45
|
+
It is not recommended to install by RubyGems, because 'require rubygems'
|
46
|
+
is an heavy-weight operation for CGI.
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
== Setup
|
51
|
+
|
52
|
+
ATTENTION! Don't forget to call 'M-x server-start' if you're Emacs user.
|
53
|
+
|
54
|
+
(for Ruby on Rails)
|
55
|
+
|
56
|
+
$ export EDITOR_KICKER="mate -n %s '%s'" (for TextMate)
|
57
|
+
$ export EDITOR_KICKER="emacsclient -n +%s '%s'" (for Emacs)
|
58
|
+
$ ruby script/server # development mode
|
59
|
+
|
60
|
+
Setting of $EDITOR_KICKER is optional. If $EDITOR_KICKER is not set,
|
61
|
+
EditorKicker will detect TextMate or Emacs automatically.
|
62
|
+
|
63
|
+
(for CGI/mod_ruby)
|
64
|
+
|
65
|
+
#!/usr/bin/env ruby
|
66
|
+
require 'cgi'
|
67
|
+
require 'cgi_exception'
|
68
|
+
|
69
|
+
### load and set up editor-kicker only when running in local machine
|
70
|
+
if ENV['SERVER_NAME'] == 'localhost'
|
71
|
+
require 'editor_kicker'
|
72
|
+
## for TextMate
|
73
|
+
mate = '/Applications/TextMate.app/Contents/Resources/mate'
|
74
|
+
ENV['EDITOR_KICKER'] = "#{mate} -l %s '%s'"
|
75
|
+
## for Emacs
|
76
|
+
emacsclient = '/Applications/Emacs.app/Contents/MacOS/bin/emacsclient'
|
77
|
+
ENV['EDITOR_KICKER'] = "#{emacsclient} -n -s /tmp/emacs501/server +%s '%s'"
|
78
|
+
end
|
79
|
+
|
80
|
+
cgi = CGI.new
|
81
|
+
print cgi.header
|
82
|
+
print "<h1>Hello</h1>"
|
83
|
+
...
|
84
|
+
|
85
|
+
If you're Emacs user, you have to change owner of socket file
|
86
|
+
(ex. '/tmp/emacsXXX/server') to Apache's process user.
|
87
|
+
|
88
|
+
### assume that CGI script is executed by 'daemon' user.
|
89
|
+
### ('/tmp/emacs501/server' will be created by M-x server-strart)
|
90
|
+
$ sudo chown -R daemon /tmp/emacs501/server
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
== Trouble shooting
|
95
|
+
|
96
|
+
|
97
|
+
=== (Emacs) can't find socket
|
98
|
+
|
99
|
+
Error:
|
100
|
+
|
101
|
+
emacsclient: can't find socket; have you started the server?
|
102
|
+
To start the server in Emacs, type "M-x server-start".
|
103
|
+
|
104
|
+
Solution:
|
105
|
+
|
106
|
+
Type 'M-x server start' in your Emacs.
|
107
|
+
|
108
|
+
In addition if you are CGI user, set $EDITOR_KICKER environment variable
|
109
|
+
to "emacsclient -n -s /tmp/emacs501/server +%s '%s'" in your CGI script
|
110
|
+
to specify socket file by '-s' option.
|
111
|
+
(Notice that '-s' option of emacsclient is available from Emacs 22.)
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
== Todo
|
116
|
+
|
117
|
+
* Merb support
|
118
|
+
* Mack support
|
119
|
+
* Ramaze support
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
== Author
|
124
|
+
|
125
|
+
makoto kuwata <kwa(at)kuwata-lab.com>
|
126
|
+
|
127
|
+
Copyright 2008 kuwata-lab.com all rights reserved.
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
== License
|
132
|
+
|
133
|
+
MIT License
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 0.1.0 $
|
5
|
+
### Copyright 2008 kuwata-lab.com all rights reserved.
|
6
|
+
###
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
|
10
|
+
spec = Gem::Specification.new do |s|
|
11
|
+
## package information
|
12
|
+
s.name = "editorkicker"
|
13
|
+
s.author = "makoto kuwata"
|
14
|
+
s.email = "kwa(at)kuwata-lab.com"
|
15
|
+
s.rubyforge_project = 'editorkicker'
|
16
|
+
s.version = "0.1.0"
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.homepage = "http://editorkicker.rubyforge.org/"
|
19
|
+
s.summary = "a pretty tool to invoke your favorite editor when error raised"
|
20
|
+
s.description = <<-'END'
|
21
|
+
EditorKicker is a pretty tool to invoke your favorite editor and open
|
22
|
+
errored file automatically when error raised in your script.
|
23
|
+
END
|
24
|
+
|
25
|
+
## files
|
26
|
+
files = []
|
27
|
+
files += Dir.glob('lib/*')
|
28
|
+
files += %W[README.txt CHANGES.txt MIT-LICENSE setup.rb #{s.name}.gemspec]
|
29
|
+
files += Dir.glob('plugin/**/*')
|
30
|
+
#files += Dir.glob('doc-api/**/*')
|
31
|
+
s.files = files
|
32
|
+
end
|
33
|
+
|
34
|
+
# Quick fix for Ruby 1.8.3 / YAML bug (thanks to Ross Bamford)
|
35
|
+
if (RUBY_VERSION == '1.8.3')
|
36
|
+
def spec.to_yaml
|
37
|
+
out = super
|
38
|
+
out = '--- ' + out unless out =~ /^---/
|
39
|
+
out
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if $0 == __FILE__
|
44
|
+
Gem::manage_gems
|
45
|
+
Gem::Builder.new(spec).build
|
46
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
##
|
2
|
+
## $Rev$
|
3
|
+
## $Release: 0.1.0 $
|
4
|
+
## Copyright 2008 kuwata-lab.com all rights reserved.
|
5
|
+
##
|
6
|
+
|
7
|
+
##
|
8
|
+
## Invoke your favorite editor and Open errored file by it.
|
9
|
+
##
|
10
|
+
## Don't forget to do `M-x server-start' if you use Emacs.
|
11
|
+
##
|
12
|
+
module EditorKicker
|
13
|
+
|
14
|
+
def self.handle_exception(ex)
|
15
|
+
self.handler.handle(ex)
|
16
|
+
end
|
17
|
+
|
18
|
+
class <<self
|
19
|
+
alias handle handle_exception
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.handler
|
23
|
+
@@handler
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.handler=(handler)
|
27
|
+
@@handler = handler
|
28
|
+
end
|
29
|
+
|
30
|
+
class ExceptionHandler
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@kicker = self # you can set Proc object to @kicker
|
34
|
+
@writable_check = false
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :command, :kicker, :writable_check
|
38
|
+
|
39
|
+
## detect error location from error and open related file
|
40
|
+
def handle(ex)
|
41
|
+
filepath, linenum = detect_location(ex)
|
42
|
+
kick(filepath, linenum) if filepath && linenum
|
43
|
+
end
|
44
|
+
|
45
|
+
## get filename and linenum from error
|
46
|
+
def detect_location(ex, backtrace=nil)
|
47
|
+
filepath = linenum = nil
|
48
|
+
backtrace ||= ex.backtrace
|
49
|
+
if backtrace && !backtrace.empty?
|
50
|
+
tuple = nil
|
51
|
+
if backtrace.find {|str| tuple = get_location(str) }
|
52
|
+
filepath, linenum = tuple
|
53
|
+
end
|
54
|
+
#elsif ex.is_a?(SyntaxEx)
|
55
|
+
# if ex.to_s =~ /^(.+):(\d+): syntax error,/
|
56
|
+
# filepath, linenum = $1, $2.to_i
|
57
|
+
# end
|
58
|
+
elsif ex.to_s =~ /\A(.+):(\d+): / # for SyntaxError
|
59
|
+
filepath, linenum = $1, $2.to_i
|
60
|
+
end
|
61
|
+
return filepath, linenum
|
62
|
+
end
|
63
|
+
|
64
|
+
## get filepath and linenum from string
|
65
|
+
def get_location(str)
|
66
|
+
return nil if str !~ /^(.+):(\d+)(:in `.+'|$)/
|
67
|
+
return nil if @writable_check && !File.writable?($1)
|
68
|
+
return [$1, $2.to_i]
|
69
|
+
end
|
70
|
+
|
71
|
+
## detect command to invoke editor
|
72
|
+
def detect_command
|
73
|
+
command = ENV['EDITOR_KICKER']
|
74
|
+
return command if command
|
75
|
+
bin = '/Applications/TextMate.app/Contents/Resources/mate'
|
76
|
+
return "#{bin} -l %s '%s'" if test(?f, bin)
|
77
|
+
return "emacsclient -n +%s '%s'"
|
78
|
+
end
|
79
|
+
|
80
|
+
## open file with editor
|
81
|
+
def kick(filepath, linenum)
|
82
|
+
if File.exists?(filepath)
|
83
|
+
@kicker.call(filepath, linenum)
|
84
|
+
else
|
85
|
+
log("#{filepath}: not found.")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
## default activity of kick()
|
90
|
+
def call(filepath, linenum) # should separate to a class?
|
91
|
+
command = (@command || detect_command()) % [linenum, filepath] # or [filepath, linenum]
|
92
|
+
log(command)
|
93
|
+
`#{command.untaint}`
|
94
|
+
end
|
95
|
+
|
96
|
+
def log(message)
|
97
|
+
$stderr.puts "** [EditorKicker] #{message}"
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
self.handler = ExceptionHandler.new
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2008 kuwata-lab.com all rights reserved.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,67 @@
|
|
1
|
+
=====================================
|
2
|
+
EditorKicker plugin for Ruby on Rails
|
3
|
+
=====================================
|
4
|
+
|
5
|
+
Release: 0.1.0
|
6
|
+
|
7
|
+
|
8
|
+
About
|
9
|
+
-----
|
10
|
+
|
11
|
+
EditorKicker is a pretty tool to invoke your favorite editor and
|
12
|
+
open errored file automatically when an exception raised on your script.
|
13
|
+
This is a plug-in of EditorKicker for Ruby on Rails.
|
14
|
+
|
15
|
+
Notice that this plug-in works only under development mode.
|
16
|
+
So it is no problem to commit this plug-in files into your app repository.
|
17
|
+
|
18
|
+
|
19
|
+
Target
|
20
|
+
------
|
21
|
+
|
22
|
+
* Rails version
|
23
|
+
- 2.1.X
|
24
|
+
- 2.0.X
|
25
|
+
- 1.2.X (I hope)
|
26
|
+
|
27
|
+
* Supported text editor by default
|
28
|
+
- TextMate
|
29
|
+
- Emacs
|
30
|
+
|
31
|
+
|
32
|
+
Install
|
33
|
+
-------
|
34
|
+
|
35
|
+
$ ruby script/plugin install http://github.com/kwatch/editorkicker.git/ruby/plugin/rails/editorkicker
|
36
|
+
|
37
|
+
|
38
|
+
Usage
|
39
|
+
-----
|
40
|
+
|
41
|
+
1. Intall EditorKicker plugin into your Rails application.
|
42
|
+
2. (optional) Set environtment variable $EDITOR_KICKER with command string to
|
43
|
+
invoke text editor (default "mate -l %s '%s'" or "emacsclient -n +%s '%s').
|
44
|
+
3. Restart Rails server in development mode.
|
45
|
+
4. Do 'M-x server-start' if you want to use Emacs. (*** IMPORTANT! ***)
|
46
|
+
|
47
|
+
|
48
|
+
Setup
|
49
|
+
-----
|
50
|
+
|
51
|
+
Environment variable $EDITOR_KICKER represents command string to invoke your
|
52
|
+
favorite editor with filename and linenum.
|
53
|
+
Default is "mate -l %s '%s'" or "emacsclient -n +%s '%s'".
|
54
|
+
|
55
|
+
|
56
|
+
Author
|
57
|
+
------
|
58
|
+
|
59
|
+
makoto kuwata <kwa(at)kuwata-lab.com>
|
60
|
+
|
61
|
+
Copyright 2008 kuwata-lab.com all rights reserved.
|
62
|
+
|
63
|
+
|
64
|
+
License
|
65
|
+
-------
|
66
|
+
|
67
|
+
MIT License
|
@@ -0,0 +1,64 @@
|
|
1
|
+
##
|
2
|
+
## $Rev$
|
3
|
+
## $Release: 0.1.0 $
|
4
|
+
## Copyright 2008 kuwata-lab.com all rights reserved.
|
5
|
+
##
|
6
|
+
|
7
|
+
##
|
8
|
+
## Notice that this plugin is loaded only when in development mode.
|
9
|
+
## So you can commit this plugin into your Rails app repository.
|
10
|
+
##
|
11
|
+
|
12
|
+
if defined?(RAILS_ENV) && RAILS_ENV == 'development'
|
13
|
+
|
14
|
+
require 'editor_kicker'
|
15
|
+
|
16
|
+
module ::EditorKicker
|
17
|
+
|
18
|
+
class RailsExceptionHandler < ExceptionHandler
|
19
|
+
|
20
|
+
def initialize(*args)
|
21
|
+
super
|
22
|
+
self.writable_check = true
|
23
|
+
end
|
24
|
+
|
25
|
+
## detect filepath and linenum
|
26
|
+
def detect_location(ex, backtrace=nil)
|
27
|
+
if ex.is_a?(ActionView::TemplateError)
|
28
|
+
# assert ex.respond_to?(:file_name)
|
29
|
+
# assert ex.respond_to?(:line_number)
|
30
|
+
filepath, linenum = ex.file_name, ex.line_number
|
31
|
+
if filepath && linenum
|
32
|
+
filepath = "app/views/#{filepath}" unless filepath[0] == ?/ || filepath =~ /\Aapp\/views\//
|
33
|
+
return filepath, linenum
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# assert ex.respond_to?(:application_backtrace)
|
37
|
+
return super(ex, ex.application_backtrace)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
self.handler = RailsExceptionHandler.new
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
module ::ActionController #:nodoc:
|
48
|
+
module Rescue #:nodoc:
|
49
|
+
protected
|
50
|
+
|
51
|
+
alias _rescue_action_locally_orig rescue_action_locally #:nodoc:
|
52
|
+
|
53
|
+
def rescue_action_locally(ex) # :nodoc:
|
54
|
+
ret = _rescue_action_locally_orig(ex) # call original
|
55
|
+
::EditorKicker.handle_exception(ex)
|
56
|
+
ret
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
::ActionController::Base.new.logger.info("** [EditorKicker] loaded.")
|
63
|
+
|
64
|
+
end
|