editors 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6c25ed541da528233569124bcc6d4eeeb89e397a
4
+ data.tar.gz: 48e7138e786182f55c17950a29e989991acf9938
5
+ SHA512:
6
+ metadata.gz: 042a38b380168dbb676b80586200194da71465fef33bcb7ef2ca4dc32722e67a62d74a292c45e932ea9dcb01b2fbad4aca0d851a1927777173fdd7b8a0341d9a
7
+ data.tar.gz: 2c83e8e9d95a81e7c4f12d55d289522c416fee353b7bcfd709a04655afadc6fb4cebe0e8ecb0ba843678ef58301ff9d40d45a3bdc934308ce60ceee0356d4745
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ vendor
16
+ *.gem
data/.hound.yml ADDED
@@ -0,0 +1,5 @@
1
+ LineLength:
2
+ Enabled: false
3
+ Style/AlignHash:
4
+ EnforcedHashRocketStyle: separator
5
+ EnforcedColonStyle: separator
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ LineLength:
2
+ Enabled: false
3
+ Style/AlignHash:
4
+ EnforcedHashRocketStyle: separator
5
+ EnforcedColonStyle: separator
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in editors.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Jeff Sandberg
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,72 @@
1
+ # Editors
2
+
3
+ A little utility gem that is designed to collect user input through the user's text editor.
4
+
5
+ This is mostly an extraction from the excellent [pry](http://github.com/pry/pry), but with more generalized functionality
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'editors'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install editors
22
+
23
+ ## Usage
24
+
25
+ **[docs](http://rubydoc.info/github/paradox460/editors/master/)**
26
+
27
+ There are 2 main ways of using `Editors`. To open files, and to collect input.
28
+
29
+ ### Files
30
+ [`Editors.file`](http://rubydoc.info/github/paradox460/editors/master/Editor.file)
31
+ ```ruby
32
+ Editor.file('/path/to/your/file.rb')
33
+ ```
34
+
35
+ ### Collecting input
36
+ This is what Editor was initially written for
37
+
38
+ [`Editors.temp`](http://rubydoc.info/github/paradox460/editors/master/Editor.temp)
39
+ ```ruby
40
+ Editor.temp('String to put into the tempfile before the user edits it')
41
+ ```
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it ( https://github.com/[my-github-username]/editors/fork )
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create a new Pull Request
50
+
51
+ ## License
52
+ ```
53
+ Copyright (c) 2014 Jeff Sandberg
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining a copy
56
+ of this software and associated documentation files (the "Software"), to deal
57
+ in the Software without restriction, including without limitation the rights
58
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
59
+ copies of the Software, and to permit persons to whom the Software is
60
+ furnished to do so, subject to the following conditions:
61
+
62
+ The above copyright notice and this permission notice shall be included in all
63
+ copies or substantial portions of the Software.
64
+
65
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
67
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
71
+ SOFTWARE.
72
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/editors.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ # rubocop:disable all
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'editors/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "editors"
9
+ spec.version = Editors::VERSION
10
+ spec.authors = ["Jeff Sandberg"]
11
+ spec.email = ["paradox460@gmail.com"]
12
+ spec.summary = %q{A library for invoking the users text editor.}
13
+ spec.description = %q{Library for opening text editors and getting their content as a string. Useful for command line scripts. Somewhat of an extraction from the excellent pry gem.}
14
+ spec.homepage = "https://github.com/paradox460/editor"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
data/lib/editor.rb ADDED
@@ -0,0 +1,167 @@
1
+ require 'english'
2
+ require 'editors/version'
3
+ require 'editors/helpers/editor_syntax'
4
+ require 'editors/helpers/platform_detection'
5
+
6
+ # Editor class. Lets you edit both real and temporary files, and returns their values after editing.
7
+ #
8
+ # @author Jeff Sandberg
9
+ #
10
+ class Editors
11
+ include Editors::Helpers::PlatformDetection
12
+ include Editors::Helpers::EditorSyntax
13
+ attr_reader :content
14
+
15
+ # Initialize a new editor, with options. You should probably use Editor.edit or Editor.new instead of these
16
+ # You must pass a file OR temp string, but NOT both
17
+ #
18
+ # @param options [Hash]
19
+ # @option file [String] options (nil) A file path to edit
20
+ # @option temp [String] options (nil) The content of the tempfile, prior to editing
21
+ # @option line [String] options (1) The line of the file to place the cursor at
22
+ # @option blocking [Boolean] options (true) Pass the editor a blocking flag
23
+ # @return [Editor] Editor object, with #content set to the return value from the file
24
+ def initialize(options = {})
25
+ opts = { file: nil, temp: nil, line: 1, blocking: true }.merge(options)
26
+ if !opts_is_valid?opts
27
+ fail ArgumentError, 'define file OR temp'
28
+ elsif opts[:file]
29
+ edit_file(opts)
30
+ elsif opts[:temp]
31
+ edit_temp(opts)
32
+ end
33
+ end
34
+
35
+ class << self
36
+ # Edit a file from the filesystem, and return its value
37
+ # @param file [String] A file path to edit
38
+ # @param line [Fixnum] The line of the file to place the cursor at
39
+ # @param blocking [Boolean] Pass the editor a blocking flag
40
+ #
41
+ # @return [String] The value of the file AFTER it was edited
42
+ def file(file, line = 1, blocking = true)
43
+ new(file: file, line: line, blocking: blocking).content
44
+ end
45
+
46
+ # Edits a temporary file, and return its value
47
+ # @param initial_content [String] The content of the tempfile, prior to editing
48
+ # @param line [Fixnum] Tempfile line to place cursor at
49
+ #
50
+ # @return [String] The value of the tempfile AFTER it was edited
51
+ def temp(initial_content, line = 1)
52
+ new(temp: initial_content, line: line, blocking: true).content
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # Checks if an options hash contains both file and temp values
59
+ # @param opts [Hash] Options hash
60
+ #
61
+ # @return [Boolean]
62
+ def opts_is_valid?(opts = {})
63
+ !(opts[:file].nil? && opts[:temp].nil?) || (opts[:file] && opts[:temp])
64
+ end
65
+
66
+ # Open the file in the users editor of choice
67
+ # @param opts [Hash] Options hash
68
+ # @option file [String] options (nil) A file path to edit
69
+ # @option line [String] options (1) The line of the file to place the cursor at
70
+ # @option blocking [Boolean] options (true) Pass the editor a blocking flag
71
+ #
72
+ # @return [String] The value of the tempfile AFTER it was edited
73
+ def edit_file(opts = {})
74
+ File.open(opts[:file]) do |f|
75
+ invoke_editor(f.path, opts[:line], opts[:blocking])
76
+ @content = File.read(f.path)
77
+ end
78
+ end
79
+
80
+ # Put a string in a temp file and present it to the user for editing
81
+ # @param opts [Hash] Options hash
82
+ # @option temp [String] options (nil) The content of the tempfile, prior to editing
83
+ # @option line [String] options (1) The line of the file to place the cursor at
84
+ #
85
+ # @return [String] The value of the tempfile AFTER it was edited
86
+ def edit_temp(opts = {})
87
+ temp_file do |f|
88
+ f.puts(opts[:temp])
89
+ f.flush
90
+ f.close(false)
91
+ invoke_editor(f.path, opts[:line], true)
92
+ @content = File.read(f.path)
93
+ end
94
+ end
95
+
96
+ # Open the users default editor with the params specified
97
+ # @param file [String] File path
98
+ # @param line [Fixnum] Line number to place cursor at
99
+ # @param blocking = true [Boolean] If the editor should be blocking
100
+ def invoke_editor(file, line = 1, blocking = true)
101
+ fail 'Please export $VISUAL or $EDITOR' unless default_editor
102
+
103
+ editor_invocation = build_editor_invocation_string(file, line, blocking)
104
+ return nil unless editor_invocation
105
+
106
+ if jruby?
107
+ open_editor_on_jruby(editor_invocation)
108
+ else
109
+ open_editor(editor_invocation)
110
+ end
111
+ end
112
+
113
+ # Create and yield a tempfile
114
+ # @param ext [String] File extension for the file to user
115
+ #
116
+ # @yieldparam [File] The tempfile object
117
+ def temp_file(ext = '.rb')
118
+ file = Tempfile.new(['editors', ext])
119
+ yield file
120
+ ensure
121
+ file.close(true) if file
122
+ end
123
+
124
+ # Builds the string that is used to call the editor
125
+ # @param file [String] File path
126
+ # @param line [Fixnum] Line number
127
+ # @param blocking [Boolean]
128
+ #
129
+ # @return [String] Editor invocation string
130
+ def build_editor_invocation_string(file, line, blocking)
131
+ sanitized_file = windows? ? file.gsub(/\//, '\\') : Shellwords.escape(file)
132
+ "#{default_editor} #{blocking_flag_for_editor(blocking)} #{start_line_syntax_for_editor(sanitized_file, line)}"
133
+ end
134
+
135
+ # Open the editor
136
+ # @param editor_invocation [String] Value from #build_editor_invocation_string
137
+ def open_editor(editor_invocation)
138
+ system(*Shellwords.split(editor_invocation)) || fail("`#{editor_invocation}` gave exit status: #{$CHILD_STATUS.exitstatus}")
139
+ end
140
+
141
+ # jRuby doesn't like open_editor, so we have to muck about with this
142
+ # @param editor_invocation [String] Value from #build_editor_invocation_string
143
+ def open_editor_on_jruby(editor_invocation)
144
+ require 'spoon'
145
+ pid = Spoon.spawnp(*Shellwords.split(editor_invocation))
146
+ Process.waitpid(pid)
147
+ rescue FFI::NotFoundError
148
+ system(editor_invocation)
149
+ end
150
+
151
+ # Get the user's configured visual or editor ENV
152
+ #
153
+ # @return [String] The editor command
154
+ def default_editor
155
+ # Visual = Advanced editor
156
+ return ENV['VISUAL'] if ENV['VISUAL'] && !ENV['VISUAL'].empty?
157
+ # Editor = basic editor
158
+ return ENV['EDITOR'] if ENV['EDITOR'] && !ENV['EDITOR'].empty?
159
+ if windows?
160
+ 'notepad'
161
+ else
162
+ %w(editor nano vi).find do |editor|
163
+ system("which #{editor} > /dev/null 2>&1")
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,61 @@
1
+ class Editors
2
+ module Helpers
3
+ # Helpers for generating editor invocation commands
4
+ #
5
+ # @author Jeff Sandberg
6
+ module EditorSyntax
7
+ def editor_name
8
+ File.basename(default_editor).split(' ').first
9
+ end
10
+ # The blocking flag for this particular editor.
11
+ #
12
+ # @param blocking [Boolean] If false, returns nothing
13
+ #
14
+ # @return [String, Nil]
15
+ def blocking_flag_for_editor(blocking)
16
+ case editor_name
17
+ when /^emacsclient/
18
+ '--no-wait'
19
+ when /^[gm]vim/
20
+ '--nofork'
21
+ when /^jedit/
22
+ '-wait'
23
+ when /^mate/, /^subl/, /^redcar/
24
+ '-w'
25
+ end if blocking
26
+ end
27
+
28
+ # The starting line syntax for the user's editor
29
+ # @param file_name [String] File name/path
30
+ # @param line_number [Fixnum]
31
+ #
32
+ # @return [String]
33
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
34
+ def start_line_syntax_for_editor(file_name, line_number)
35
+ return file_name if line_number <= 1
36
+
37
+ case editor_name
38
+ when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
39
+ "+#{line_number} #{file_name}"
40
+ when /^mate/, /^geany/
41
+ "-l #{line_number} #{file_name}"
42
+ when /^subl/
43
+ "#{file_name}:#{line_number}"
44
+ when /^uedit32/
45
+ "#{file_name}/#{line_number}"
46
+ when /^jedit/
47
+ "#{file_name} +line:#{line_number}"
48
+ when /^redcar/
49
+ "-l#{line_number} #{file_name}"
50
+ else
51
+ if windows?
52
+ "#{file_name}"
53
+ else
54
+ "+#{line_number} #{file_name}"
55
+ end
56
+ end
57
+ end
58
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,52 @@
1
+ class Editors
2
+ module Helpers
3
+ # Utilities for detecting which platform and which version of ruby the user is running
4
+ #
5
+ # @author Jeff Sandberg
6
+ module PlatformDetection
7
+ def windows?
8
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
9
+ end
10
+
11
+ # Determines if we can use ANSI on windows
12
+ #
13
+ # @return [Boolean]
14
+ def windows_ansi?
15
+ defined?(Win32::Console) || ENV['ANSICON'] || (windows? && mri_2?)
16
+ end
17
+
18
+ def jruby?
19
+ RbConfig::CONFIG['ruby_install_name'] == 'jruby'
20
+ end
21
+
22
+ def jruby_19?
23
+ jruby? && RbConfig::CONFIG['ruby_version'] == '1.9'
24
+ end
25
+
26
+ def rbx?
27
+ RbConfig::CONFIG['ruby_install_name'] == 'rbx'
28
+ end
29
+
30
+ def mri?
31
+ RbConfig::CONFIG['ruby_install_name'] == 'ruby'
32
+ end
33
+ # rubocop:disable Style/DoubleNegation
34
+ def mri_19?
35
+ !!(mri? && RUBY_VERSION =~ /^1\.9/)
36
+ end
37
+
38
+ def mri_2?
39
+ !!(mri? && RUBY_VERSION =~ /^2/)
40
+ end
41
+
42
+ def mri_20?
43
+ !!(mri? && RUBY_VERSION =~ /^2\.0/)
44
+ end
45
+
46
+ def mri_21?
47
+ !!(mri? && RUBY_VERSION =~ /^2\.1/)
48
+ end
49
+ # rubocop:enable Style/DoubleNegation
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,6 @@
1
+ class Editors
2
+ MAJOR = 0
3
+ MINOR = 0
4
+ PATCH = 1
5
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
6
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: editors
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Sandberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Library for opening text editors and getting their content as a string.
42
+ Useful for command line scripts. Somewhat of an extraction from the excellent pry
43
+ gem.
44
+ email:
45
+ - paradox460@gmail.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".gitignore"
51
+ - ".hound.yml"
52
+ - ".rubocop.yml"
53
+ - ".travis.yml"
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - editors.gemspec
59
+ - lib/editor.rb
60
+ - lib/editors/helpers/editor_syntax.rb
61
+ - lib/editors/helpers/platform_detection.rb
62
+ - lib/editors/version.rb
63
+ homepage: https://github.com/paradox460/editor
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.2.2
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: A library for invoking the users text editor.
87
+ test_files: []
88
+ has_rdoc: