wrapped.vim/python3/wrapped/__init__.py
Ari Archer 55e37255a9
Improve awkward formatting.
Signed-off-by: Ari Archer <ari@ari.lt>
2024-12-25 10:25:48 +02:00

299 lines
10 KiB
Python

#!/usr/bin/env python3
# languages -*- coding: utf-8 -*-
"""Wrapped.vim plugin"""
import datetime
import os
import typing as t
import uuid
import vim
from . import const, processing, util
YEAR: t.Final[int] = datetime.datetime.now(datetime.timezone.utc).year
def setup() -> None:
"""Setup stats"""
vim.command(f"const g:wrapped_stats_id = '{uuid.uuid4()}'")
def wrap_gen_seasonal_nick(hour: int, month: int) -> str:
"""Generate seasonal nickname"""
nick: str
if month in [12, 1, 2]:
nick = "Winter"
elif month in [3, 4, 5]:
nick = "Spring"
elif month in [6, 7, 8]:
nick = "Summer"
elif month in [9, 10, 11]:
nick = "Autumn"
else:
nick = "Intergalactic"
if hour < 6:
nick += " night owl"
elif hour < 12:
nick += " morning sun"
elif hour < 18:
nick += " afternoon delight"
else:
nick += " evening breeze"
return nick
def wrap_logo(g: processing.GeneralStats, total: int) -> None:
"""Print logo"""
c: t.Any = vim.current.buffer # type: ignore
logo: str = f"""
________ ++ ________
/VVVVVVVV\\++++ /VVVVVVVV\\
\\VVVVVVVV/++++++\\VVVVVVVV/ {os.getlogin().title()}'s Vim wrapped of {YEAR}.
|VVVVVV|++++++++/VVVVV/'
|VVVVVV|++++++/VVVVV/' - {wrap_gen_seasonal_nick(g.hour.most_common(1)[0][0], g.month.most_common(1)[0][0])}
+|VVVVVV|++++/VVVVV/'+ - {total} events
+++|VVVVVV|++/VVVVV/'+++++ - {g.adds + g.dels} changes in {g.opens} sessions
+++++|VVVVVV|/VVV___++++++++++ - {len(g.langs)} languages
+++|VVVVVVVVVV/##/ +_+_+_+_ - {(g.adds - g.dels) / (g.adds + g.dels) * 100:.2f}% code growth ratio
+|VVVVVVVVV___ +/#_#,#_#,\\ - {(g.pastes - g.copies) / (g.adds + g.dels) * 100:.2f}% copy-paste ratio
|VVVVVVV//##/+/#/+/#/'/#/
|VVVVV/'+/#/+/#/+/#/ /#/ #VimWrapped{YEAR} #VimInAPod{YEAR}
|VVV/'++/#/+/#/ /#/ /#/ Your year was eventful. Let's see how you did!
'V/' /##//##//##//###/
++
Credits to Erling Westenvik for the ASCII logo
Presented to you with <3 by wrapped.vim"""
for line in logo.splitlines()[1:]:
c.append(line)
def wrap_general(g: processing.GeneralStats, total: int) -> None:
"""Wrap general stats up"""
c: t.Any = vim.current.buffer # type: ignore
tlines: int = g.adds - g.dels
c.append(
f"This year, you have written {g.adds} ({g.invalid_writes} of which were invalid) new lines of code and removed {g.dels} lines in {len(g.langs)} languages, resulting in a {'neutral' if tlines == 0 else ('positive' if tlines > 0 else 'negative')} total of {tlines} lines."
)
c.append(
f"These statistics make your code growth ratio {(g.adds - g.dels) / (g.adds + g.dels) * 100:.2f}%."
)
c.append("")
c.append("Some of your most prominent languages used included:")
lang_total: int = g.langs.total()
for lang, frequency in g.langs.most_common(10):
c.append(f" * {lang.title()} at {frequency / lang_total * 100:.2f}%")
c.append(
f"Also, when editing, you copied code {g.copies} times and pasted code {g.pastes} times, making your copy-paste ratio {(g.pastes - g.copies) / (g.adds + g.dels) * 100:.2f}%."
)
c.append("")
c.append(
f"Your most beloved filenames included {', '.join(f[0] for f in g.files.most_common(5))}. Got a naming convension, huh?"
)
c.append("")
c.append("Timewise it's simple.")
month: t.Tuple[int, int] = g.month.most_common(1)[0]
c.append(
f" 1. You did the most in {const.MONTHS[month[0] - 1]} with {month[1]} events recorded then."
)
try:
h1, h2 = g.hour.most_common(2)
except Exception:
h1 = h2 = g.hour.most_common(1)[0]
c.append(
f" 2. Your most active times were {h1[0]:02}:00 and {h2[0]:02}:00 with {h1[1] + h2[1]} events recorded in total during these times."
)
days: t.List[t.Tuple[int, int]] = g.day.most_common(7)
c.append(
f" 3. Your most active weekday was {const.DAYS[days[0][0]]} at {days[0][1]} events recorded{', with the follow-uppers being...' if len(days) > 1 else '.'}"
)
for day, frequency in days[1:]:
c.append(
f" {const.DAYS[day]:<10} | {frequency} events ({frequency / total * 100:.2f}%)"
)
c.append("Great time management!")
c.append("")
cmds_total: int = g.cmds.total()
c.append(
f"You opened Vim in total of {g.opens} times, then closed it {g.closes} times."
+ (
" (Forgot how to exit vim? :p)"
if g.opens > g.closes
else (" (Lots of tabs? Productive!)" if g.opens < g.closes else "")
)
)
c.append("")
c.append(f"In the mean time you ran {cmds_total} commands, such as:")
for cmd, frequency in g.cmds.most_common(10):
c.append(f" :{cmd} ({frequency / cmds_total * 100:.2f}%)")
c.append(f"Out of which {g.invalid_commands} were invalid.")
def wrap_behaviour(
g: processing.GeneralStats, b: processing.BehaviourStats, total: int
) -> None:
"""Wrap behavioural statistics"""
c: t.Any = vim.current.buffer # type: ignore
c.append(
f"After collecting and analysing {total} events spanning {util.seconds_to_human_readable(int(b.data_range))}, we have concluded your habits."
)
c.append(
f"Amongst those events we found {b.invalid_writes} invalid write events and {b.invalid_commands} invalid command events."
)
c.append("")
days: float = b.data_range / 86400
c.append(
f"You have created {len(b.sessions)} sessions, out of which {b.invalid_session_closes} produced invalid (stray) close events, and/or had {b.invalid_events} invalid (stray) events."
)
c.append("")
c.append(
f"You also spent a whole {util.seconds_to_human_readable(int(b.editing_time))} editing code and other files!"
)
c.append(
f"Moreover, your average session lasts {util.seconds_to_human_readable(b.avg_duration)}, though usually lasting {util.seconds_to_human_readable(b.med_duration)}."
)
c.append("")
c.append("During your coding sessions you tend to do the following the most:")
for evt, freq in sorted(b.evts.items(), key=lambda p: p[1], reverse=True):
c.append(f" * {evt.name} ({freq / total * 100:.2f}%)")
c.append("")
c.append("Lastly, on average, you...")
c.append(f" * Work with {b.avg_sessions} sessions on the daily basis.")
c.append(
f" * Write {g.adds // days:.0f} new lines of code while simultaneously deleting {g.dels // days:.0f} a day."
)
c.append(
f" * Copy {g.copies // days:.0f} lines of code and paste {g.pastes // days:.0f} a day."
)
c.append(f" * Work with {b.avg_langs} languages on average a day.")
c.append("")
c.append("Your journey was impressive. Keep it up!")
def wrap() -> None:
"""Wrap your year in Vim up"""
vim.command("tabnew")
vim.command("setlocal ft=wrapped syntax=wrapped")
vim.command("setlocal noconfirm buftype=nofile")
c: t.Any = vim.current.buffer # type: ignore
for lang, clr in const.LANG_COLOURS.items():
vim.command(
f"call matchadd('Wrapped{clr.capitalize()}', '\\<{lang.capitalize()}\\>')"
)
# Syntax
vim.command(r"call matchadd('WrappedGreen', '\d*.\d*%')")
vim.command(r"call matchadd('WrappedRed', '-\d*.\d*%')")
vim.command(
r"call matchadd('WrappedYellow', '\(, \)\?\(and \)\?\d\+ \(second\|minute\|hour\|day\|month\|year\)s\?')"
)
# Vim logo
vim.command(r"call matchadd('WrappedGreen', 'VVVV*')")
vim.command(r"call matchadd('WrappedGreen', 'V/')")
vim.command(r"call matchadd('WrappedGreen', '##*')")
vim.command(r"call matchadd('WrappedBlue', '#VimWrapped\d\+')")
vim.command(r"call matchadd('WrappedBlue', '#VimInAPod\d\+')")
vim.command(r"call matchadd('WrappedGreen', 'Vimming')")
# Misc
vim.command(r"call matchadd('WrappedGreen', 'written \d* new lines of code')")
vim.command(r"call matchadd('WrappedGreen', 'positive total of \d* lines')")
vim.command(r"call matchadd('WrappedRed', 'removed \d* lines')")
vim.command(r"call matchadd('WrappedRed', 'negative total of -\d* lines')")
vim.command(r"call matchadd('WrappedBlue', 'neutral total of \d* lines')")
vim.command(r"call matchadd('WrappedGray', '=============================*')")
# Credits
vim.command(
r"call matchadd('WrappedGray', 'Credits to Erling Westenvik for the ASCII logo')"
)
vim.command(
r"call matchadd('WrappedGray', 'Presented to you with <3 by wrapped.vim')"
)
bar: util.VimLoadingBar = util.VimLoadingBar(36)
def wrap_end() -> None:
"""Finishing message"""
bar.clear()
c.append("")
c.append(
f"That's all we're able to tell you thus far \u00AF\\\u005F(\u30C4)\u005F/\u00AF Keep Vimming and see you in {YEAR + 1}!"
)
vim.command("set readonly nomodifiable")
vim.command("normal gg")
bar.set_msg("Counting data...").render_status()
total: int = processing.count_of_records_yr()
if total == 0:
bar.clear()
wrap_end()
return
bar.set_total(total)
g: processing.GeneralStats = processing.process_general_statistics(
bar.set_msg("Processing general statistics...")
)
bar.reset()
bar.set_msg("Rendering general info...").render_status()
wrap_logo(g, total)
c.append("")
wrap_general(g, total)
c.append("")
c.append("=" * 128)
c.append("")
bar.reset()
bar.set_total(total)
b: processing.BehaviourStats = processing.process_behaviour_statistics(
bar.set_msg("Processing behavioural statistics...")
)
bar.reset()
bar.set_total(len(b.sessions))
b = processing.process_avg_behaviour_statistics(
bar.set_msg("Processing average statistics..."),
b,
)
bar.reset()
bar.set_msg("Rendering behaviour info...").render_status()
wrap_behaviour(g, b, total)
c.append("")
c.append("=" * 128)
wrap_end()