Class: Utils::Editor

Inherits:
Object show all
Defined in:
lib/utils/editor.rb

Overview

An editor interface for interacting with Vim server instances.

This class provides functionality for managing Vim editor sessions through server connections, enabling features like remote file editing, window management, and server state monitoring. It handles communication with running Vim instances and supports various configuration options for customizing the editing experience.

Examples:

editor = Utils::Editor.new
editor.edit('file.rb')
editor.activate
editor.stop

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize { ... } ⇒ Utils::Editor

The initialize method sets up a new editor instance with default configuration.

This method configures the editor by initializing default values for wait flag, pause duration, and server name. It also loads the configuration file and assigns the edit configuration section to the instance.

self as argument.

Yields:

  • |editor| optional block to be executed after initialization with



31
32
33
34
35
36
37
38
39
# File 'lib/utils/editor.rb', line 31

def initialize
  self.wait           = false
  self.pause_duration = 1
  self.servername     = derive_server_name
  config              = Utils::ConfigFile.new
  config.configure_from_paths
  self.config = config.edit
  yield self if block_given?
end

Instance Attribute Details

#configUtils::ConfigFile

The config method provides access to the configuration object.

This method returns the configuration instance variable that holds the settings and options for the object’s operation.

Returns:



99
100
101
# File 'lib/utils/editor.rb', line 99

def config
  @config
end

#mkdirTrueClass, FalseClass

The mkdir method provides access to the directory creation flag.

This method returns the current value of the mkdir flag, which determines whether directory creation should be attempted when processing files.

Returns:

  • (TrueClass, FalseClass)

    the current state of the mkdir flag



91
92
93
# File 'lib/utils/editor.rb', line 91

def mkdir
  @mkdir
end

#pause_durationInteger, Float

The pause_duration method provides access to the duration value used for pausing operations.

This method returns the current value of the pause duration attribute, which controls how long certain operations should wait or pause between actions.

Returns:

  • (Integer, Float)

    the current pause duration value in seconds



68
69
70
# File 'lib/utils/editor.rb', line 68

def pause_duration
  @pause_duration
end

#servernameString

The servername method provides access to the server name attribute.

This method returns the value of the server name instance variable, which represents the name of the server being used.

Returns:

  • (String)

    the server name value



83
84
85
# File 'lib/utils/editor.rb', line 83

def servername
  @servername
end

#waitTrueClass, ... Also known as: wait?

The wait method gets the wait status.

Returns:

  • (TrueClass, FalseClass, nil)

    the wait status value



73
74
75
# File 'lib/utils/editor.rb', line 73

def wait
  @wait
end

Instance Method Details

#activateObject

The activate method switches to the Vim editor window or opens a new one.

This method checks if the Vim default arguments include the ‘-g’ flag to determine whether to open a new buffer in the current window or switch to an existing Vim pane. When the ‘-g’ flag is present, it creates a temporary file and then closes it. Otherwise, it identifies the appropriate tmux pane running an editor process and switches to it.



325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/utils/editor.rb', line 325

def activate
  if Array(config.vim_default_args).include?('-g')
    edit_remote("stupid_trick#{rand}")
    sleep pause_duration
    edit_remote_send('<ESC>:bw<CR>')
  else
    pstree = PSTree.new
    switch_to_index =
      `tmux list-panes -F '\#{pane_pid} \#{pane_index}'`.lines.find { |l|
        pid, index = l.split(' ')
        pid = pid.to_i
        if pstree.find { |ps| ps.pid != $$ && ps.ppid == pid && ps.cmd =~ %r(/edit( |$)) }
          break index.to_i
        end
      }
    switch_to_index and system "tmux select-pane -t #{switch_to_index}"
  end
end

#cmd(*parts) ⇒ Boolean

The cmd method constructs a command from parts and executes it.

This method takes multiple arguments, processes them to build a command array, and then executes the command using the system call.

Parameters:

  • parts (Array)

    the parts to be included in the command

Returns:

  • (Boolean)

    true if the command was successful, false otherwise



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/utils/editor.rb', line 120

def cmd(*parts)
  command = parts.compact.inject([]) do |a, p|
    case
    when p == nil, p == []
      a
    when p.respond_to?(:to_ary)
      a.concat p.to_ary
    else
      a << p.to_s
    end
  end
  $DEBUG and warn command * ' '
  system(*command.map(&:to_s))
end

#edit(*filenames) ⇒ Object

The edit method processes filenames to determine their source location and delegates to appropriate editing methods.

