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



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

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:



101
102
103
# File 'lib/utils/editor.rb', line 101

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



93
94
95
# File 'lib/utils/editor.rb', line 93

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



70
71
72
# File 'lib/utils/editor.rb', line 70

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



85
86
87
# File 'lib/utils/editor.rb', line 85

def servername
  @servername
end

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

The wait method gets the wait status.

Returns:

  • (TrueClass, FalseClass, nil)

    the wait status value



75
76
77
# File 'lib/utils/editor.rb', line 75

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.



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

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



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

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



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

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



240
241
242
243
# File 'lib/utils/editor.rb', line 240

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



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

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



379
380
381
382
# File 'lib/utils/editor.rb', line 379

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



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

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



407
408
409
410
# File 'lib/utils/editor.rb', line 407

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



392
393
394
395
# File 'lib/utils/editor.rb', line 392

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



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

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



183
184
185
# File 'lib/utils/editor.rb', line 183

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



170
171
172
# File 'lib/utils/editor.rb', line 170

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



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

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



352
353
354
# File 'lib/utils/editor.rb', line 352

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.



307
308
309
310
# File 'lib/utils/editor.rb', line 307

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



365
366
367
# File 'lib/utils/editor.rb', line 365

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.



316
317
318
# File 'lib/utils/editor.rb', line 316

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



110
111
112
# File 'lib/utils/editor.rb', line 110

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