Class: AutomateIt::EditManager::EditSession

Inherits:
Common show all
Defined in:
lib/automateit/edit_manager.rb

Overview

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.

Constant Summary

Constants included from Constants

Constants::HELPERS_DIR, Constants::INSTALL_DIR, Constants::PERROR, Constants::PEXEC, Constants::PNOTE, Constants::WARNING_BOILERPLATE

Instance Attribute Summary collapse

Attributes inherited from Common

#interpreter

Instance Method Summary collapse

Methods inherited from Common

#log, #nitpick, #noop, #noop=, #noop?, #preview, #preview=, #preview?, #preview_for, #setup, #superuser?, #writing, #writing=, #writing?

Constructor Details

#initialize(*args) ⇒ EditSession

Create an EditSession.

Options:

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



70
71
72
73
# File 'lib/automateit/edit_manager.rb', line 70

def initialize(*args)
  super(*args)
  interpreter.add_method_missing_to(self)
end

Instance Attribute Details

#comment_prefixObject

Comment prefix, e.g., “/*”



165
166
167
# File 'lib/automateit/edit_manager.rb', line 165

def comment_prefix
  @comment_prefix
end

#comment_suffixObject

Comment suffix, e.g., “*/”



168
169
170
# File 'lib/automateit/edit_manager.rb', line 168

def comment_suffix
  @comment_suffix
end

#contentsObject

Current contents of the editing buffer.



156
157
158
# File 'lib/automateit/edit_manager.rb', line 156

def contents
  @contents
end

#filenameObject

File that was read for editing.



153
154
155
# File 'lib/automateit/edit_manager.rb', line 153

def filename
  @filename
end

#original_contentsObject

Original contents of the editing buffer before any changes were made.



159
160
161
# File 'lib/automateit/edit_manager.rb', line 159

def original_contents
  @original_contents
end

#paramsObject

Hash of parameters to make available to the editing session.



162
163
164
# File 'lib/automateit/edit_manager.rb', line 162

def params
  @params
end

Instance Method Details

#append(line, opts = {}) ⇒ Object

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.



202
203
204
205
206
207
208
209
# 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 = {}) ⇒ Object

Comment out lines matching the String or Regexp query.



235
236
237
238
239
240
# 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 = "") ⇒ Object

Specify the comment style’s prefix and suffix.

Example:

# C style comments
comment_style "/*", "*/"


229
230
231
232
# File 'lib/automateit/edit_manager.rb', line 229

def comment_style(prefix, suffix="")
  @comment_prefix = prefix
  @comment_suffix = suffix
end

#contains?(line) ⇒ Boolean

Does the buffer contain anything that matches the String or Regexp query?

Returns:

  • (Boolean)


212
213
214
215
# 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 = {}) ⇒ Object

Delete lines matching the String or Regexp query



218
219
220
221
222
# 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?Boolean

Is the buffer currently different than its original contents?

Returns:

  • (Boolean)


268
269
270
# File 'lib/automateit/edit_manager.rb', line 268

def different?
  @contents != @original_contents
end

#edit(*a, &block) ⇒ Object

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

Raises:

  • (ArgumentError)


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# 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(&block) ⇒ Object

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


263
264
265
# File 'lib/automateit/edit_manager.rb', line 263

def manipulate(&block) # :yields: buffer
  @contents = block.call(@contents)
end

#prepend(line, opts = {}) ⇒ Object

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/)


185
186
187
188
189
190
191
192
# 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 = {}) ⇒ Object

Replace contents matching the String or Regexp query with the string.



251
252
253
254
# 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 = {}) ⇒ Object

Uncomment lines matching the String or Regexp query.



243
244
245
246
247
248
# 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