77 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| .. moduleauthor:: Eric Torres
 | |
| .. module:: file_scripts.editor
 | |
|     :synopsis: Helper functions for interacting with system editors
 | |
| """
 | |
| # ========== Imports ==========
 | |
| import os
 | |
| import shutil
 | |
| 
 | |
| from pathlib import Path
 | |
| 
 | |
| # ========== Constants ==========
 | |
| SUDO_COMMAND = "sudo"
 | |
| 
 | |
| # ========== Functions ==========
 | |
| def select_editor(override=None):
 | |
|     """Return a canonical path to an editor.
 | |
| 
 | |
|     Select an editor from one of:
 | |
|     * -e, --editor
 | |
|     * $EDITOR
 | |
|     * Default of vim
 | |
| 
 | |
|     In this order
 | |
| 
 | |
|     If an editor cannot be resolved, then a FileNotFoundError is raised instead.
 | |
| 
 | |
|     :param override: argument to override an editor
 | |
|     :returns: path to one of these editors
 | |
|     :rtype: str
 | |
|     :raises: FileNotFoundError if an editor could not be resolved
 | |
|     """
 | |
|     editor = None
 | |
| 
 | |
|     if override is not None:
 | |
|         editor = shutil.which(override)
 | |
|     elif "EDITOR" in os.environ:
 | |
|         editor = shutil.which(os.environ.get("EDITOR"))
 | |
|     elif shutil.which("vim") is not None:
 | |
|         editor = shutil.which("vim")
 | |
| 
 | |
|     if editor is None:
 | |
|         raise FileNotFoundError("An editor could not be resolved")
 | |
| 
 | |
|     return editor
 | |
| 
 | |
| 
 | |
| def gen_editor_cmd(editor, filename):
 | |
|     """Generate a command line to run for editing a file based on
 | |
|     permissions. This command line is suitable for passing to
 | |
|     subprocess.run().
 | |
| 
 | |
|     This command does not pass extra options to the editor, hence
 | |
|     there are no arguments to pass for options.
 | |
| 
 | |
|     Conditions
 | |
|     ----------
 | |
|     * Path exists: use normal command
 | |
|     * Path does not exist: use normal command
 | |
|     * Path exists but is not readable by current process: use SUDO_COMMAND
 | |
| 
 | |
| 
 | |
|     :param editor: path of editor
 | |
|     :type editor: str or path-like object
 | |
|     :param filename: path/name of file to edit
 | |
|     :type filename: str or path-like object
 | |
|     :returns: command to execute to edit file
 | |
|     :rtype: list
 | |
|     """
 | |
|     # Possible for a race condition to occur here
 | |
|     # What happens if the file or its metadata changes?
 | |
|     path = Path(filename)
 | |
|     if path.exists() and not os.access(path, os.W_OK):
 | |
|         return [SUDO_COMMAND, "--edit", filename]
 | |
|     else:
 | |
|         return [editor, filename]
 |