elog -> evlog

This commit is contained in:
Jeffrey Serio 2025-04-19 11:03:47 -05:00
parent 154280cec9
commit 8e23b695bb
3 changed files with 100 additions and 96 deletions

View File

@ -1,31 +1,31 @@
# daily-event-logger
# evlog
This is a little utility I use for logging my daily activities and events. It is written in Python.
## Install
```bash
python3 -m pip install daily-event-logger
pipx install evlog
```
## Usage
To change the directory where elogs are stored, set a shell environment variable ELOG_DIR. To make this change permament, set the following in your shell configuration:
To change the directory where evlogs are stored, set a shell environment variable EVLOG_DIR. To make this change permament, set the following in your shell configuration:
```bash
export ELOG_DIR="/path/to/elog/dir"
export EVLOG_DIR="/path/to/evlog/dir"
```
Otherwise, the default elog directory will be `~/elogs`.
Otherwise, the default evlog directory will be `~/evlogs`.
To get started, add your first elog entry! This will create a JSON file under your elog directory for the day and ensure the elog directory exists. E.g.:
To get started, add your first evlog entry! This will create a JSON file under your evlog directory for the day and ensure the evlog directory exists. E.g.:
```bash
elog add -m "Started new elog. Yay!"
evlog add -m "Started new evlog. Yay!"
```
```bash
usage: elog [-h] [-v] {add,edit,rm,ls,lsfiles,search} ...
usage: evlog [-h] [-v] {add,edit,rm,ls,lsfiles,search} ...
positional arguments:
{add,edit,rm,ls,lsfiles,search}

174
evlog.py
View File

@ -17,50 +17,50 @@ from rich.traceback import install
install(show_locals=True)
VERSION = "0.1.5"
VERSION = "0.1.6"
default_date = dt.date.today().strftime("%Y-%m-%d")
ELOG_DIR = os.getenv("ELOG_DIR")
if ELOG_DIR is None:
elog_dir = Path("~/elogs").expanduser()
EVLOG_DIR = os.getenv("EVLOG_DIR")
if EVLOG_DIR is None:
evlog_dir = Path("~/evlogs").expanduser()
else:
elog_dir = Path(ELOG_DIR)
evlog_dir = Path(EVLOG_DIR)
def elog_init(filename):
"""Initialize elog file and directory, if necessary.
def evlog_init(filename):
"""Initialize evlog file and directory, if necessary.
elog_dir is taken from the current shell's ELOG_DIR environment variable, or else it defaults to
~/elogs.
evlog_dir is taken from the current shell's EVLOG_DIR environment variable, or else it defaults to
~/evlogs.
"""
elog_file = elog_dir.joinpath(filename).with_suffix(".json")
evlog_file = evlog_dir.joinpath(filename).with_suffix(".json")
elog_dir.mkdir(exist_ok=True)
elog_file.touch()
evlog_dir.mkdir(exist_ok=True)
evlog_file.touch()
json_array = []
with open(elog_file, "w") as ef:
with open(evlog_file, "w") as ef:
json.dump(json_array, ef)
def elog_list(args):
"""List elog entries.
def evlog_list(args):
"""List evlog entries.
Lists elog entries for provided timestamp range and/or elog file
Lists evlog entries for provided timestamp range and/or evlog file
"""
if args.file:
selected_elog_file = elog_dir.joinpath(args.file)
selected_evlog_file = evlog_dir.joinpath(args.file)
else:
selected_elog_file = elog_dir.joinpath(default_date + "_elog").with_suffix(
selected_evlog_file = evlog_dir.joinpath(default_date + "_evlog").with_suffix(
".json"
)
if not selected_elog_file.exists():
exit("elog file %s not found. Are you sure it exists?" % selected_elog_file)
if not selected_evlog_file.exists():
exit("evlog file %s not found. Are you sure it exists?" % selected_evlog_file)
if not args.start:
ts_from = selected_elog_file.stem[:10] + " 00:00:00"
ts_from = selected_evlog_file.stem[:10] + " 00:00:00"
else:
dt.datetime.strptime(args.start, "%Y-%m-%d %H:%M:%S")
ts_from = args.start
@ -71,7 +71,7 @@ def elog_list(args):
dt.datetime.strptime(args.end, "%Y-%m-%d %H:%M:%S")
ts_to = args.end
with open(selected_elog_file, "r") as ef:
with open(selected_evlog_file, "r") as ef:
json_data = json.load(ef)
table = Table(style="#5f00ff", header_style="bold", box=box.ROUNDED)
@ -87,12 +87,12 @@ def elog_list(args):
console.print(table)
def elog_list_files(args):
"""List all elog files.
def evlog_list_files(args):
"""List all evlog files.
Lists all elog files currently present in elog directory.
Lists all evlog files currently present in evlog directory.
"""
for file in sorted(elog_dir.iterdir()):
for file in sorted(evlog_dir.iterdir()):
if file.is_file():
if args.absolute:
print(file)
@ -100,18 +100,18 @@ def elog_list_files(args):
print(file.name)
def elog_search(args):
def evlog_search(args):
"""Search for a string.
Searches all elog files and prints found matches.
Searches all evlog files and prints found matches.
"""
found_entries = list()
elog_list = [file.name for file in elog_dir.iterdir()]
evlog_list = [file.name for file in evlog_dir.iterdir()]
console = Console()
for file in elog_list:
with open(elog_dir.joinpath(file), "r") as ef:
for file in evlog_list:
with open(evlog_dir.joinpath(file), "r") as ef:
json_data = json.load(ef)
for entry in json_data:
if args.word in entry["message"]:
@ -126,14 +126,14 @@ def elog_search(args):
)
else:
console.print(
"[bold yellow]{0}[/bold yellow] was not found in any of the elog files".format(
"[bold yellow]{0}[/bold yellow] was not found in any of the evlog files".format(
args.word
)
)
def elog_sort(file):
"""Sort elog entries.
def evlog_sort(file):
"""Sort evlog entries.
Entries are sorted by provided timestamp.
"""
@ -154,7 +154,7 @@ def validate_json(file):
Call jsonschema.validate on `file`.
"""
elog_schema = {
evlog_schema = {
"type": "array",
"properties": {
"timestamp": {"type": "string"},
@ -166,17 +166,17 @@ def validate_json(file):
json_data = json.load(ef)
try:
validate(instance=json_data, schema=elog_schema)
validate(instance=json_data, schema=evlog_schema)
except jsonschema.ValidationError as err:
print("Invalid JSON detected on %s" % file)
print(err)
def elog_append(args):
def evlog_append(args):
"""
Append a new elog entry to the elog file.
Append a new evlog entry to the evlog file.
Use elog file indicated by provided timestamp, or else use the elog file for current day.
Use evlog file indicated by provided timestamp, or else use the evlog file for current day.
"""
if not args.timestamp:
ts = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@ -184,64 +184,68 @@ def elog_append(args):
dt.datetime.strptime(args.timestamp, "%Y-%m-%d %H:%M:%S")
ts = args.timestamp
elog_filename = ts[:10] + "_elog"
elog_file = elog_dir.joinpath(elog_filename).with_suffix(".json")
evlog_filename = ts[:10] + "_evlog"
evlog_file = evlog_dir.joinpath(evlog_filename).with_suffix(".json")
if not elog_file.exists():
elog_init(elog_file)
if not evlog_file.exists():
evlog_init(evlog_file)
entry = {"timestamp": ts, "message": args.message}
with open(elog_file, "r+") as ef:
with open(evlog_file, "r+") as ef:
json_data = json.load(ef)
json_data.append(entry)
ef.seek(0)
json.dump(json_data, ef, indent=4)
elog_sort(elog_file)
validate_json(elog_file)
evlog_sort(evlog_file)
validate_json(evlog_file)
def elog_edit(args):
"""Edit elog entry at provided index argument."""
def evlog_edit(args):
"""Edit evlog entry at provided index argument."""
if args.file:
elog_file = elog_dir.joinpath(args.file)
evlog_file = evlog_dir.joinpath(args.file)
else:
elog_file = elog_dir.joinpath(default_date + "_elog").with_suffix(".json")
evlog_file = evlog_dir.joinpath(default_date + "_evlog").with_suffix(".json")
if not elog_file.exists():
exit("elog file not found. Please run 'elog append' to start a new elog file.")
if not evlog_file.exists():
exit(
"evlog file not found. Please run 'evlog append' to start a new evlog file."
)
with open(elog_file, "r+") as ef:
with open(evlog_file, "r+") as ef:
json_data = json.load(ef)
json_data[args.index]["message"] = args.message
ef.seek(0)
json.dump(json_data, ef, indent=4)
validate_json(elog_file)
validate_json(evlog_file)
def elog_remove(args):
"""Remove an elog entry at provided index argument."""
def evlog_remove(args):
"""Remove an evlog entry at provided index argument."""
if args.file:
elog_file = elog_dir.joinpath(args.file)
evlog_file = evlog_dir.joinpath(args.file)
else:
elog_file = elog_dir.joinpath(default_date + "_elog").with_suffix(".json")
evlog_file = evlog_dir.joinpath(default_date + "_evlog").with_suffix(".json")
if not elog_file.exists():
exit("elog file not found. Please run 'elog append' to start a new elog file.")
if not evlog_file.exists():
exit(
"evlog file not found. Please run 'evlog append' to start a new evlog file."
)
with open(elog_file, "r") as ef:
with open(evlog_file, "r") as ef:
json_data = json.load(ef)
json_data.pop(args.index)
with open(elog_file, "w") as ef:
with open(evlog_file, "w") as ef:
json.dump(json_data, ef, indent=4)
validate_json(elog_file)
validate_json(evlog_file)
parser = argparse.ArgumentParser(prog="elog")
parser = argparse.ArgumentParser(prog="evlog")
parser.add_argument(
"-v",
"--version",
@ -251,14 +255,14 @@ parser.add_argument(
)
subparsers = parser.add_subparsers()
add_parser = subparsers.add_parser("add", description="Add an elog entry")
add_parser = subparsers.add_parser("add", description="Add an evlog entry")
add_parser.add_argument(
"-t",
"--timestamp",
required=False,
type=str,
action="store",
help="Timestamp for elog entry: str",
help="Timestamp for evlog entry: str",
)
add_parser.add_argument(
"-m",
@ -266,18 +270,18 @@ add_parser.add_argument(
required=True,
type=str,
action="store",
help="Message for elog entry: str",
help="Message for evlog entry: str",
)
add_parser.set_defaults(func=elog_append)
add_parser.set_defaults(func=evlog_append)
edit_parser = subparsers.add_parser("edit", description="Edit an elog entry")
edit_parser = subparsers.add_parser("edit", description="Edit an evlog entry")
edit_parser.add_argument(
"-i",
"--index",
required=True,
type=int,
action="store",
help="Index of elog entry: int",
help="Index of evlog entry: int",
)
edit_parser.add_argument(
"-m",
@ -285,7 +289,7 @@ edit_parser.add_argument(
required=True,
type=str,
action="store",
help="New message for elog entry: str",
help="New message for evlog entry: str",
)
edit_parser.add_argument(
"-f",
@ -293,18 +297,18 @@ edit_parser.add_argument(
required=False,
type=str,
action="store",
help="elog file to edit. Ex: 2022-10-02_elog.json",
help="evlog file to edit. Ex: 2022-10-02_evlog.json",
)
edit_parser.set_defaults(func=elog_edit)
edit_parser.set_defaults(func=evlog_edit)
rm_parser = subparsers.add_parser("rm", description="Remove an elog entry")
rm_parser = subparsers.add_parser("rm", description="Remove an evlog entry")
rm_parser.add_argument(
"-i",
"--index",
required=True,
type=int,
action="store",
help="Index of elog entry: int",
help="Index of evlog entry: int",
)
rm_parser.add_argument(
"-f",
@ -312,11 +316,11 @@ rm_parser.add_argument(
required=False,
type=str,
action="store",
help="elog file to remove from. Ex: 2022-10-02_elog.json",
help="evlog file to remove from. Ex: 2022-10-02_evlog.json",
)
rm_parser.set_defaults(func=elog_remove)
rm_parser.set_defaults(func=evlog_remove)
ls_parser = subparsers.add_parser("ls", description="List elog entries")
ls_parser = subparsers.add_parser("ls", description="List evlog entries")
ls_parser.add_argument(
"-s",
"--start",
@ -341,27 +345,27 @@ ls_parser.add_argument(
required=False,
type=str,
action="store",
help="elog file to view. Ex: 2022-10-02_elog.json",
help="evlog file to view. Ex: 2022-10-02_evlog.json",
)
ls_parser.set_defaults(func=elog_list)
ls_parser.set_defaults(func=evlog_list)
ls_files_parser = subparsers.add_parser("lsfiles", description="List all elog files")
ls_files_parser = subparsers.add_parser("lsfiles", description="List all evlog files")
ls_files_parser.add_argument(
"-a",
"--absolute",
required=False,
action="store_true",
help="List the absolute paths of the elog files",
help="List the absolute paths of the evlog files",
)
ls_files_parser.set_defaults(func=elog_list_files)
ls_files_parser.set_defaults(func=evlog_list_files)
search_parser = subparsers.add_parser(
"search", description="Search for keywords in elog files"
"search", description="Search for keywords in evlog files"
)
search_parser.add_argument(
"-w", "--word", required=True, type=str, action="store", help="Word to search for"
)
search_parser.set_defaults(func=elog_search)
search_parser.set_defaults(func=evlog_search)
def main():

View File

@ -1,6 +1,6 @@
[project]
name = "evlog"
version = "0.1.5"
version = "0.1.6"
authors = [
{ name="Jeffrey Serio", email="hyperreal@moonshadow.dev" },
]
@ -18,8 +18,8 @@ dependencies = ["jsonschema>=4.17.0", "rich>=12.6.0"]
elog = "evlog:main"
[project.urls]
Homepage = "https://git.hyperreal.coffee/hyperreal/daily-event-logger"
Issues = "https://git.hyperreal.coffee/hyperreal/daily-event-logger/issues"
Homepage = "https://git.hyperreal.coffee/hyperreal/evlog"
Issues = "https://git.hyperreal.coffee/hyperreal/evlog/issues"
[build-system]
requires = ["hatchling"]