Belle II Software development
InputEditor Class Reference

Public Member Functions

 __init__ (self, str editor_command=None, str initial_content=None, str commentlines_start_with="#")
 
 input (self)
 
 get_editor_command (self)
 

Public Attributes

 editor_command_list = shlex.split(editor_command_string, posix=True)
 command line for the editor, split to separate executable name command line arguments
 
 initial_content = initial_content
 initial content of the editor window
 
 comment_string = commentlines_start_with
 string which starts comments in the file
 

Protected Member Functions

 _remove_comment_lines (self, a_string)
 
 _default_environment_editor (self)
 
 _prompt_for_editor (self)
 

Detailed Description

Class to get user input via opening a temporary file in a text editor.

It is an alternative to the python commands ``input()`` or ``sys.stdin.readlines`` and is
similar to the behaviour of ``git commit`` for editing commit messages.  By using an editor
instead of the command line, the user is motivated to give expressive multi-line input,
leveraging the full text editing capabilities of his editor.  This function cannot be used for
example in interactive terminal scripts, whenever detailed user input is required.

Heavily inspired by the code in this blog post:
https://chase-seibert.github.io/blog/2012/10/31/python-fork-exec-vim-raw-input.html

Parameters:
    editor_command: Editor to open for user input.  If ``None``, get
        default editor from environment variables.  It should be the name
        of a shell executable and can contain command line arguments.
    initial_content: Initial string to insert into the temporary file that
        is opened for user input.  Can be used for default input or to
        insert comment lines with instructions.
    commentlines_start_with: Optionally define string with which comment
        lines start

Definition at line 316 of file terminal_utils.py.

Constructor & Destructor Documentation

◆ __init__()

__init__ ( self,
str editor_command = None,
str initial_content = None,
str commentlines_start_with = "#" )
Constructor

Definition at line 340 of file terminal_utils.py.

343 commentlines_start_with: str = "#"):
344 """Constructor"""
345 # Use provided editor command or editor command from environment variables
346 editor_command_string = editor_command or self._default_environment_editor()
347 ## command line for the editor, split to separate executable name command line arguments
348 self.editor_command_list = shlex.split(editor_command_string, posix=True)
349 # check if editor executable exists and if not, prompt for new editor command
350 if shutil.which(self.editor_command_list[0]) is None:
351 self._prompt_for_editor()
352
353 ## initial content of the editor window
354 self.initial_content = initial_content
355 ## string which starts comments in the file
356 self.comment_string = commentlines_start_with
357

Member Function Documentation

◆ _default_environment_editor()

_default_environment_editor ( self)
protected
Return editor from environment variables. If not existing, return vi(m) as default.

Definition at line 396 of file terminal_utils.py.

396 def _default_environment_editor(self):
397 """
398 Return editor from environment variables. If not existing, return vi(m) as default.
399 """
400 editor_command = (os.environ.get('VISUAL') or os.environ.get('EDITOR') or
401 'vim' or 'vi')
402 return editor_command
403

◆ _prompt_for_editor()

_prompt_for_editor ( self)
protected
Ask user to provide editor command

Definition at line 404 of file terminal_utils.py.

404 def _prompt_for_editor(self):
405 """
406 Ask user to provide editor command
407 """
408 # Prompt user for editor command until one is found which exists in PATH
409 while True:
410 new_editor_command_string = input("Use editor: ")
411 new_editor_command_list = shlex.split(new_editor_command_string, posix=True)
412
413 if shutil.which(new_editor_command_list[0]) is not None:
414 self.editor_command_list = new_editor_command_list
415 return self.editor_command_list
416
417 else:
418 print(f"Editor '{self.editor_command_list[0]}' not found in $PATH.")

◆ _remove_comment_lines()

_remove_comment_lines ( self,
a_string )
protected
Remove lines from string that start with a comment character and return modified version.

Definition at line 386 of file terminal_utils.py.

386 def _remove_comment_lines(self, a_string):
387 """
388 Remove lines from string that start with a comment character and return modified version.
389 """
390 if self.comment_string is not None:
391 a_string = "\n".join(
392 [line for line in a_string.splitlines()
393 if not line.startswith(self.comment_string)]).strip()
394 return a_string
395

◆ get_editor_command()

get_editor_command ( self)
Get editor shell command string used for user input.

Definition at line 381 of file terminal_utils.py.

381 def get_editor_command(self):
382 """Get editor shell command string used for user input."""
383 # Construct string from list which holds the executable and args
384 return " ".join(self.editor_command_list)
385

◆ input()

input ( self)
Get user input via editing a temporary file in an editor. If opening the editor fails, fall
back to command line input

Definition at line 358 of file terminal_utils.py.

358 def input(self):
359 """
360 Get user input via editing a temporary file in an editor. If opening the editor fails, fall
361 back to command line input
362 """
363 try:
364 with tempfile.NamedTemporaryFile(mode='r+') as tmpfile:
365 if self.initial_content:
366 tmpfile.write(self.initial_content)
367 tmpfile.flush()
368 subprocess.check_call(self.editor_command_list + [tmpfile.name])
369 tmpfile.seek(0)
370 input_string = tmpfile.read().strip()
371 input_string = self._remove_comment_lines(input_string)
372
373 except (FileNotFoundError, subprocess.CalledProcessError):
374 # If editor not found or other problem with subprocess call, fall back to terminal input
375 print(f"Could not open {self.get_editor_command()}.")
376 print("Try to set your $VISUAL or $EDITOR environment variables properly.\n")
377 sys.exit(1)
378
379 return input_string
380

Member Data Documentation

◆ comment_string

comment_string = commentlines_start_with

string which starts comments in the file

Definition at line 356 of file terminal_utils.py.

◆ editor_command_list

editor_command_list = shlex.split(editor_command_string, posix=True)

command line for the editor, split to separate executable name command line arguments

Definition at line 348 of file terminal_utils.py.

◆ initial_content

initial_content = initial_content

initial content of the editor window

Definition at line 354 of file terminal_utils.py.


The documentation for this class was generated from the following file: