Class | AutomateIt::EditManager::EditSession |
In: |
lib/automateit/edit_manager.rb
|
Parent: | AutomateIt::Common |
EditSession provides a way to edit files and strings.
For example, here‘s how to edit a string from the Interpreter:
edit(:text => "# hello") do uncomment "llo" append "world" end # => "hello\nworld"
The above example edits a text string containing "# hello". The editing session uncomments the line containing "llo" and then appends a line with the word "world". The edited result is returned, containing two lines: "hello" and "world".
The edit session only makes changes if they‘re needed. In the above example, once the "hello" line is uncommented, the "uncomment" command won‘t do anything. Similarly, once the word "world" has been appended, it won‘t be appended again. So if you re-edit the resulting string, it won‘t be changed because it‘s already in the desired state.
This approach simplifies editing because you only need to specify the commands that are needed to change the file, and the session will figure out which ones to run.
comment_prefix | [RW] | Comment prefix, e.g., "/*" |
comment_suffix | [RW] | Comment suffix, e.g., "*/" |
contents | [RW] | Current contents of the editing buffer. |
filename | [RW] | File that was read for editing. |
original_contents | [RW] | Original contents of the editing buffer before any changes were made. |
params | [RW] | Hash of parameters to make available to the editing session. |
Create an EditSession.
Options:
# File lib/automateit/edit_manager.rb, line 70 def initialize(*args) super(*args) interpreter.add_method_missing_to(self) end
Append line to the bottom of the buffer, but only if it‘s not in this file already.
Options:
See example for prepend.
# File lib/automateit/edit_manager.rb, line 202 def append(line, opts={}) query = opts[:unless] || line if query.is_a?(String) query = Regexp.new(Regexp.escape(query)) end return if contains?(query) @contents = "%s\n%s\n" % [@contents.chomp, line] end
Comment out lines matching the String or Regexp query.
# File lib/automateit/edit_manager.rb, line 235 def comment(line, opts={}) query = line.is_a?(String) ? Regexp.escape(line) : line query = Regexp.new("^(?!#{comment_prefix})([^\n]*%s[^\n]*)(\n*)" % query) return false unless @contents.match(query) @contents.gsub!(query, "%s%s%s%s" % [@comment_prefix, $1, @comment_suffix, $2]) end
Does the buffer contain anything that matches the String or Regexp query?
# File lib/automateit/edit_manager.rb, line 212 def contains?(line) query = line.is_a?(String) ? Regexp.new(Regexp.escape(line)) : line ! @contents.match(query).nil? end
Delete lines matching the String or Regexp query
# File lib/automateit/edit_manager.rb, line 218 def delete(line, opts={}) query = line.is_a?(String) ? Regexp.escape(line) : line query = Regexp.new("^[^\n]*%s[^\n]*\n?" % query) @contents.gsub!(query, "") end
Is the buffer currently different than its original contents?
# File lib/automateit/edit_manager.rb, line 268 def different? @contents != @original_contents end
Edit a file or string.
Requires a filename argument or options hash — e.g.,. edit("foo") and edit(:file => "foo") will both edit a file called foo.
Options:
Edit a string:
edit(:text => "foo") do replace "o", "@" end # => "f@@"
Edit a file and pass parameters to the editing session:
edit(:file => "myfile", :params => {:greet => "world"} do prepend "MyHeader" append "Hello "+params[:greet] end
Edit a file, create it and set permissions if necessary:
edit("/tmp/foo", :create => true, :mode => 0600, :user => :root) do prepend "Hello world!" end
# File lib/automateit/edit_manager.rb, line 108 def edit(*a, &block) args, opts = args_and_opts(*a) if args.first @filename = args.first else raise ArgumentError.new("no file or text specified for editing") unless opts[:file] or opts[:text] @filename = opts[:file] @contents = opts[:text] end @params = opts[:params] || {} @is_backup = opts[:backup].nil? ? true : opts[:backup] @comment_prefix = "# " @comment_suffix = "" begin @contents ||= _read || "" rescue Errno::ENOENT => e if opts[:create] @contents = "" else raise e end end @original_contents = @contents.clone raise ArgumentError.new("no block given") unless block instance_eval(&block) if @filename if different? _backup if @is_backup _write end chperm_opts = {} for key in [:owner, :user, :group, :mode] chperm_opts[key] = opts[key] if opts[key] end chperm(@filename, chperm_opts) unless chperm_opts.empty? return different? else return contents end end
Manipulate the buffer. The result of your block will replace the buffer. This is very useful for complex edits.
Example:
manipulate do |buffer| buffer.gsub(/foo/, "bar") end
# File lib/automateit/edit_manager.rb, line 263 def manipulate(&block) # :yields: buffer @contents = block.call(@contents) end
Prepend line to the top of the buffer, but only if it‘s not in this file already.
Options:
Example:
# Buffer's contents are 'add this line' # This will prepend a line because they're not identical. prepend("add this line") # Won't prepend line because Regexp matches exisint line in buffer. prepend("add this line", :unless => /add\s*this\*line/)
# File lib/automateit/edit_manager.rb, line 185 def prepend(line, opts={}) query = opts[:unless] || line if query.is_a?(String) query = Regexp.new(Regexp.escape(query)) end return if contains?(query) @contents = "%s\n%s" % [line.chomp, @contents] end
Replace contents matching the String or Regexp query with the string.
# File lib/automateit/edit_manager.rb, line 251 def replace(line, string, opts={}) query = line.is_a?(String) ? Regexp.new(Regexp.escape(line)) : line @contents.gsub!(query, string) end
Uncomment lines matching the String or Regexp query.
# File lib/automateit/edit_manager.rb, line 243 def uncomment(line, opts={}) query = line.is_a?(String) ? Regexp.escape(line) : line query = Regexp.new("^(%s)([^\n]*%s[^\n]*)(%s)(\n*)" % [@comment_prefix, query, @comment_suffix]) return false unless @contents.match(query) @contents.gsub!(query, "%s%s" % [$2, $4]) end
Backup the original file.
# File lib/automateit/edit_manager.rb, line 301 def _backup return false unless @filename and File.exists?(@filename) result = nil log.silence(Logger::WARN) do result = backup(@filename) end log.debug(PNOTE+"Saved '#{@filename}' to '#{result}'") end
Does the file exist?
# File lib/automateit/edit_manager.rb, line 311 def _exists? File.exists?(@filename) end
Read contents from filename. Called by the edit command to load text into the buffer.
# File lib/automateit/edit_manager.rb, line 276 def _read @contents = \ if writing? or (preview? and @filename and _exists? and _readable?) File.read(@filename) elsif preview? and not _readable? log.info(PNOTE+"Not allowed to read file, previewing edits as if it doesn't exist: #{@filename}") nil else nil end end
Is the file readable?
# File lib/automateit/edit_manager.rb, line 316 def _readable? FileTest.readable?(@filename) end
Write contents to filename. Used by the edit command to write the buffer to a file.
# File lib/automateit/edit_manager.rb, line 290 def _write return false unless @filename log.info(PNOTE+"Edited '#{@filename}'") if preview? true else File.open(@filename, "w+"){|writer| writer.write(@contents)} end end