<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>notes from /dev/null - python</title><link href="http://yummymelon.com/devnull/" rel="alternate"/><link href="http://yummymelon.com/devnull/feeds/tags/python.atom.xml" rel="self"/><id>http://yummymelon.com/devnull/</id><updated>2025-02-05T11:50:00-08:00</updated><entry><title>Elisp Cheatsheet for Python Programmers</title><link href="http://yummymelon.com/devnull/elisp-cheatsheet-for-python-programmers.html" rel="alternate"/><published>2025-02-05T11:50:00-08:00</published><updated>2025-02-05T11:50:00-08:00</updated><author><name>Charles Choi</name></author><id>tag:yummymelon.com,2025-02-05:/devnull/elisp-cheatsheet-for-python-programmers.html</id><summary type="html">&lt;p&gt;Started a WIP cheatsheet showing translations of Python code to Emacs Lisp. Pushing this out in the wild.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Late last December (although given events of late it feels like a decade ago) I asked on Mastodon the following question:&lt;/p&gt;
&lt;blockquote class="mastodon-embed" data-embed-url="https://sfba.social/@kickingvegas/113723373781728507/embed" style="background: #FCF8FF; border-radius: 8px; border: 1px solid #C9C4DA; margin: 0; max-width: 540px; min-width: 270px; overflow: hidden; padding: 0;"&gt; &lt;a href="https://sfba.social/@kickingvegas/113723373781728507" target="_blank" style="align-items: center; color: #1C1A25; display: flex; flex-direction: column; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', Roboto, sans-serif; font-size: 14px; justify-content: center; letter-spacing: 0.25px; line-height: 20px; padding: 24px; text-decoration: none;"&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 79 75"&gt;&lt;path d="M74.7135 16.6043C73.6199 8.54587 66.5351 2.19527 58.1366 0.964691C56.7196 0.756754 51.351 0 38.9148 0H38.822C26.3824 0 23.7135 0.756754 22.2966 0.964691C14.1319 2.16118 6.67571 7.86752 4.86669 16.0214C3.99657 20.0369 3.90371 24.4888 4.06535 28.5726C4.29578 34.4289 4.34049 40.275 4.877 46.1075C5.24791 49.9817 5.89495 53.8251 6.81328 57.6088C8.53288 64.5968 15.4938 70.4122 22.3138 72.7848C29.6155 75.259 37.468 75.6697 44.9919 73.971C45.8196 73.7801 46.6381 73.5586 47.4475 73.3063C49.2737 72.7302 51.4164 72.086 52.9915 70.9542C53.0131 70.9384 53.0308 70.9178 53.0433 70.8942C53.0558 70.8706 53.0628 70.8445 53.0637 70.8179V65.1661C53.0634 65.1412 53.0574 65.1167 53.0462 65.0944C53.035 65.0721 53.0189 65.0525 52.9992 65.0371C52.9794 65.0218 52.9564 65.011 52.9318 65.0056C52.9073 65.0002 52.8819 65.0003 52.8574 65.0059C48.0369 66.1472 43.0971 66.7193 38.141 66.7103C29.6118 66.7103 27.3178 62.6981 26.6609 61.0278C26.1329 59.5842 25.7976 58.0784 25.6636 56.5486C25.6622 56.5229 25.667 56.4973 25.6775 56.4738C25.688 56.4502 25.7039 56.4295 25.724 56.4132C25.7441 56.397 25.7678 56.3856 25.7931 56.3801C25.8185 56.3746 25.8448 56.3751 25.8699 56.3816C30.6101 57.5151 35.4693 58.0873 40.3455 58.086C41.5183 58.086 42.6876 58.086 43.8604 58.0553C48.7647 57.919 53.9339 57.6701 58.7591 56.7361C58.8794 56.7123 58.9998 56.6918 59.103 56.6611C66.7139 55.2124 73.9569 50.665 74.6929 39.1501C74.7204 38.6967 74.7892 34.4016 74.7892 33.9312C74.7926 32.3325 75.3085 22.5901 74.7135 16.6043ZM62.9996 45.3371H54.9966V25.9069C54.9966 21.8163 53.277 19.7302 49.7793 19.7302C45.9343 19.7302 44.0083 22.1981 44.0083 27.0727V37.7082H36.0534V27.0727C36.0534 22.1981 34.124 19.7302 30.279 19.7302C26.8019 19.7302 25.0651 21.8163 25.0617 25.9069V45.3371H17.0656V25.3172C17.0656 21.2266 18.1191 17.9769 20.2262 15.568C22.3998 13.1648 25.2509 11.9308 28.7898 11.9308C32.8859 11.9308 35.9812 13.492 38.0447 16.6111L40.036 19.9245L42.0308 16.6111C44.0943 13.492 47.1896 11.9308 51.2788 11.9308C54.8143 11.9308 57.6654 13.1648 59.8459 15.568C61.9529 17.9746 63.0065 21.2243 63.0065 25.3172L62.9996 45.3371Z" fill="currentColor"/&gt;&lt;/svg&gt; &lt;div style="color: #787588; margin-top: 16px;"&gt;Post by @kickingvegas@sfba.social&lt;/div&gt; &lt;div style="font-weight: 500;"&gt;View on Mastodon&lt;/div&gt; &lt;/a&gt; &lt;/blockquote&gt;
&lt;script data-allowed-prefixes="https://sfba.social/" async src="https://sfba.social/embed.js"&gt;&lt;/script&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;It seemed like such a thing didn't exist. So I set about trying to remedy this situation and started writing an &lt;a href="https://github.com/kickingvegas/elisp-for-python"&gt;Elisp Cheatsheet for Python Programmers&lt;/a&gt;. It's published as a README.org on GitHub. It's very much a work in progress, but there's enough there to help me translate my working knowledge of Python (as well as Swift and Objective-C) to Elisp. I'm putting this out in the wild because perhaps others will find this similarly useful.&lt;/p&gt;</content><category term="misc"/><category term="emacs"/><category term="python"/><category term="software"/></entry><entry><title>Sometimes you just want the dang thing to pass butter. Introducing launchutil.</title><link href="http://yummymelon.com/devnull/sometimes-you-just-want-the-dang-thing-to-pass-butter-introducing-launchutil.html" rel="alternate"/><published>2023-06-15T18:28:00-07:00</published><updated>2023-06-15T18:28:00-07:00</updated><author><name>Charles Choi</name></author><id>tag:yummymelon.com,2023-06-15:/devnull/sometimes-you-just-want-the-dang-thing-to-pass-butter-introducing-launchutil.html</id><summary type="html">&lt;p&gt;Introducing &lt;a href="https://github.com/kickingvegas/launchutil"&gt;launchutil&lt;/a&gt;, a helper utility to support creating and running a simple macOS &lt;code&gt;launchd&lt;/code&gt; service.&lt;/p&gt;</summary><content type="html">&lt;p&gt;There&amp;rsquo;s an old yet useful feature in macOS where you can get the time &lt;a href="https://support.apple.com/guide/mac-help/change-control-center-settings-mchlad96d366/13.0/mac/13.0"&gt;announced periodically&lt;/a&gt;, typically at the top of the hour.&lt;/p&gt;
&lt;p&gt;One thing though: Turning this feature on means &lt;em&gt;manually&lt;/em&gt; turning it on and having it repeatedly announce until you &lt;em&gt;manually&lt;/em&gt; turn it off. This begs for automation, especially if you want the time announced only during working hours (say 9am to 5pm). Since macOS is my daily driver, this is where we talk about &lt;a href="https://support.apple.com/guide/terminal/script-management-with-launchd-apdc6c1077b-5d5d-4d35-9c19-60f2397b2369/mac"&gt;launchd&lt;/a&gt;, which since Mac OS X 10.4 has been the system process that manages daemons and agents. There&amp;rsquo;s plenty of posts describing it and how &lt;code&gt;launchd&lt;/code&gt; works (see references below) so I won&amp;rsquo;t go over that here. What I will say though is that working with &lt;code&gt;launchd&lt;/code&gt; via the &lt;code&gt;launchctl&lt;/code&gt; command line utility is a PITA.&lt;/p&gt;
&lt;p&gt;By and large my pain points in using &lt;code&gt;launchctl&lt;/code&gt; are this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Creating a launch script means you need to write it in XML, following a schema that I find impossible to remember.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Installing the launch script means you need to work with two different directories: 1) where you create the launch script and 2) where you need to install it (typically &lt;code&gt;$HOME/Library/LaunchAgents&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Managing the launch script (that is starting, stopping, getting its status) using &lt;code&gt;launchctl&lt;/code&gt; requires different references to the launch script/service which means different command line arguments to access the same thing. This makes the ergonomics of using &lt;code&gt;launchctl&lt;/code&gt; &lt;em&gt;punishing&lt;/em&gt;, especially when debugging the launch script.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Having worked with macOS for well over a decade, I&amp;rsquo;ve felt the woe of writing a number of launch scripts and encountering all of the pain points above. So I&amp;rsquo;ve decided to do something about it.&lt;/p&gt;
&lt;p&gt;Introducing &lt;a href="https://github.com/kickingvegas/launchutil"&gt;launchutil&lt;/a&gt;, a helper utility to support creating and running a simple macOS &lt;code&gt;launchd&lt;/code&gt; service. It is written in Python and is expressly designed to have the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy creation of a working XML file for daily scheduling that you can edit to taste.&lt;/li&gt;
&lt;li&gt;Uses the launch script name as the reference to the job/service you want to run. (You can still use the service name though.)&lt;/li&gt;
&lt;li&gt;Easy installation and removal of the launch script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s see &lt;code&gt;launchutil&lt;/code&gt; at work: Imagine that you want to create a job that invokes the &lt;code&gt;say&lt;/code&gt; command to say &amp;ldquo;hello there&amp;rdquo; at 14:00 (2pm) and 15:15 (3:15 pm) everyday. The command invocation would look like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--program&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/say&lt;span class="w"&gt; &lt;/span&gt;--program-arguments&lt;span class="w"&gt; &lt;/span&gt;hello&lt;span class="w"&gt; &lt;/span&gt;there&lt;span class="w"&gt; &lt;/span&gt;--daily&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:00&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;:15&lt;span class="w"&gt; &lt;/span&gt;--execute&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Alternately, you can use short arguments to achieve the same result.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/say&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;hello&lt;span class="w"&gt; &lt;/span&gt;there&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:00&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;:15&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Running the above generates the launch script named &lt;code&gt;com.yummymelon.sayhello.plist&lt;/code&gt; whose contents are shown below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;
&lt;span class="normal"&gt;30&lt;/span&gt;
&lt;span class="normal"&gt;31&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.yummymelon.sayhello&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Program&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/bin/say&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/bin/say&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;hello&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;there&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StartCalendarInterval&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;14&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;15&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;15&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that the launch script file name is built off the service name. &lt;code&gt;launchutil&lt;/code&gt; relies on this convention to support the command-line ergonomics to &lt;em&gt;infer&lt;/em&gt; the service name from the launch script file name and vice-versa.&lt;/p&gt;
&lt;p&gt;Installing the launch script into the default directory &lt;code&gt;$HOME/Library/LaunchAgents&lt;/code&gt; is achieved with the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello.plist&lt;span class="w"&gt; &lt;/span&gt;-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To start the service:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello.plist&lt;span class="w"&gt; &lt;/span&gt;-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To get the status of the service:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello.plist&lt;span class="w"&gt; &lt;/span&gt;-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To stop the service:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello.plist&lt;span class="w"&gt; &lt;/span&gt;-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To uninstall the service:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;launchutil&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;com.yummymelon.sayhello.plist&lt;span class="w"&gt; &lt;/span&gt;-x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that in all the above commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No navigation or references to the installed directory.&lt;/li&gt;
&lt;li&gt;Only reference the launch script file name (or service name).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Say Time at the Top of the Hour&lt;/h1&gt;
&lt;p&gt;So as promised at the start of this post, a &lt;code&gt;launchutil&lt;/code&gt; example that will announce the time daily from 9am to 5pm can be found at &lt;a href="https://github.com/kickingvegas/launchutil/tree/main/examples"&gt;https://github.com/kickingvegas/launchutil/tree/main/examples&lt;/a&gt;  &lt;/p&gt;
&lt;h1&gt;Getting launchutil&lt;/h1&gt;
&lt;p&gt;If you&amp;rsquo;ve made all the way here and are still interested, you can get &lt;code&gt;launchutil&lt;/code&gt; at &lt;a href="https://github.com/kickingvegas/launchutil"&gt;https://github.com/kickingvegas/launchutil&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the sake of simplicity, there is no &lt;a href="https://pypi.org/project/pip/"&gt;pip · PyPI&lt;/a&gt; packaging; just install the single file Python 3 script into your &lt;code&gt;bin&lt;/code&gt; directory. It has no dependencies to any packages outside of the basic macOS install.&lt;/p&gt;
&lt;p&gt;If you have any feedback, please let me know at the GitHub &lt;a href="https://github.com/kickingvegas/launchutil/discussions"&gt;discussion&lt;/a&gt; board for &lt;code&gt;launchutil&lt;/code&gt;. &lt;/p&gt;
&lt;h1&gt;References&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eclecticlight.co/2021/09/13/running-software-automatically-using-launchd/"&gt;Running software automatically using launchd – The Eclectic Light Company&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/"&gt;Launchctl 2.0 Syntax | Babo D&amp;rsquo;s Corner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eclecticlight.co/2023/03/11/whos-managing-my-apps/"&gt;Who’s managing my apps? – The Eclectic Light Company&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leancrew.com/all-this/2009/08/launchd-as-a-replacement-for-at/"&gt;Launchd as a replacement for at - All this&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="misc"/><category term="python"/><category term="macos"/><category term="automation"/></entry><entry><title>BrowseAudit</title><link href="http://yummymelon.com/devnull/browseaudit.html" rel="alternate"/><published>2013-03-20T10:48:00-07:00</published><updated>2013-03-20T10:48:00-07:00</updated><author><name>Charles Choi</name></author><id>tag:yummymelon.com,2013-03-20:/devnull/browseaudit.html</id><summary type="html">&lt;p&gt;A Python script to read your OS X Safari history file and privately list your most frequently visited website domains. Output includes HTML, CSV, and listing to stdout.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="http://kickingvegas.github.io/BrowseAudit/"&gt;BrowseAudit&lt;/a&gt; is a Python script to read your OS X Safari history file and privately list your most frequently visited website domains. Output includes HTML, CSV, and listing to stdout.  &lt;/p&gt;
&lt;p&gt;I wrote this over the weekend, pretty much to procrastinate on doing my taxes. That said, it has the purpose of showing you where you're spending too much time with when you're on the web. &lt;/p&gt;
&lt;p&gt;Surprise yourself today.&lt;/p&gt;</content><category term="misc"/><category term="Python"/><category term="Web"/></entry><entry><title>Find Yummy Melon here.</title><link href="http://yummymelon.com/devnull/find-yummy-melon-here-30.html" rel="alternate"/><published>2009-09-17T19:30:00-07:00</published><updated>2009-09-17T19:30:00-07:00</updated><author><name>Charles Choi</name></author><id>tag:yummymelon.com,2009-09-17:/devnull/find-yummy-melon-here-30.html</id><summary type="html">&lt;p&gt;Jim Baker talk on optimization @slide&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img src="http://yummymelon.com/devnull/images/LmO1mEht83U07knMkGrgB3O5ByE5o9mOfGG9jxDRsRk5t75RVUttTdpYp1yY/aqui_2009-09-17_1925.png"/&gt;&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Jim Baker talk on optimization @slide #jython #python &lt;br /&gt;&lt;a href="http://maps.google.com/maps?q=Yummy%20Melon+7:25+PM+PDT@37.781950,-122.391844"&gt;Yummy Melon Location&lt;/a&gt; 7:25 PM PDT&lt;/p&gt;&lt;p align="right"&gt;&lt;a href="http://maps.blackberry.com?lat=37.781950&amp;amp;lon=-122.391844&amp;amp;z=3&amp;amp;label=Yummy+Melon+7:26+PM+PDT"&gt;Location (BlackBerry 4.5+ friendly)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Sent using &lt;a href="http://www.yummymelon.com/aqui"&gt;Aqu&amp;iacute;&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;p /&gt;&lt;div&gt;&lt;p /&gt;&lt;/div&gt;</content><category term="misc"/><category term="Software"/><category term="Python"/></entry></feed>