Class: Ruber::Rake::Plugin

Inherits:
Ruber::RubyRunner::RubyRunnerPlugin show all
Defined in:
plugins/rake/rake.rb

Overview

Plugin object for the Rake plugin.

This plugin relies in a project extension to keep a list of project tasks.

Defined Under Namespace

Classes: Error, RakeError, RakefileNotFound, Timeout

Constant Summary

Constants inherited from Plugin

LICENSES

Instance Attribute Summary

Attributes inherited from ExternalProgramPlugin

process

Attributes included from PluginLike

plugin_description

Instance Method Summary (collapse)

Methods inherited from Ruber::RubyRunner::RubyRunnerPlugin

#interpreter_for, #option_for, #ruby_command_for

Methods inherited from ExternalProgramPlugin

#display_exit_message, #do_stderr, #do_stdout, #failed_to_start, #process_standard_error, #process_standard_output, #run_process, #shutdown, #slot_process_finished, #stop_process

Methods inherited from GuiPlugin

#action_collection, #execute_action, #register_action_handler, #setup_actions, #unload

Methods inherited from Plugin

#about_data

Methods included from PluginLike

#add_extensions_to_project, #add_options_to_project, #add_widgets_to_project, #create_tool_widget, #delayed_initialize, #initialize_plugin, #plugin_name, #query_close, #register_options, #register_with_project, #remove_extensions_from_project, #remove_from_project, #remove_options_from_project, #remove_widgets_from_project, #restore_session, #save_settings, #session_data, #setup_action, #setup_actions, #shutdown, #unload, #update_project

Signal Summary

Methods API

Constructor Details

- (Plugin) initialize(psf)

A new instance of Plugin

Parameters:



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'plugins/rake/rake.rb', line 132

def initialize psf
  @quick_tasks_actions = []
  @project_tasks_actions = []
  @current_target = nil
  super psf, :rake, :scope => [:global, :document]
  setup_handlers
  Ruber[:main_window].change_state 'rake_running', false
  Ruber[:autosave].register_plugin self, true
  @output_widget = @widget
  self.connect(SIGNAL(:rake_finished)) do
    Ruber[:main_window].change_state 'rake_running', false
  end
  self.connect(SIGNAL(:process_failed_to_start)){Ruber[:main_window].change_state 'rake_running', false}
  connect Ruber[:world], SIGNAL('active_project_changed(QObject*)'), self, SLOT(:set_current_target)
  connect Ruber[:world], SIGNAL('active_document_changed(QObject*)'), self, SLOT(:set_current_target)
  connect self, SIGNAL('process_finished(int, QString)'), self, SIGNAL(:rake_finished)
  connect self, SIGNAL('extension_added(QString, QObject*)'), self, SLOT(:set_current_target)
  connect self, SIGNAL('extension_removed(QString, QObject*)'), self, SLOT(:set_current_target)
  Ruber[:components].connect(SIGNAL('feature_loaded(QString, QObject*)')) do |f, o|
    o.register_plugin self, true if f == 'autosave'
  end
  fill_quick_tasks_menu
  set_current_target
end

Instance Method Details

- (nil) choose_and_run_task (private)

Slot associated with the rake-run action

It displays a dialog where the user can choose a taks for the current target, then executes it. If the user cancels the dialog, nothing else happens

Returns:

  • (nil)


369
370
371
372
373
# File 'plugins/rake/rake.rb', line 369

def choose_and_run_task
  task = choose_task_for @current_target
  return unless task
  @current_target.extension(:rake).run_rake task
end

Slot Signature:

choose_and_run_task()

- (String?) choose_task_for(prj) (private)

Displays a dialog where the user can choose the task to run according to the settings of the given project.

dialog with the Cancel button

Parameters:

Returns:

  • (String, nil)

    the name of the chosen task or nil if the user closed the



384
385
386
387
388
# File 'plugins/rake/rake.rb', line 384

def choose_task_for prj
  dlg = ChooseTaskDlg.new prj
  return if dlg.exec == Qt::Dialog::Rejected
  dlg.task
end

- (self) display_task_retrival_error_dialog(ex)

Displays a message box telling why rake failed to retrieve tasks

This method is meant to be called in a rescue clause for RakeError exceptions from methods which call #tasks. According to the type of exception raised, the appropriate text will be displayed in the message box.

Parameters:

  • ex (RakeError)

    the exception describing the error

Returns:

  • (self)


293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'plugins/rake/rake.rb', line 293