If a single filename is provided and it has a source location, the method checks whether the location includes filename and linenumber attributes. If so, it calls edit_source_location with the source location; otherwise, it calls edit_file_linenumber with the source location components. If multiple filenames are provided and all have source locations, the method expands any glob patterns in the filenames, then calls edit_file with the expanded list of filenames. Finally, it ensures the editor is activated after processing.

may contain source location information

Parameters:

  • filenames (Array<String, Integer>)

    an array of filenames that



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/utils/editor.rb', line 199

def edit(*filenames)
  source_location = nil
  if filenames.size == 1 and
    source_location = filenames.first.source_location
  then
    if source_location.respond_to?(:filename) and source_location.respond_to?(:linenumber)
      edit_source_location(source_location)
    else
      edit_file_linenumber(*source_location)
    end
  elsif source_locations = filenames.map(&:source_location).compact.full?
    filenames = expand_globs(source_locations.map(&:first))
    edit_file(*filenames)
  end.tap do
    activate
  end
end

#edit_file(*filenames) ⇒ Object

The edit_file method processes a list of filenames by ensuring their directories exist and then delegates to a remote file editing function.

Parameters:

  • filenames (Array<String>)

    an array of filename strings to be processed



238
239
240
241
# File 'lib/utils/editor.rb', line 238

def edit_file(*filenames)
  make_dirs(*filenames)
  edit_remote_file(*filenames)
end

#edit_file_linenumber(filename, linenumber, rangeend = nil) ⇒ Object

The edit_file_linenumber method opens a file at a specific line number and optionally selects a range of lines in an editor.

opened nil if no range is specified

Parameters:

  • filename (String)

    the path to the file to be opened

  • linenumber (Integer)

    the line number where the file should be

  • rangeend (Integer, nil) (defaults to: nil)

    the ending line number for selection, or



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/utils/editor.rb', line 251

def edit_file_linenumber(filename, linenumber, rangeend = nil)
  make_dirs filename
  if rangeend
    Thread.new do
      while !started?
        sleep 1
      end
      edit_remote_send("<ESC>:normal #{linenumber}GV#{rangeend}G<CR>")
    end
  end
  if wait?
    activate
    edit_remote_wait("+#{linenumber}", filename)
  else
    edit_remote("+#{linenumber}", filename)
  end
end

#edit_remote(*args) ⇒ Object

The edit_remote method executes a remote Vim command with the specified arguments.

This method prepares a command to communicate with a running Vim server instance, allowing for remote execution of Vim commands without directly interacting with the terminal. It ensures the window is renamed before sending the command and constructs the appropriate command line arguments for the Vim server interface.

Parameters:

  • args (Array)

    the arguments to be passed to the remote Vim command



377
378
379
380
# File 'lib/utils/editor.rb', line 377

def edit_remote(*args)
  rename_window
  cmd(*vim, '--servername', servername, '--remote', *args)
end

#edit_remote_file(*filenames) ⇒ Object

The edit_remote_file method delegates to either edit_remote_wait or edit_remote based on the wait? condition.

This method determines whether to execute file editing operations with waiting for completion or without waiting, depending on the result of the wait? check.

Parameters:

  • filenames (Array<String>)

    an array of filenames to be processed



418
419
420
421
422
423
424
# File 'lib/utils/editor.rb', line 418

def edit_remote_file(*filenames)
  if wait?
    edit_remote_wait(*filenames)
  else
    edit_remote(*filenames)
  end
end

#edit_remote_send(*args) ⇒ Object

The edit_remote_send method transmits a sequence of arguments to a remote Vim server for execution.

This method prepares and sends commands to an already running Vim instance identified by its server name, allowing for remote control of the editor session. It ensures the window is properly named before sending the command, and uses the configured Vim executable along with its remote communication flags.

Parameters:

  • args (Array<String>)

    the arguments to be sent to the remote Vim server



405
406
407
408
# File 'lib/utils/editor.rb', line 405

def edit_remote_send(*args)
  rename_window
  cmd(*vim, '--servername', servername, '--remote-send', *args)
end

#edit_remote_wait(*args) ⇒ Object

The edit_remote_wait method executes a command remotely and waits for its completion.

This method sends a command to a remote server using the specified vim server connection, and blocks until the remote operation finishes executing.

Parameters:

  • args (Array)

    the arguments to be passed to the remote command



390
391
392
393
# File 'lib/utils/editor.rb', line 390

def edit_remote_wait(*args)
  rename_window
  cmd(*vim, '--servername', servername, '--remote-wait', *args)
