ruby-edit 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.rubocop.yml +15 -0
- data/.simplecov +6 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +141 -0
- data/LICENSE.txt +20 -0
- data/README.md +72 -0
- data/Rakefile +9 -0
- data/bin/console +12 -0
- data/bin/setup +8 -0
- data/configuration.yml +2 -0
- data/exe/ruby-edit +19 -0
- data/lib/ruby_edit.rb +15 -0
- data/lib/ruby_edit/apply_prompt.rb +12 -0
- data/lib/ruby_edit/cli.rb +72 -0
- data/lib/ruby_edit/command.rb +122 -0
- data/lib/ruby_edit/commands/.gitkeep +1 -0
- data/lib/ruby_edit/commands/configure.rb +30 -0
- data/lib/ruby_edit/commands/edit.rb +58 -0
- data/lib/ruby_edit/commands/grep.rb +20 -0
- data/lib/ruby_edit/configuration.rb +36 -0
- data/lib/ruby_edit/editor.rb +16 -0
- data/lib/ruby_edit/grep.rb +34 -0
- data/lib/ruby_edit/source_file.rb +16 -0
- data/lib/ruby_edit/templates/.gitkeep +1 -0
- data/lib/ruby_edit/version.rb +6 -0
- data/lib/ruby_edit/writer.rb +55 -0
- data/ruby-edit.gemspec +53 -0
- metadata +412 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'thor'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
# Handle the application command line parsing
|
|
7
|
+
# and the dispatch to various command objects
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
class CLI < Thor
|
|
11
|
+
# Error raised by this runner
|
|
12
|
+
Error = Class.new(StandardError)
|
|
13
|
+
|
|
14
|
+
desc 'version', 'ruby-edit version'
|
|
15
|
+
def version
|
|
16
|
+
require_relative 'version'
|
|
17
|
+
puts "v#{RubyEdit::VERSION}"
|
|
18
|
+
end
|
|
19
|
+
map %w[--version -v] => :version
|
|
20
|
+
|
|
21
|
+
desc 'grep', 'search for an expression in your directory'
|
|
22
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
|
23
|
+
method_option :expression, aliases: %w[-e --expression], type: :string,
|
|
24
|
+
desc: 'the grep expression'
|
|
25
|
+
method_option :path, aliases: %w[-p --path], type: :string, desc: 'the path you want to search'
|
|
26
|
+
def grep(*)
|
|
27
|
+
if options[:help]
|
|
28
|
+
invoke :help, ['grep']
|
|
29
|
+
else
|
|
30
|
+
require_relative 'commands/grep'
|
|
31
|
+
RubyEdit::Commands::Grep.new(options).execute
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
map %w[--grep -g] => :grep
|
|
36
|
+
|
|
37
|
+
desc 'configure', 'set and read your settings'
|
|
38
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display useage information'
|
|
39
|
+
method_option :editor, aliases: %w[-e --editor], type: :string,
|
|
40
|
+
desc: 'Set or view your default text editor'
|
|
41
|
+
def configure(*)
|
|
42
|
+
if options[:help]
|
|
43
|
+
invoke :help, ['configure']
|
|
44
|
+
else
|
|
45
|
+
require_relative 'commands/configure'
|
|
46
|
+
RubyEdit::Commands::Configure.new(options).execute
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
map %w[--configure -c] => :configure
|
|
51
|
+
|
|
52
|
+
desc 'edit', '[Default] Perform a grep and edit the changes in one file'
|
|
53
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
|
54
|
+
method_option :expression, aliases: %w[-e --expression], type: :string,
|
|
55
|
+
desc: 'the grep expression'
|
|
56
|
+
method_option :path, aliases: %w[-p --path], type: :string, desc: 'the path you want to search'
|
|
57
|
+
|
|
58
|
+
def edit(*)
|
|
59
|
+
if options[:help]
|
|
60
|
+
invoke :help, ['edit']
|
|
61
|
+
elsif options.empty?
|
|
62
|
+
invoke :help
|
|
63
|
+
else
|
|
64
|
+
require_relative 'commands/edit'
|
|
65
|
+
RubyEdit::Commands::Edit.new(options).execute
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
default_task :edit
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
class Command
|
|
7
|
+
extend Forwardable
|
|
8
|
+
|
|
9
|
+
def_delegators :command, :run
|
|
10
|
+
|
|
11
|
+
# Execute this command
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
def execute(*)
|
|
15
|
+
raise(
|
|
16
|
+
NotImplementedError,
|
|
17
|
+
"#{self.class}##{__method__} must be implemented"
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# The external commands runner
|
|
22
|
+
#
|
|
23
|
+
# @see http://www.rubydoc.info/gems/tty-command
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
def command(**options)
|
|
27
|
+
require 'tty-command'
|
|
28
|
+
TTY::Command.new(options)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The cursor movement
|
|
32
|
+
#
|
|
33
|
+
# @see http://www.rubydoc.info/gems/tty-cursor
|
|
34
|
+
#
|
|
35
|
+
# @api public
|
|
36
|
+
def cursor
|
|
37
|
+
require 'tty-cursor'
|
|
38
|
+
TTY::Cursor
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Open a file or text in the user's preferred editor
|
|
42
|
+
#
|
|
43
|
+
# @see http://www.rubydoc.info/gems/tty-editor
|
|
44
|
+
#
|
|
45
|
+
# @api public
|
|
46
|
+
def editor
|
|
47
|
+
require 'tty-editor'
|
|
48
|
+
TTY::Editor
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# File manipulation utility methods
|
|
52
|
+
#
|
|
53
|
+
# @see http://www.rubydoc.info/gems/tty-file
|
|
54
|
+
#
|
|
55
|
+
# @api public
|
|
56
|
+
def generator
|
|
57
|
+
require 'tty-file'
|
|
58
|
+
TTY::File
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Terminal output paging
|
|
62
|
+
#
|
|
63
|
+
# @see http://www.rubydoc.info/gems/tty-pager
|
|
64
|
+
#
|
|
65
|
+
# @api public
|
|
66
|
+
def pager(**options)
|
|
67
|
+
require 'tty-pager'
|
|
68
|
+
TTY::Pager.new(options)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Terminal platform and OS properties
|
|
72
|
+
#
|
|
73
|
+
# @see http://www.rubydoc.info/gems/tty-pager
|
|
74
|
+
#
|
|
75
|
+
# @api public
|
|
76
|
+
def platform
|
|
77
|
+
require 'tty-platform'
|
|
78
|
+
TTY::Platform.new
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The interactive prompt
|
|
82
|
+
#
|
|
83
|
+
# @see http://www.rubydoc.info/gems/tty-prompt
|
|
84
|
+
#
|
|
85
|
+
# @api public
|
|
86
|
+
def prompt(**options)
|
|
87
|
+
require 'tty-prompt'
|
|
88
|
+
TTY::Prompt.new(options)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Get terminal screen properties
|
|
92
|
+
#
|
|
93
|
+
# @see http://www.rubydoc.info/gems/tty-screen
|
|
94
|
+
#
|
|
95
|
+
# @api public
|
|
96
|
+
def screen
|
|
97
|
+
require 'tty-screen'
|
|
98
|
+
TTY::Screen
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The unix which utility
|
|
102
|
+
#
|
|
103
|
+
# @see http://www.rubydoc.info/gems/tty-which
|
|
104
|
+
#
|
|
105
|
+
# @api public
|
|
106
|
+
def which(*args)
|
|
107
|
+
require 'tty-which'
|
|
108
|
+
TTY::Which.which(*args)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Check if executable exists
|
|
112
|
+
#
|
|
113
|
+
# @see http://www.rubydoc.info/gems/tty-which
|
|
114
|
+
#
|
|
115
|
+
# @api public
|
|
116
|
+
def exec_exist?(*args)
|
|
117
|
+
require 'tty-which'
|
|
118
|
+
TTY::Which.exist?(*args)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
module Commands
|
|
7
|
+
class Configure
|
|
8
|
+
def initialize(options)
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def execute(output: $stdout)
|
|
13
|
+
# This may need to be made dynamic if more configuration options are added
|
|
14
|
+
if editor == 'editor'
|
|
15
|
+
output.puts RubyEdit.config.editor
|
|
16
|
+
else
|
|
17
|
+
RubyEdit.config.editor = editor
|
|
18
|
+
output.puts "Editor changed to #{editor}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def editor
|
|
25
|
+
@options[:editor]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit'
|
|
4
|
+
require 'ruby_edit/apply_prompt'
|
|
5
|
+
require 'ruby_edit/editor'
|
|
6
|
+
require 'ruby_edit/grep'
|
|
7
|
+
require 'ruby_edit/source_file'
|
|
8
|
+
require 'ruby_edit/writer'
|
|
9
|
+
|
|
10
|
+
module RubyEdit
|
|
11
|
+
module Commands
|
|
12
|
+
# TODO: Write an integration spec for this
|
|
13
|
+
class Edit
|
|
14
|
+
def initialize(options)
|
|
15
|
+
@grep = RubyEdit::Grep.new(options)
|
|
16
|
+
@sourcefile = RubyEdit::SourceFile.new
|
|
17
|
+
@editor = RubyEdit::Editor.new
|
|
18
|
+
@output = $stdout
|
|
19
|
+
@errors = $stderr
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def execute
|
|
23
|
+
grep_search
|
|
24
|
+
populate_sourcefile
|
|
25
|
+
edit_file
|
|
26
|
+
apply_changes if apply_changes?
|
|
27
|
+
delete_sourcefile
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def grep_search
|
|
33
|
+
@grep.search(output: @output, errors: @errors)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def populate_sourcefile
|
|
37
|
+
@sourcefile.populate(@grep.result.out)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def edit_file
|
|
41
|
+
@editor.edit_sourcefile
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def apply_changes?
|
|
45
|
+
RubyEdit::ApplyPrompt.new.continue?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def apply_changes
|
|
49
|
+
RubyEdit::Writer.new.write
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def delete_sourcefile
|
|
53
|
+
@sourcefile.delete
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit/grep'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
module Commands
|
|
7
|
+
class Grep
|
|
8
|
+
def initialize(options)
|
|
9
|
+
@options = options
|
|
10
|
+
@grep = RubyEdit::Grep.new(@options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute(output: $stdout)
|
|
14
|
+
@result = @grep.search
|
|
15
|
+
output.puts 'OK'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'tty/config'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
class Configuration
|
|
7
|
+
LOCATION = File.expand_path('../../configuration', __dir__)
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@config = TTY::Config.new
|
|
11
|
+
@config.filename = LOCATION
|
|
12
|
+
@config.read("#{LOCATION}.yml")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def editor
|
|
16
|
+
@config.fetch(:editor).to_sym
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def editor=(editor)
|
|
20
|
+
@config.set(:editor, value: editor.to_s)
|
|
21
|
+
write
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reset_defaults
|
|
25
|
+
@config.set(:editor, value: 'vim')
|
|
26
|
+
write
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def write
|
|
32
|
+
@config.write
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit/command'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
class Editor < RubyEdit::Command
|
|
7
|
+
def initialize
|
|
8
|
+
@config = RubyEdit.config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def edit_sourcefile
|
|
12
|
+
editor.open RubyEdit::SOURCE_FILE_LOCATION, command: @config.editor
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit/command'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
class Grep < RubyEdit::Command
|
|
7
|
+
attr_reader :result
|
|
8
|
+
|
|
9
|
+
def initialize(options)
|
|
10
|
+
@path = options[:path] || '.'
|
|
11
|
+
@expression = options[:expression]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def search(output: $stdout, errors: $stderr)
|
|
15
|
+
if empty_expression?
|
|
16
|
+
output.puts 'No expression given'
|
|
17
|
+
return false
|
|
18
|
+
end
|
|
19
|
+
@result = run "grep -irn #{@path} -e '#{@expression}'" do |out, err|
|
|
20
|
+
output << out if out
|
|
21
|
+
errors << err if err
|
|
22
|
+
end
|
|
23
|
+
rescue TTY::Command::ExitError => error
|
|
24
|
+
output.puts error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def empty_expression?
|
|
30
|
+
@expression.nil? || @expression.empty?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ruby_edit/command'
|
|
4
|
+
|
|
5
|
+
module RubyEdit
|
|
6
|
+
class SourceFile < RubyEdit::Command
|
|
7
|
+
def populate(content)
|
|
8
|
+
generator.create_file(RubyEdit::SOURCE_FILE_LOCATION, content, force: true)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def delete
|
|
12
|
+
generator.remove_file(RubyEdit::SOURCE_FILE_LOCATION)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
require 'ruby_edit/command'
|
|
6
|
+
|
|
7
|
+
module RubyEdit
|
|
8
|
+
class Writer < RubyEdit::Command
|
|
9
|
+
LINE_REGEX = /^.*\d+./
|
|
10
|
+
|
|
11
|
+
def write
|
|
12
|
+
File.open(RubyEdit::SOURCE_FILE_LOCATION, 'rb') do |file|
|
|
13
|
+
file.each_line { |line| find_and_replace_line line }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def find_and_replace_line(new_line)
|
|
20
|
+
@temp_file = Tempfile.new('temp_file')
|
|
21
|
+
split_file_and_line(new_line)
|
|
22
|
+
@new_line = new_line.sub LINE_REGEX, ''
|
|
23
|
+
begin
|
|
24
|
+
replace_line
|
|
25
|
+
replace_file
|
|
26
|
+
ensure
|
|
27
|
+
@temp_file.close
|
|
28
|
+
@temp_file.unlink
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def split_file_and_line(line)
|
|
33
|
+
@file_name, @line_number = line.match(LINE_REGEX)[0].split(':')
|
|
34
|
+
rescue NoMethodError
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Replaces the line in the original file, with the line from the sourcefile
|
|
39
|
+
def replace_line
|
|
40
|
+
File.open(@file_name, 'r+') do |file|
|
|
41
|
+
file.each_with_index do |line, index|
|
|
42
|
+
output = index + 1 == @line_number.to_i ? @new_line : line
|
|
43
|
+
@temp_file.puts output
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Replaces the old file, with the new edited file
|
|
49
|
+
def replace_file
|
|
50
|
+
@temp_file.close
|
|
51
|
+
FileUtils.mv(@temp_file.path, @file_name)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|