def display_task_retrival_error_dialog ex
  msg = case ex
  when RakeError
    # The <i></i> tag is needed because (according to the QMessageBox documentation),
    # for the text to be interpreted as rich text, an html tag must be present
    # before the first newline.
    "Rake aborted with the following error message:<i></i>\n<pre>#{e.rake_error}\n#{e.rake_backtrace.join "\n"}</pre>"
  when RakefileNotFound then "No rakefile was found"
  when Timeout then e.message
  end
  KDE::MessageBox.sorry Ruber[:main_window], msg
  self
end

- (nil) fill_project_menu (private)

Fills the Project Tasks menu, according to the current target

It clears the menu, then inserts in the menu one action for each entry in the current target’s rake/tasks option. If that option is empty, or if there’s no current target, then a single, disabled entry with text ‘(Empty)’ is inserted in the menu

Returns:

  • (nil)


516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
# File 'plugins/rake/rake.rb', line 516

def fill_project_menu
  @gui.unplug_action_list 'rake-project_tasks_list'
  mw = Ruber[:main_window]
  @project_tasks_actions.each do |a| 
    mw.remove_action_handler_for a
    a.dispose
  end
  @project_tasks_actions.clear
  coll = @gui.action_collection
  if @current_target
    tasks = @current_target[:rake, :tasks]
    tasks.each_pair do |t, x|
      desc, short = *x
      a = coll.add_action "rake-project_task-#{t}", self, SLOT(:run_project_task)
      a.text = t
      a.shortcut = KDE::Shortcut.new short if short
      a.help_text = desc
      Ruber[:main_window].register_action_handler a, 
          %w[rake_running active_project_exists], :extra_id => self, 
          &@quick_tasks_handler_prc
      @project_tasks_actions << a
    end
  end
  if @project_tasks_actions.empty?
    a = coll.add_action 'rake-project_tasks_empty'
    a.text = "(Empty)"
    a.enabled = false
    @project_tasks_actions << a
  end
  @gui.plug_action_list 'rake-project_tasks_list', @project_tasks_actions
  nil
end

Slot Signature:

fill_project_menu()

- (Object) fill_quick_tasks_menu (private)

Fills the Quick Tasks menu

It removes the rake-quick_tasks_list action list from the menu, then creates the actions according to the current content of the rake/quick_tasks option and fills the menu again.

If the rake/quick_tasks option is empty, a single, disabled action with text (Empty) is inserted.

Returns:

  • nil



335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'plugins/rake/rake.rb', line 335

def fill_quick_tasks_menu
  mw = Ruber[:main_window]
  @quick_tasks_actions.each do |a| 
    mw.remove_action_handler_for a if a.object_name != 'rake-quick_task_empty_action'
    a.dispose
  end
  @gui.unplug_action_list "rake-quick_tasks_list"
  coll = @gui.action_collection
  @quick_tasks_actions = Ruber[:config][:rake, :quick_tasks].sort.map do |k, v|
    a = coll.add_action "rake-quick_task-#{k}", self, SLOT(:run_quick_task)
    a.text = k
    a.shortcut = KDE::Shortcut.new(v)
    mw.register_action_handler a, %w[rake_running active_project_exists current_document],  :extra_id => self, &@quick_tasks_handler_prc
    a
  end
  if @quick_tasks_actions.empty?
    a = coll.add_action 'rake-quick_task_empty_action'
    a.text = '(Empty)'
    a.enabled = false
    a.object_name = 'rake-quick_task_empty_action'
    @quick_tasks_actions << a
  end
  @gui.plug_action_list "rake-quick_tasks_list", @quick_tasks_actions
  nil
end

- (Array<String>) filter_options_to_find_tasks(opts) (private)

Given a list of rake options, creates a list containing only those which are safe to use from tasks.

The options which will be removed are: -D, -n, -P, -q, —rules, -s, -t, v, -V, -h, -e, -p and -E, because in a way or another have the capability to change the rake output from what tasks_for expects.

Note: this method creates a new array; it doesn’t modify opts.

Parameters:

  • opts (Array <String>)

    a list of options to be passed to rake

Returns:

  • (Array<String>)

    an array containing only the safe options from opts



465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'plugins/rake/rake.rb', line 465

def filter_options_to_find_tasks opts
  flags_to_delete = %w[-D --describe -n --dry-run -P --prereqs -q --quiet  --rules -s --silent -t --trace -v --verbose -V --version -h -H --help]
  opts = opts.dup
  opts.delete '-D'
  opts.delete '--describe'
  opts.delete '-n'
  %w[-e --execute -p --execute-print -E --execute-continue].each do |o|
    idxs = opts.each_index.find_all{|i| opts[i] == o}
    idxs.reverse_each do |i| 
      opts.delete_at i + 1
      opts.delete_at i
    end
  end
  opts
