Add ability to use template with --template (#1667)

* Add ability to pass template path with --template

Update jrnl/args.py

* Fix tests
This commit is contained in:
Aaron Lichtman 2023-03-25 11:47:00 -07:00 committed by GitHub
parent 0725ea6b87
commit a2b217fdfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 217 additions and 68 deletions

View file

@ -11,6 +11,7 @@ from jrnl import time
from jrnl.config import DEFAULT_JOURNAL_KEY
from jrnl.config import get_config_path
from jrnl.config import get_journal_name
from jrnl.config import get_templates_path
from jrnl.config import scope_config
from jrnl.editor import get_text_from_editor
from jrnl.editor import get_text_from_stdin
@ -23,7 +24,7 @@ from jrnl.messages import MsgText
from jrnl.output import print_msg
from jrnl.output import print_msgs
from jrnl.override import apply_overrides
from jrnl.path import expand_path
from jrnl.path import absolute_path
if TYPE_CHECKING:
from argparse import Namespace
@ -123,9 +124,78 @@ def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
return write_mode
def _read_template_file(template_arg: str, template_path_from_config: str) -> str:
"""
This function is called when either a template file is passed with --template, or config.template is set.
The processing logic is:
If --template was not used: Load the global template file.
If --template was used:
* Check $XDG_DATA_HOME/jrnl/templates/template_arg.
* Check template_arg as an absolute / relative path.
If a file is found, its contents are returned as a string.
If not, a JrnlException is raised.
"""
logging.debug(
"Write mode: Either a template arg was passed, or the global config is set."
)
# If filename is unset, we are in this flow due to a global template being configured
if not template_arg:
logging.debug("Write mode: Global template configuration detected.")
global_template_path = absolute_path(template_path_from_config)
try:
with open(global_template_path, encoding="utf-8") as f:
template_data = f.read()
return template_data
except FileNotFoundError:
raise JrnlException(
Message(
MsgText.CantReadTemplateGlobalConfig,
MsgStyle.ERROR,
{
"global_template_path": global_template_path,
},
)
)
else: # A template CLI arg was passed.
logging.debug("Trying to load template from $XDG_DATA_HOME/jrnl/templates/")
jrnl_template_dir = get_templates_path()
logging.debug(f"Write mode: jrnl templates directory: {jrnl_template_dir}")
template_path = jrnl_template_dir / template_arg
try:
with open(template_path, encoding="utf-8") as f:
template_data = f.read()
return template_data
except FileNotFoundError:
logging.debug(
f"Couldn't open {template_path}. Treating --template argument like a local / abs path."
)
pass
normalized_template_arg_filepath = absolute_path(template_arg)
try:
with open(normalized_template_arg_filepath, encoding="utf-8") as f:
template_data = f.read()
return template_data
except FileNotFoundError:
raise JrnlException(
Message(
MsgText.CantReadTemplateCLIArg,
MsgStyle.ERROR,
{
"normalized_template_arg_filepath": normalized_template_arg_filepath,
"jrnl_template_dir": template_path,
},
)
)
def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> None:
"""
Gets input from the user to write to the journal
0. Check for a template passed as an argument, or in the global config
1. Check for input from cli
2. Check input being piped in
3. Open editor if configured (prepopulated with template if available)
@ -134,8 +204,16 @@ def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> N
"""
logging.debug("Write mode: starting")
if args.text:
logging.debug("Write mode: cli text detected: %s", args.text)
if args.template or config["template"]:
logging.debug(f"Write mode: template CLI arg detected: {args.template}")
# Read template file and pass as raw text into the composer
template_data = _read_template_file(args.template, config["template"])
raw = _write_in_editor(config, template_data)
if raw == template_data:
logging.error("Write mode: raw text was the same as the template")
raise JrnlException(Message(MsgText.NoChangesToTemplate, MsgStyle.NORMAL))
elif args.text:
logging.debug(f"Write mode: cli text detected: {args.text}")
raw = " ".join(args.text).strip()
if args.edit:
raw = _write_in_editor(config, raw)
@ -150,9 +228,6 @@ def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> N
if not raw or raw.isspace():
logging.error("Write mode: couldn't get raw text or entry was empty")
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.NORMAL))
if config["template"] and raw == _get_editor_template(config):
logging.error("Write mode: raw text was the same as the template")
raise JrnlException(Message(MsgText.NoChangesToTemplate, MsgStyle.NORMAL))
logging.debug(
'Write mode: appending raw text to journal "%s": %s', args.journal_name, raw
@ -224,45 +299,16 @@ def search_mode(args: "Namespace", journal: Journal, **kwargs) -> None:
_display_search_results(**kwargs)
def _write_in_editor(config: dict, template: str | None = None) -> str:
def _write_in_editor(config: dict, prepopulated_text: str | None = None) -> str:
if config["editor"]:
logging.debug("Write mode: opening editor")
if not template:
template = _get_editor_template(config)
raw = get_text_from_editor(config, template)
raw = get_text_from_editor(config, prepopulated_text)
else:
raw = get_text_from_stdin()
return raw
def _get_editor_template(config: dict, **kwargs) -> str:
logging.debug("Write mode: loading template for entry")
if not config["template"]:
logging.debug("Write mode: no template configured")
return ""
template_path = expand_path(config["template"])
try:
with open(template_path) as f:
template = f.read()
logging.debug("Write mode: template loaded: %s", template)
except OSError:
logging.error("Write mode: template not loaded")
raise JrnlException(
Message(
MsgText.CantReadTemplate,
MsgStyle.ERROR,
{"template": template_path},
)
)
return template
def _has_search_args(args: "Namespace") -> bool:
return any(
(
@ -438,7 +484,7 @@ def _change_time_search_results(
journal: Journal,
old_entries: list["Entry"],
no_prompt: bool = False,
**kwargs
**kwargs,
) -> None:
# separate entries we are not editing
other_entries = _other_entries(journal, old_entries)