class AutomateIt::EditManager::EditSession

EditSession

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.

Attributes

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.

Public Class Methods

new(*args) click to toggle source

Create an EditSession.

Options:

  • :interpreter – AutomateIt Interpreter, required. Will be automatically set if you use AutomateIt::Interpreter#edit.

Calls superclass method AutomateIt::Common::new
# File lib/automateit/edit_manager.rb, line 70
def initialize(*args)
  super(*args)
  interpreter.add_method_missing_to(self)
end

Public Instance Methods

append(line, opts={}) click to toggle source

Append line to the bottom of the buffer, but only if it’s not in this file already.

Options:

  • :unless – Look for this String or Regexp instead and don’t append if it matches.

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(line, opts={}) click to toggle source

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
comment_style(prefix, suffix="") click to toggle source

Specify the comment style’s prefix and suffix.

Example:

# C style comments
comment_style "/*", "*/"
# File lib/automateit/edit_manager.rb, line 229
def comment_style(prefix, suffix="")
  @comment_prefix = prefix
  @comment_suffix = suffix
end
contains?(line) click to toggle source

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(line, opts={}) click to toggle source

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
different?() click to toggle source

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, &block) click to toggle source

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:

  • :file – File to edit.

  • :text – String to edit.

  • :params – Hash to make available to editor session.

  • :create – Create the file if it doesn’t exist? Defaults to false.

  • :mode, :user, :group – Set permissions on generated file, see ShellManager#chperm

  • :backup – Make a backup of original file? Defaults to true.

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() { |buffer| ... } click to toggle source

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, opts={}) click to toggle source

Prepend line to the top of the buffer, but only if it’s not in this file already.

Options:

  • :unless – Look for this String or Regexp instead and don’t prepend if it matches.

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(line, string, opts={}) click to toggle source

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(line, opts={}) click to toggle source

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

Protected Instance Methods

_backup() click to toggle source

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
_exists?() click to toggle source

Does the file exist?

# File lib/automateit/edit_manager.rb, line 311
def _exists?
  File.exists?(@filename)
end
_read() click to toggle source

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
_readable?() click to toggle source

Is the file readable?

# File lib/automateit/edit_manager.rb, line 316
def _readable?
  FileTest.readable?(@filename)
end
_write() click to toggle source

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