end

- (DocumentProject, ...) find_current_target (private)

The project to run rake for when one of the rake menu entries is chosen

document if the latter is a rakefile and doesn’t belong to the current project it isn’t a rakefile and there’s no open project

Returns:

  • (DocumentProject)

    the DocumentProject associated with the current

  • (Project)

    the current project, if the current file belongs to it or if

  • (nil)

    if there’s no open document or if the current document isn’t a rakefile



439
440
441
442
443
444
445
446
447
448
# File 'plugins/rake/rake.rb', line 439

def find_current_target
  target = Ruber[:world].active_document.project rescue nil
  if target.nil? or !target.has_extension? :rake
    prj = Ruber[:world].active_project
    target = if prj and prj.has_extension? :rake then prj
    else nil
    end
  end
  target
end

- (nil) load_settings

Loads the settings

While loading the settings, it also builds the Quick Tasks menu

Returns:

  • (nil)


164
165
166
167
168
169
# File 'plugins/rake/rake.rb', line 164

def load_settings
  cfg = Ruber[:config][:rake]
  #This method is called from Plugin#initialize before the gui is created
  fill_quick_tasks_menu if @gui
  nil
end

Slot Signature:

load_settings()

- (nil) refresh_tasks (private)

Updates the tasks

Returns:

  • (nil)


554
555
556
557
558
559
560
561
# File 'plugins/rake/rake.rb', line 554

def refresh_tasks
  Ruber[:app].with_override_cursor do
    begin @current_target.extension(:rake).update_tasks
    rescue Error => ex
      display_task_retrival_error_dialog ex
    end
  end
end

Slot Signature:

refresh_tasks()

- (nil) run_default_task (private)

Slot associated with the rake-run_default action.

Runs the default task for the current target

Returns:

  • (nil)


396
397
398
399
# File 'plugins/rake/rake.rb', line 396

def run_default_task
  @current_target.extension(:rake).run_rake nil
  nil
end

Slot Signature:

run_default_task()

- (nil) run_project_task (private)

Slot associated with the various project tasks actions defined by the user for the current target

Runs the rake task whose name is equal to the name of the action which called this slot

Returns:

  • (nil)


423
424
425
426
# File 'plugins/rake/rake.rb', line 423

def run_project_task
  task = sender.text.gsub('&', '')
  @current_target.extension(:rake).run_rake task
end

Slot Signature:

run_project_task()

- (nil) run_quick_task (private)

Slot associated with the various quick tasks actions defined by the user

Runs the rake task whose name is equal to the name of the action which called this slot

Returns:

  • (nil)


409
410
411
412
# File 'plugins/rake/rake.rb', line 409

def run_quick_task
  task = sender.text.gsub('&', '')
  @current_target.extension(:rake).run_rake task
end

Slot Signature:

run_quick_task()

- (nil) run_rake(ruby, dir, data)

Runs rake, displaying the output in the associated output widget, according to the given options.

rake. The system environment will be used if this is empty executed if this is missing

Parameters:

  • ruby (String)

    the path of the ruby interpreter to use to run rake

  • dir (String)

    the directory rake should be run from

  • data (Hash)

    a hash containing the options to pass to rake or ruby

Options Hash (data):

  • :ruby_options (Array<String>) — default: []

    The arguments to pass to ruby itself

  • :rake (String) — default: Ruber[:config][:rake, :rake]

    The path to the rake program to use

  • :options (Array<String>) — default: []

    The options to pass to rake

  • :rakefile (String) — default: nil

    The rakefile to use (use the default rakefile if nil)

  • :env (Array<String>) — default: []

    The environment variables to set before calling

  • :task (String) — default: nil

    The task to execute. The default task will be

Returns:

  • (nil)


266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'plugins/rake/rake.rb', line 266

def run_rake ruby, dir, data
  rake = data[:rake]
  args = Array(data[:ruby_options]) + [rake] + Array(data[:options])
  args += ['-f', data[:rakefile]] if data[:rakefile]
  args << data[:task] if data[:task]
  env = Array(data[:env])
  process.environment = process.system_environment + env
  cmd = env + [ruby] + args 
  @widget.clear_output
  @widget.working_directory = dir
  Ruber[:main_window].activate_tool @widget
  Ruber[:main_window].change_state 'rake_running', true
  run_process ruby, dir, args
  nil
end

