{"id":1434,"date":"2014-07-20T21:30:54","date_gmt":"2014-07-21T04:30:54","guid":{"rendered":"http:\/\/zackmdavis.net\/blog\/?p=1434"},"modified":"2014-07-20T21:38:10","modified_gmt":"2014-07-21T04:38:10","slug":"growl","status":"publish","type":"post","link":"http:\/\/zackmdavis.net\/blog\/2014\/07\/growl\/","title":{"rendered":"Growl"},"content":{"rendered":"<p>Dear reader, imagine you have an idea for a work of prose that you want to have finished by Election Day for reasons which will become clear later, and you're not sure how long it should end up being, but you think maybe around twelve thousand words. When considering what you can do to ensure that this feat will actually be accomplished, it occurs to you that you could start writing now. <em>Or<\/em>\u2014<\/p>\n<p><!--more--><\/p>\n<p><em>Or you could design a script to make desktop notifications about how much more writing you have to do!<\/em> (<em>Maybe<\/em> you could even put it in a cronjob so that it would nag you to write <em>automatically<\/em>!)<\/p>\n<p>Well, I already made it for you (unless your Linux distribution doesn't use <code>notify-send<\/code> or you're on a Mac or something).<\/p>\n<pre><code>#!\/usr\/bin\/env python3\r\n\r\nimport argparse\r\nimport subprocess\r\nfrom datetime import datetime\r\n\r\narg_parser = argparse.ArgumentParser()\r\narg_parser.add_argument(&quot;filename&quot;, help=&quot;path to file of draft&quot;)\r\narg_parser.add_argument(&quot;goal&quot;, type=int, help=&quot;goal wordcount&quot;)\r\narg_parser.add_argument(&quot;deadline&quot;, help=&quot;deadline in YYYY-MM-DD format&quot;)\r\nargs = arg_parser.parse_args()\r\n\r\ntoday = datetime.today()\r\nfilename = args.filename\r\ngoal = args.goal\r\ndeadline = datetime.strptime(args.deadline, &quot;%Y-%m-%d&quot;)\r\n\r\ndef nag_message():\r\n    progress = int(subprocess.check_output([&quot;wc&quot;, filename, &quot;-w&quot;]).split()[0])\r\n    to_go = goal - progress\r\n    days_remaining = (deadline - today).days\r\n    to_go_per_day = to_go \/ days_remaining\r\n    proportion = progress \/ goal\r\n    return &quot;\\n&quot;.join(\r\n        &quot;{}: {:.2f}&quot;.format(k.replace(&quot;_&quot;, &quot; &quot;), v) for k, v in locals().items()\r\n    )\r\n\r\nsubprocess.check_output([&quot;notify-send&quot;, &quot;writing progress&quot;, nag_message()])<\/code><\/pre>\n<p><a href=\"http:\/\/zackmdavis.net\/blog\/wp-content\/uploads\/2014\/07\/wordcount_notification.png\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/zackmdavis.net\/blog\/wp-content\/uploads\/2014\/07\/wordcount_notification.png\" alt=\"My Wordcount Notification\" width=\"214\" height=\"214\" class=\"size-full wp-image-1435\" srcset=\"http:\/\/zackmdavis.net\/blog\/wp-content\/uploads\/2014\/07\/wordcount_notification.png 214w, http:\/\/zackmdavis.net\/blog\/wp-content\/uploads\/2014\/07\/wordcount_notification-150x150.png 150w\" sizes=\"(max-width: 214px) 100vw, 214px\" \/><\/a><\/p>\n<p><em>You're welcome<\/em>. Now get back to work.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dear reader, imagine you have an idea for a work of prose that you want to have finished by Election Day for reasons which will become clear later, and you're not sure how long it should end up being, but &hellip; <a href=\"http:\/\/zackmdavis.net\/blog\/2014\/07\/growl\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[12],"tags":[24,47,21],"_links":{"self":[{"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/posts\/1434"}],"collection":[{"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/comments?post=1434"}],"version-history":[{"count":8,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/posts\/1434\/revisions"}],"predecessor-version":[{"id":1443,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/posts\/1434\/revisions\/1443"}],"wp:attachment":[{"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/media?parent=1434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/categories?post=1434"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/zackmdavis.net\/blog\/wp-json\/wp\/v2\/tags?post=1434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}