end

#edit_source_location(source_location) ⇒ Object

The edit_source_location method processes a source location object to open the corresponding file at the specified line number.

This method takes a source location object and uses its filename, line number, and optional range end to invoke the edit_file_linenumber method for opening the file in an editor.

containing filename and line number information

Parameters:

  • source_location (Array<String, Integer>)

    the source location



278
279
280
281
282
283
284
# File 'lib/utils/editor.rb', line 278

def edit_source_location(source_location)
  edit_file_linenumber(
    source_location.filename,
    source_location.linenumber,
    source_location.rangeend
  )
end

#expand_globs(filenames) ⇒ Array<String>

The expand_globs method processes an array of filename patterns by expanding glob expressions and returning a sorted array of unique filenames.

include glob expressions

patterns expanded, or the original array if no glob patterns are present

Parameters:

  • filenames (Array<String>)

    an array of filename patterns that may

Returns:

  • (Array<String>)

    a sorted array of unique filenames with glob



181
182
183
# File 'lib/utils/editor.rb', line 181

def expand_globs(filenames)
  filenames.map { |f| Dir[f] }.flatten.uniq.sort.full? || filenames
end

#file_linenumber?(filename) ⇒ MatchData?

The file_linenumber? method checks if a filename matches the file and line number pattern.

This method determines whether the provided filename string conforms to the regular expression pattern used for identifying file paths accompanied by line numbers.

Parameters:

  • filename (String)

    the filename string to be checked

Returns:

  • (MatchData, nil)

    a match data object if the filename matches the pattern, or nil if it does not match



168
169
170
# File 'lib/utils/editor.rb', line 168

def file_linenumber?(filename)
  filename.match(Utils::Xt::SourceLocationExtension::FILE_LINENUMBER_REGEXP)
end

#fullscreen=(enabled) ⇒ Object

The fullscreen= method sets the fullscreen state for the remote editor session.

This method configures the fullscreen mode of the remote editor by sending appropriate commands through the edit_remote_send mechanism. It ensures the editor session is started and paused briefly before applying the fullscreen setting, then activates the session to apply the changes.

disable fullscreen mode

Parameters:

  • enabled (TrueClass, FalseClass)

    determines whether to enable or



146
147
148
149
150
151
152
153
154
155
# File 'lib/utils/editor.rb', line 146

def fullscreen=(enabled)
  start
  sleep pause_duration
  if enabled
    edit_remote_send '<ESC>:set fullscreen<CR>'
  else
    edit_remote_send '<ESC>:set nofullscreen<CR>'
  end
  activate
end

#serverlistArray<String>

The serverlist method retrieves a list of available Vim server names.

This method executes the Vim command to list all active servers and returns the results as an array of server names.

Returns:

  • (Array<String>)

    an array of Vim server names currently available



350
351
352
# File 'lib/utils/editor.rb', line 350

def serverlist
  `#{vim.map(&:inspect) * ' '} --serverlist`.split
end

#startObject

The start method initializes the Vim server connection if it is not already running.

This method first attempts to rename the terminal window to reflect the server name, then checks if the Vim server has already been started. If not, it executes the command to launch the Vim server with the specified server name.



305
306
307
308
# File 'lib/utils/editor.rb', line 305

def start
  rename_window
  started? or cmd(*vim, '--servername', servername)
end

#started?(name = servername) ⇒ TrueClass, FalseClass

The started? method checks whether a server with the given name is currently running.

This method verifies the presence of a server in the list of active servers by checking if the server name exists within the serverlist.

Parameters:

  • name (String) (defaults to: servername)

    the name of the server to check for

Returns:

  • (TrueClass, FalseClass)

    true if the server is running, false otherwise



363
364
365
# File 'lib/utils/editor.rb', line 363

def started?(name = servername)
  serverlist.member?(name)
end

#stopObject

The stop method sends a quit command to the remote editor.

This method checks if the editor is currently running and, if so, sends a quit command to close all windows and terminate the editor session.



314
315
316
# File 'lib/utils/editor.rb', line 314

def stop
  started? and edit_remote_send('<ESC>:qa<CR>')
end

#vimArray<String>

The vim method constructs and returns the Vim command configuration.

This method assembles the Vim command by combining the configured Vim path with any default arguments specified in the configuration.

Returns:

  • (Array<String>)

    an array containing the Vim executable path and its default arguments for command execution



108
109
110
# File 'lib/utils/editor.rb', line 108

def vim
  ([ config.vim_path ] + Array(config.vim_default_args))
end