- (nil) set_current_target (private)

Changes the current target.

It uses #find_current_target to find out the new current target, then, if it is different from the old one, makes the necessary connections and disconnections and refills the project menu

Returns:

  • (nil)


490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# File 'plugins/rake/rake.rb', line 490

def set_current_target
  target = find_current_target
  return if target == @current_target
  # If the project is being closed, the extension may have been removed
  if @current_target and @current_target.extension(:rake)
    @current_target.extension(:rake).disconnect SIGNAL(:tasks_updated)
  end
  @current_target = target
  fill_project_menu
  if @current_target
    connect @current_target.extension(:rake), SIGNAL(:tasks_updated), self, SLOT(:fill_project_menu)
  end
  Ruber[:main_window].set_state 'rake_has_target', !@current_target.nil?
  nil
end

Slot Signature:

set_current_target()

- (nil) setup_handlers (private)

Creates and registers the gui state handlers for the actions provided by the plugin.

Returns:

  • (nil)


314
315
316
317
318
319
320
321
# File 'plugins/rake/rake.rb', line 314

def setup_handlers
  @quick_tasks_handler_prc = Proc.new do |sts|
    !sts['rake_running'] and sts['rake_has_target']
  end
  register_action_handler 'rake-run', &@quick_tasks_handler_prc
  register_action_handler 'rake-run_default', &@quick_tasks_handler_prc
  nil
end

- (Hash) tasks(ruby, dir, opts)

The rake tasks availlable, according to the given options.

To obtain the task list, this method calls rake -T synchronously (this means that the method won’t return until rake has finished). To avoid freezing Ruber should rake go into an endless loop, this method will give up after a given time (default: 30 seconds).

For this method to work, the output from rake -T should be a series of lines of the form

rake task_name # Description

However, rake accepts a number of options which may (at least potentially) change this output. If any of these is included in the :options entry of opts_, it’ll be removed (see #filter_options_to_find</em>tasks for a list of the problematic options)

rake. must be of the form VARIABLE=VALUE won’t be passed to rake, which will choose the rakefile by itself rake hasn’t finished

Parameters:

  • ruby (String)

    the path of the ruby interpreter to use

  • dir (String)

    the directory rake should be run from

  • opts (Hash)

    a hash containing options to pass to rake and ruby

Options Hash (opts):

  • :rake (String) — default: Ruber[:config][:rake, :rake]

    the path to

  • :options (<String>) — default: []

    the options to pass to rake

  • :env (<String>) — default: []

    the environment to pass to rake. Each entry

  • :ruby_options (<String>) — default: []

    the arguments to pass to ruby

  • :rakefile (String) — default: nil

    the rakefile to use. If nil, the -f option

  • :timeout (Integer) — default: 30

    the number of seconds before giving up if

Returns:

  • (Hash)

    a hash with task names as keys and task descriptions as values

Raises:

  • (RakeError)

    if rake reports an error while executing the rakefile

  • (RakefileNotFound)

    if rake can’t find the rakefile

  • (Timeout)

    if rake -T doesn’t exit after a suitable time



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'plugins/rake/rake.rb', line 209

def tasks ruby, dir, opts
  rake = opts[:rake]
  default_opts = {:options => [], :env => [], :ruby_options => []}
  options = default_opts.merge opts
  options = filter_options_to_find_tasks options[:options]
  args = [rake, '-T'] + options
  args << '-f' << opts[:rakefile] if opts[:rakefile]
  env = opts[:env].join ' '
  cmd = [ruby] + opts[:ruby_options] + args
  timeout = opts[:timeout] || 30
  begin
    out, err = ::Timeout.timeout(timeout) do
      _in, out, err = Open3.popen3 env + cmd.join(' ')
      [out.read, err.read]
    end
  rescue ::Timeout::Error
    ['', 'timeout']
  end
  if err.sub!(/^\s*rake aborted!\s*\n/i, '')
    if err=~ /no rakefile found/i then raise RakefileNotFound, err
    elsif err == 'timeout'
      raise Timeout.new(timeout)
    else
      lines = err.split_lines
      err = lines.shift
      lines.delete_at(-1) if lines[-1] =~ /^\s*\(See full trace/
      raise RakeError.new err, lines
    end
  end
  out = out.split_lines.map do |l|
    if l.match(/^\s*rake\s*(.*)\s#\s+(.*)/) then [$1.strip, $2]
    else nil
    end
  end
  out.compact!
  out.to_h
end

Signal Details

- rake_finished

Signal emitted when the rake program started with #run_rake has exited