<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Notes · Pablo Stafforini</title><link>https://stafforini.com/notes/</link><description/><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sun, 12 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://stafforini.com/notes/index.xml" rel="self" type="application/rss+xml"/><item><title>Wild animal welfare: a bibliography</title><link>https://stafforini.com/notes/wild-animal-welfare-a-bibliography/</link><pubDate>Thu, 06 Jun 2013 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/wild-animal-welfare-a-bibliography/</guid><description>&lt;![CDATA[<p>This bibliography is primarily based on<a href="/works/horta-2012-publications-in-english/">Publications in English on the suffering of animals in the wild and the ways to help them</a>,<a href="/works/dorado-2015-ethical-interventions-wild/">Ethical interventions in the wild</a>, and the research that<a href="http://www.vallinder.se/">Aron Vallinder</a> and I did for a paper on wild animal welfare that we once planned to write. If you know of relevant material not included in the list below, please<a href="/notes/contact/">let me know</a>.</p><hr><ul><li>Elisa Aaltola,<a href="/works/aaltola-2010-animal-ethics-argument/">Animal ethics and the argument from absurdity</a>,<em>Environmental values</em>, vol. 19, no. 1, 2010, pp. 79–98</li><li>Peter Alward,<a href="/works/alward-2000-naive-argument-moral/">The naïve argument against moral vegetarianism</a>,<em>Environmental values</em>, vol. 9, no. 1, 2000, pp. 81–89</li><li>David Benatar,<a href="/works/benatar-2001-why-naive-argument/">Why the naïve argument against moral vegetarianism really is naïve</a>,<em>Environmental values</em>, vol. 10, no. 2001, 2001, pp. 103–112</li><li>Bernice Bovenkerk et al.,<a href="/works/bovenkerk-2003-act-not-act/">To act or not to act? sheltering animals from the wild: A pluralistic account of a conflict between animal and environmental ethics</a>,<em>Ethics, Place & Environment</em>, vol. 6, no. 1, 2003, pp. 13–26</li><li>Stijn Bruers,<a href="/works/bruers-2015-predation-procreation-problems/">The predation and procreation problems: Persistent intuitions gone wild</a>,<em>Relations</em>, no. 3, 2015, pp. 85–91</li><li>Max Carpendale,<a href="/works/carpendale-2015-welfare-biology-extension/">Welfare biology as an extension of biology: interview with Yew-Kwang Ng</a>,<em>Relations</em>, vol. 3, no. 2, 2015, pp. 197–202</li><li>Stephen R. L. Clark,<a href="/works/clark-1979-rights-wild-things/">The rights of wild things</a>,<em>Inquiry</em>, vol. 22, no. 1-4, 1979, pp. 171–188</li><li>Matthew Clarke and Yew-Kwang Ng,<a href="/works/clarke-2006-population-dynamics-animal/">Population dynamics and animal welfare: issues raised by the culling of kangaroos in Puckapunyal</a>,<em>Social choice and welfare</em>, vol. 27, no. 2, 2006, pp. 407–422</li><li>Tyler Cowen,<a href="/works/cowen-2003-policing-nature/">Policing nature</a>,<em>Environmental ethics</em>, vol. 25, no. 2, 2003, pp. 169–182</li><li>Luciano Carlos Cunha,<a href="/works/cunha-2015-if-natural-entities/">If natural entities have intrinsic value, should we then abstain from helping animals who are victims of natural processes?</a>,<em>Relations</em>, no. 3, 2015, pp. 51–63</li><li>Richard Dawkins,<a href="/works/dawkins-1995-god-utility-function/">God's utility function</a>,<em>Scientific American</em>, vol. 273, no. 5, 1995, pp. 80–85</li><li>Sue Donaldson and Will Kymlicka,<a href="/works/donaldson-2011-zoopolis-political-theory/"><em>Zoopolis: A political theory of animal rights</em></a>, Oxford, 2011</li><li>Sue Donaldson and Will Kymlicka,<a href="/works/donaldson-2013-defense-animal-citizens/">A Defense of Animal Citizens and Sovereigns</a>,<em>Law, Ethics and Philosophy</em>, vol. 1, 2013, pp. 143–160</li><li>Daniel Dorado,<a href="/works/dorado-2015-ethical-interventions-wild/">Ethical interventions in the wild: An annotated bibliography</a>,<em>Relations</em>, vol. 3, no. 3, 2015, pp. 219–238</li><li>Rainer Ebert and Tibor R. Machan,<a href="/works/ebert-2012-innocent-threats-problem/">Innocent threats and the moral problem of carnivorous animals</a>,<em>Journal of applied philosophy</em>, vol. 29, no. 2, 2012, pp. 146–159</li><li>Jennifer Everett,<a href="/works/everett-2001-environmental-ethics-animal/">Environmental ethics, animal welfarism, and the problem of predation: a Bambi lover's respect for nature</a>,<em>Ethics & the environment</em>, vol. 6, no. 1, 2001, pp. 42–67</li><li>Catia Faria and Eze Paez,<a href="/works/faria-2015-animals-need-problem/">Animals in need: The problem of wild animal suffering and intervention in nature</a>,<em>Relations: Beyond Anthropocentrism</em>, vol. 3, no. 1, 2015, pp. 7–13</li><li>Catia Faria,<a href="/works/faria-2015-making-difference-behalf/">Making a difference on behalf of animals living in the wild: Interview with Jeff McMahan</a>,<em>Relations</em>, vol. 3, no. 1, 2015, pp. 81–84</li><li>Catia Faria,<a href="/works/faria-2015-disentangling-obligations-assistance/">Disentangling obligations of assistance: A reply to Clare Palmer’s “Against the view that we are usually required to assist wild animals”</a>,<em>Relations</em>, no. 3, 2015, pp. 211–218</li><li>David S. Favre,<a href="/works/favre-1979-wildlife-rights-ever/">Wildlife rights: the ever-widening circle</a>,<em>Environmental law</em>, vol. 9, no. 241, 1979, pp. 241–281</li><li>Charles K. Fink,<a href="/works/fink-2005-predation-argument/">The predation argument</a>,<em>Between the species</em>, vol. 13, no. 5, 2005, pp. 1–16</li><li>Stephen Jay Gould,<a href="/works/gould-1982-nonmoral-nature/">Nonmoral nature</a>,<em>Natural History</em>, vol. 91, 1982, pp. 19–26</li><li>John Hadley,<a href="/works/hadley-2006-duty-to-aid/">The duty to aid nonhuman animals in dire need</a>,<em>Journal of Applied Philosophy</em>, vol. 23, 2006, pp. 445–451</li><li>Ned Hettinger,<a href="/works/hettinger-1994-valuing-predation-rolston/">Valuing predation in Rolston's environmental ethics: Bambi lovers versus tree huggers</a>,<em>Environmental ethics</em>, vol. 19, no. 1, 1994, pp. 3–20</li><li>Alison Hills,<a href="/works/hills-2010-utilitarianism-contractualism-demandingness/">Utilitarianism, contractualism and demandingness</a>,<em>The Philosophical Quarterly</em>, vol. 60, no. 239, 2010, pp. 225–242</li><li>Oscar Horta,<a href="/works/horta-2010-disvalue-nature-intervention/">Disvalue in nature and intervention</a>,<em>Pensata animal</em>, vol. 34, 2010</li><li>Oscar Horta,<a href="/works/horta-2010-ethics-ecology-fear/">The ethics of the ecology of fear against the nonspeciesist paradigm: A shift in the aims of intervention in nature</a>,<em>Between the Species: An Online Journal for the Study of Philosophy and Animals</em>, vol. 13, no. 10, 2010, pp. 163–187</li><li>Oscar Horta,<a href="/works/horta-2010-debunking-idyllic-view/">Debunking the idyllic view of natural processes: Population dynamics and suffering in the wild</a>,<em>Télos</em>, vol. 17, no. 1, 2010, pp. 73–88</li><li>Oscar Horta,<a href="/works/horta-2013-zoopolis-intervention-state/">Zoopolis, intervention, and the state of nature</a>,<em>Law, Ethics, and Philosophy</em>, vol. 1, no. 1, 2013, pp. 113–125</li><li>Oscar Horta,<a href="/works/horta-2015-problem-evil-nature/">The problem of evil in nature: evolutionary bases of the prevalence of disvalue</a>,<em>Relations</em>, vol. 30, no. 3, 2015, pp. 17–32</li><li>Michael Hutchins and Christen Wemmer,<a href="/works/hutchins-1987-wildlife-conservation-animal/">Wildlife conservation and animal rights: Are they compatible?</a>, in M. W. Fox and L. D. Mickley (eds.)<em>Advances in Animal Welfare Science 1986/87</em>, Dordrecht, 1987, pp. 111–137</li><li>Dale Jamieson,<a href="/works/jamieson-1990-rights-justice-duties/">Rights, justice, and duties to provde assistance: A critique of Regan's theory of rights</a>,<em>Ethics</em>, vol. 100, no. 2, 1990, pp. 349–362</li><li>J. K. Kirkwood and A. W. Sainsbury,<a href="/works/kirkwood-1996-ethics-interventions-welfare/">Ethics of interventions for the welfare of free-living wild animals</a>,<em>Animal Welfare</em>, vol. 5, no. 3, 1996, pp. 235–243</li><li>T. Bruce Lauber et al.,<a href="/works/bruce-lauber-2007-role-ethical-judgments/">The role of ethical judgments related to wildlife fertility control</a>,<em>Society & Natural Resources</em>, vol. 20, no. 2, 2007, pp. 119–133</li><li>Adriano Mannino,<a href="/works/mannino-2015-humanitarian-intervention-nature/">Humanitarian intervention in nature: Crucial questions and probable answers</a>,<em>Relations. Beyond Anthropocentrism</em>, vol. 3, no. 1, 2015, pp. 107–118</li><li>Leah McKelvie,<a href="/works/mc-kelvie-2015-seeking-increase-awareness/">Seeking to increase awareness of speciesism and its impact on all animals: A report on ‘animal ethics’</a>,<em>Relations</em>, no. 3, 2015, pp. 101–105</li><li>Jeff McMahan,<a href="/works/mc-mahan-2010-meat-eaters/">The meat eaters</a>,<em>The New York times</em>, September 19, 2010</li><li>Jeff McMahan,<a href="/works/mc-mahan-2010-predators-response/">Predators: A response</a>,<em>The New York times</em>, September 28, 2010</li><li>Jeff McMahan,<a href="/works/mc-mahan-2015-moral-problem-predation/">The moral problem of predation</a>, in Andrew Chignell, Terence Cuneo, and Matthew Halteman (eds.)<em>Philosophy comes to dinner: Arguments about the ethics of eating</em>, New York, 2015, pp. 268–294</li><li>Ole Martin Moen,<a href="/works/moen-2016-ethics-of-wild/">The Ethics of Wild Animal Suffering</a>,<em>Etikk i praksis - Nordic Journal of Applied Ethics</em>, no. 1, 2016, pp. 91–104</li><li>Richard Thornhill and Michael Morris,<a href="/works/thornhill-2006-animal-liberationist-responses/">Animal liberationist responses to non-anthropogenic animal suffering</a>,<em>Worldviews: Global Religions, Culture, and Ecology</em>, vol. 10, no. 3, 2006, pp. 355–379</li><li>Julia Mosquera,<a href="/works/mosquera-2015-harm-they-inflict/">The harm they inflict when values conflict: Why diversity does not matter</a>,<em>Relations</em>, no. 3, 2015, pp. 65–77</li><li>Albert W. Musschenga,<a href="/works/musschenga-2002-naturalness-animal-welfare/">Naturalness: Beyond animal welfare</a>,<em>Journal of Agricultural and Environmental Ethics</em>, vol. 15, no. 2, 2002, pp. 171–186</li><li>Arne Naess,<a href="/works/naess-1991-should-we-try/">Should we try to relieve clear cases of extreme suffering in nature?</a>,<em>Pan ecology</em>, vol. 6, no. 1, 1991, pp. 1–5</li><li>Yew-Kwang Ng,<a href="/works/ng-1995-welfare-biology-evolutionary/">Towards welfare biology: evolutionary economics of animal consciousness and suffering</a>,<em>Biology and philosophy</em>, vol. 10, no. 3, 1995, pp. 255–285</li><li>Eze Paez,<a href="/works/paez-2015-intuitions-gone-astray/">Intuitions gone astray: Between implausibility and speciesism</a>,<em>Relations</em>, no. 3, 2015, pp. 93–99</li><li>Eze Paez,<a href="/works/paez-2015-refusing-help-inflicting/">Refusing help and inflicting harm: A critique of the environmentalist view</a>,<em>Relations</em>, no. 3, 2015, pp. 165–178</li><li>Clare Palmer,<a href="/works/palmer-2015-view-that-we/">Against the view that we are normally required to assist wild animals</a>,<em>Relations</em>, no. 3, 2015, pp. 203–210</li><li>David Pearce,<a href="/works/pearce-2015-welfare-state-elephants/">A welfare state for elephants? A case study of compassionate stewardship</a>,<em>Relations</em>, vol. 3, no. 2, 2015, pp. 153–164</li><li>Ty Raterman and The University of North Texas Center for Environmental Philosophy,<a href="/works/raterman-2008-environmentalist-lament-predation/">An environmentalist's lament on predation</a>,<em>Environmental Ethics</em>, vol. 30, no. 4, 2008, pp. 417–434</li><li>Tom Regan,<a href="/works/regan-2004-case-animal-rights/"><em>The case for animal rights: updated with a new preface</em></a>, Berkeley, 2004</li><li>Bernard E. Rollin,<a href="/works/rollin-1981-animal-rights-human/"><em>Animal rights and human morality</em></a>, Buffalo, 1981</li><li>Holmes Rolston,<a href="/works/rolston-1992-disvalues-nature/">Disvalues in nature</a>,<em>The monist</em>, vol. 75, no. 2, 1992, pp. 250–278</li><li>Mark Sagoff,<a href="/works/sagoff-1984-animal-liberation-environmental/">Animal liberation and environmental ethics: bad marriage, quick divorce</a>,<em>Osgoode Hall law journal</em>, vol. 22, no. 1, 1984, pp. 297–307</li><li>Steve F. Sapontzis,<a href="/works/sapontzis-1984-predation/">Predation</a>,<em>Ethics and animals</em>, vol. 5, no. 2, 1984, pp. 27–38</li><li>Steve F. Sapontzis,<a href="/works/sapontzis-1987-morals-reason-animals/"><em>Morals, reason, and animals</em></a>, Philadelphia, 1987</li><li>Aaron Simmons,<a href="/works/simmons-2009-animals-predators-right/">Animals, predators, the right to life and the duty to save lives</a>,<em>Ethics & the environment</em>, vol. 14, no. 1, 2009, pp. 15–27</li><li>Peter Singer,<a href="/works/singer-1973-food-thought-reply/">Food for thought: Reply</a>,<em>The New York Review of Books</em>, 1973</li><li>Thomas M. Sittler-Adamczewski,<a href="/works/sittler-adamczewski-2016-consistent-vegetarianism-suffering/">Consistent vegetarianism and the suffering of wild animals</a>,<em>Journal of practical ethics</em>, vol. 4, no. 2, 2016</li><li>Beril İdemen Sözmen,<a href="/works/sozmen-2013-harm-wild-facing/">Harm in the wild: Facing non-human suffering in nature</a>,<em>Ethical Theory and Moral Practice</em>, vol. 16, no. 5, 2013, pp. 1075–1088</li><li>Beril İdemen Sözmen,<a href="/works/sozmen-2015-relations-moral-obligations/">Relations and moral obligations towards other animals</a>,<em>Relations</em>, no. 3, 2015, pp. 179–193</li><li>Brian Tomasik,<a href="/works/tomasik-2015-importance-of-wild/">The importance of wild-animal suffering</a>,<em>Relations. Beyond Anthropocentrism</em>, vol. 3, no. 2, 2015, pp. 133–152</li><li>Mikel Torres,<a href="/works/torres-2015-case-intervention-nature/">The case for intervention in nature on behalf of animals: a critical review of the main arguments against intervention</a>,<em>Relations</em>, vol. 3, no. 1, 2015, pp. 33–49</li><li>Stephen M. Young,<a href="/works/young-2006-status-vermin/">On the status of vermin</a>,<em>Between the Species: An Online Journal for the Study of Philosophy and Animals</em>, vol. 13, no. 6, 2006</li></ul><p><em>With thanks to Tom Bradschetl and Ricardo Torres.</em></p>
]]></description></item><item><title>California Proposition 2: a bibliography</title><link>https://stafforini.com/notes/california-proposition-2-a-bibliography/</link><pubDate>Sun, 09 Jun 2013 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/california-proposition-2-a-bibliography/</guid><description>&lt;![CDATA[<p>This bibliography was prepared for a research project on California Proposition 2 that I undertook a while ago, while volunteering for<a href="http://www.effectiveanimalactivism.org/">Effective Animal Activism</a>. As I became increasingly busy with many other activities, the project was eventually put on hold. I hope to resume work at some point in the future; in the meantime, I thought I should at least make this material public, in the hope that it might inspire others to do research in this and related areas.</p><ul><li>Don Bell,<a href="/works/bell-2005-review-recent-publications/"><em>A review of recent publications on animal welfare issues for table egg laying hens</em></a>, 2005</li><li>Dee Max Corbin,<a href="/works/corbin-2011-what-factors-influence/"><em>What factors influence how a state will vote on animal welfare ballot initiatives?</em></a>, 2011</li><li>Katherine Ann Kuykendall,<a href="/works/kuykendall-2012-selected-newspaper-coverage/"><em>Selected newspaper coverage of the 2008 California Proposition 2: A content analysis</em></a>, 2012</li><li>Jonathan R. Lovvorn and Nancy V. Perry,<a href="/works/lovvorn-2008-california-proposition-watershed/">California Proposition 2: A watershed moment for animal law</a>,<em>Animal law</em>, vol. 15, 2009, pp. 149–170</li><li>Jayson L. Lusk,<a href="/works/lusk-2010-effect-proposition-demand/">The effect of proposition 2 on the demand for eggs in California</a>,<em>Journal of agricultural & food industrial organization</em>, vol. 8, no. 1, 2010</li><li>Matthew Newman, Tim Gage, and Trisha McMahon,<a href="/works/newman-2008-fiscal-economic-effects/"><em>Fiscal and economic effects of Proposition 2</em></a>, 2008</li><li>Timothy J Richards et al.,<a href="/works/richards-2011-media-advertising-ballot/"><em>Media advertising and ballot initiatives: an experimental analysis</em></a>, 2011</li><li>Daniel A. Sumner et al.,<a href="/works/sumner-2010-economics-regulations-hen/">The economics of regulations on hen housing in California</a>,<em>Journal of Agricultural and Applied Economics</em>, vol. 42, no. 3, 2010, pp. 429–438</li><li>Neil Thapar,<a href="/works/thapar-2011-taking-live-stock/">Taking (live) stock of animal welfare in agriculture: comparing two ballot initiatives</a>,<em>Hastings women's law journal</em>, vol. 22, no. 2, 2011, pp. 317–338</li></ul>
]]></description></item><item><title>Earning to give: an annotated bibliography</title><link>https://stafforini.com/notes/earning-to-give-an-annotated-bibliography/</link><pubDate>Sat, 22 Mar 2014 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/earning-to-give-an-annotated-bibliography/</guid><description>&lt;![CDATA[<p>A while ago, I did a quick survey of the literature on earning to give—the pursuit of a high-earning career with the express purpose of donating a large portion of one&rsquo;s earnings to high-impact charities. Given the recent interest in the topic, I thought I should turn those notes into a proper bibliography. If I&rsquo;m missing anything, please let me know.</p><span class="cite-unresolved" title="No work page found for Andreev2013MaximizingDonationsVia">Andreev2013MaximizingDonationsVia</span><blockquote><p>Chronicles the author&rsquo;s experience in finding a job as a software engineer with the goal of earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Brooks2013WayProducePerson">Brooks2013WayProducePerson</span><blockquote><p>If your profoundest interest is dying children in Africa or Bangladesh, it&rsquo;s probably best to go to Africa or Bangladesh, not to Wall Street.</p></blockquote><span class="cite-unresolved" title="No work page found for Carter2013VocationEarningGive">Carter2013VocationEarningGive</span><blockquote><p>Working to fund one&rsquo;s philanthropic ventures is certainly noble. But we shouldn&rsquo;t downplay the value of the income-generating work just because we can&rsquo;t see as directly how it helps others.</p></blockquote><span class="cite-unresolved" title="No work page found for Farquhar2012ReplaceabilityEffectWorking">Farquhar2012ReplaceabilityEffectWorking</span><blockquote><p>When we look at the consequences of our actions, and consider whether to take a job in a harmful industry, the harm of our taking the job is somewhat less than it first appears. There is still a harm, though, so you shouldn&rsquo;t take the job unless you think you can do something pretty good with it.</p></blockquote><span class="cite-unresolved" title="No work page found for Farquhar2012CollectiveActionWorking">Farquhar2012CollectiveActionWorking</span><blockquote><p>You need to pay attention to what other EAs are doing. But it doesn&rsquo;t mean that we should always avoid working in harmful industries, or thinking in general about how to individually make the most difference.</p></blockquote><span class="cite-unresolved" title="No work page found for Farquhar2012UniversalisabilityImmoral">Farquhar2012UniversalisabilityImmoral</span><blockquote><p>We recommend earning to give only because we look at the way the world is and we reckon it makes a positive difference. If the world became different, and lots of people naturally decided to do earning to give, we&rsquo;d recommend something else.</p></blockquote><span class="cite-unresolved" title="No work page found for Hallquist2014WhyEarnGive">Hallquist2014WhyEarnGive</span><blockquote><p>An engaging, informal introduction to earning to give. Recommended.</p></blockquote><span class="cite-unresolved" title="No work page found for Hoskin2013HowMuchTaxes">Hoskin2013HowMuchTaxes</span><blockquote><p>Suppose you&rsquo;re looking to donate as much as possible to charity, and are choosing between two jobs. Should you worry about the taxes in each location?</p></blockquote><span class="cite-unresolved" title="No work page found for Hurford2013WhatEarningGive">Hurford2013WhatEarningGive</span><blockquote><p>A survey of the field.</p></blockquote><span class="cite-unresolved" title="No work page found for Karnofsky2013OurTakeEarning">Karnofsky2013OurTakeEarning</span><blockquote><p>We&rsquo;re excited about &ldquo;earning to give&rdquo; as one option among many.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2011HowMuchShouldYou">Kaufman2011HowMuchShouldYou</span><blockquote><p>Earn and give as much as you can for the level of personal suffering you are prepared to accept.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2011WhatAboutNonWork">Kaufman2011WhatAboutNonWork</span><blockquote><p>Even in your spare time, which you usually can&rsquo;t turn into money to donate by working additional hours, you should still not engage in local charitable activities.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2012ProfessionalPhilanthropy">Kaufman2012ProfessionalPhilanthropy</span><blockquote><p>A brief discussion of the convenience of using that expression, before &rsquo;earning to give&rsquo; had became established.</p></blockquote>
Jeff Kaufman,<a href="/works/kaufman-2012-history-earning-give/">History of "Earning to Give"</a>,<em>Jeff Kaufman's Blog</em>, September 18, 2012<blockquote><p>Credits Brian Tomasik with the first formulation of the idea.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2013SummariesEarningGive">Kaufman2013SummariesEarningGive</span><blockquote><p>Earning to give involves four main ideas: (1) donate; (2) donate to the most effective organizations; (3) earn more so you can give more; (4) spend less so you can give more.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2013ArguingAboutBanking">Kaufman2013ArguingAboutBanking</span><blockquote><p>Examples of people in clearly beneficial jobs like Boris Yakubchik (high school math teacher) and Julia Wise (social worker at a prison) are both much less controversial and much more attainable for the typical reader.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2013HistoryEarningGiveII">Kaufman2013HistoryEarningGiveII</span><blockquote><p>Quotes an exchange between Singer and an early proponent of earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2013HistoryEarningGiveIII">Kaufman2013HistoryEarningGiveIII</span><blockquote><p>Claims that John Wesley, founder of the Methodist movement, was an early advocate of earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Kaufman2016EarningGive">Kaufman2016EarningGive</span><blockquote><p>Earning to give is a career path that is well suited to people who are good at earning money, who are still exploring cause areas, who prioritize interventions that are funding-limited, who are early in their careers and want to build their skills, or who want to balance altruism against other things in their lives. I find that it suits me well, but I also can imagine myself doing something else five years from now.</p></blockquote><span class="cite-unresolved" title="No work page found for Kuhn2013DowngradingConfidenceEarning">Kuhn2013DowngradingConfidenceEarning</span><blockquote><p>Concludes that (1) doing high-paying highly-skilled careers might be dominated by doing directly charitable things and that (2) effective altruists should probably be spreading a broader message.</p></blockquote><span class="cite-unresolved" title="No work page found for Kuhn2013CommonObjectionsEarning">Kuhn2013CommonObjectionsEarning</span><blockquote><p>Discusses five objections to earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for MacAskill2011BankingEthicalCareer">MacAskill2011BankingEthicalCareer</span><blockquote><p>Altruistic bankers earn a lot, aren&rsquo;t likely to be replaceable, and can support the very best charities. They are likely to do more good than someone in an &ldquo;ethical&rdquo; career.</p></blockquote><span class="cite-unresolved" title="No work page found for MacAskill2012FollowingSchindlersFootsteps">MacAskill2012FollowingSchindlersFootsteps</span><blockquote><p>Uses Schindler&rsquo;s example to discuss the morality of working for an evil corporation.</p></blockquote><span class="cite-unresolved" title="No work page found for MacAskill2013SaveWorldDont">MacAskill2013SaveWorldDont</span><blockquote><p>Earning to give is often the best career option because of (1) discrepancy in earnings, (2) replaceability and (3) high variations in charity cost-effectiveness.</p></blockquote>
William MacAskill,<a href="/works/mac-askill-2014-replaceability-career-choice/">Replaceability, career choice, and making a difference</a>,<em>Ethical theory and moral practice</em>, vol. 17, no. 2, 2014, pp. 269–283<blockquote><p>Defends the idea that deliberately pursuing a lucrative career in order to donate a large proportion of one&rsquo;s earnings is typically ethically preferable to a career within the charity sector.</p></blockquote><span class="cite-unresolved" title="No work page found for MacAskill201580000HoursThinks">MacAskill201580000HoursThinks</span><blockquote><p>80,000 Hours never claimed that most people should earn to give; and now thinks that even fewer people should pursue this path to impact than it did before.</p></blockquote><span class="cite-unresolved" title="No work page found for MacAskill2016ShouldYouSwitch">MacAskill2016ShouldYouSwitch</span><blockquote><p>When considering whether to do direct work or earn to give, you could ask yourself: am I in the top 15% of people in terms of comparative advantage at earning to give?</p></blockquote>
William MacAskill,<a href="/works/mac-askill-2016-banking-ethical-career/">Banking: the ethical career choice</a>, in David Edmonds (ed.)<em>Philosophers take on the world</em>, Oxford, 2016<blockquote><p>Condensed version of &lsquo;Replaceability, career choice, and making a difference&rsquo;.</p></blockquote><span class="cite-unresolved" title="No work page found for Matthews2013JoinWallStreet">Matthews2013JoinWallStreet</span><blockquote><p>A popular, engaging piece, with profiles of many prominent advocates and practitioners of earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Penalva2015QueGanarPara">Penalva2015QueGanarPara</span><blockquote><p>An engaging introduction for Spanish-speaking readers.</p></blockquote><span class="cite-unresolved" title="No work page found for Redwood2012FlatMarginEffect">Redwood2012FlatMarginEffect</span><blockquote><p>Argues that if you take a job that seems to have a strong (positive or negative) impact on the economy, the actual difference it makes to social welfare will be minimal.</p></blockquote><span class="cite-unresolved" title="No work page found for Salam2013RiseSingerians">Salam2013RiseSingerians</span><blockquote><p>A criticism from a conservative perspective. Claims that people motivated by curiosity and novelty or a desire for recognition may have a much bigger positive impact than people who try to do good deliberately.</p></blockquote><span class="cite-unresolved" title="No work page found for Sinick2013EarningGiveAltruistic">Sinick2013EarningGiveAltruistic</span><blockquote><p>Responds to MacAskill&rsquo;s Quartz piece on earning to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Shulman2012EntrepreneurshipGamePoker">Shulman2012EntrepreneurshipGamePoker</span><blockquote><p>It would be a mistake to think of the returns to entrepreneurship as predictably stemming from just showing up and taking a spin at the wheel of startup roulette. Instead, entrepreneurship is more like poker: a game where even the best players cannot predictably win over a single night, but measurable differences predict that some will earn much more than others on average.</p></blockquote><span class="cite-unresolved" title="No work page found for Shulman2012SoftwareEngineeringBritain">Shulman2012SoftwareEngineeringBritain</span><blockquote><p>How attractive is the software industry for those who want to make money and use it to do good? In some ways, the British statistics are misleading, but they also reflect a real difference: software engineers in the US, and especially Silicon Valley, really are better compensated. The post lays out the supporting data, and discusses ways people outside the United States can make their way to Silicon Valley.</p></blockquote>
Carl Shulman,<a href="/works/shulman-2012-salary-startup-how/">Salary or startup? How do-gooders can gain more from risky careers</a>,<em>80,000 Hours</em>, January 8, 2012<blockquote><p>Altruists have stronger reasons to pursue risky careers because the standard arguments for risk aversion do not apply.</p></blockquote><span class="cite-unresolved" title="No work page found for Todd2013ShowMeHarm">Todd2013ShowMeHarm</span><blockquote><p>Makes some very rough estimates of how harmful finance would have to be in order for its harm to outweigh the good realized by the donations of someone who earns to give.</p></blockquote><span class="cite-unresolved" title="No work page found for Todd2013ComparisonMedicalResearch">Todd2013ComparisonMedicalResearch</span><blockquote><p>Earning to give in finance is slightly better than medical research.</p></blockquote><span class="cite-unresolved" title="No work page found for Todd2014HowMuchPeople">Todd2014HowMuchPeople</span><blockquote><p>Attemps to estimate how much people pursuing earning to give donate, how much they can be expected to donate in the immediate future, and how much extra giving was caused by 80,000 Hours.</p></blockquote>
Brian Tomasik,<a href="/works/tomasik-2006-why-activists-should/">Why activists should consider making lots of money</a>,<em>Essays on Reducing Suffering</em>, 2006<blockquote><p>A pioneering essay.</p></blockquote><span class="cite-unresolved" title="No work page found for Xodarap2014PoliticalSkillsWhich">Xodarap2014PoliticalSkillsWhich</span><blockquote><p>An annotated bibliography of a few recent meta-analyses of predictors of income.</p></blockquote><p><em>With thanks to Imma Six.</em></p>
]]></description></item><item><title>My beliefs</title><link>https://stafforini.com/notes/my-beliefs/</link><pubDate>Thu, 05 Feb 2015 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/my-beliefs/</guid><description>&lt;![CDATA[<p>My friend Brian Tomasik recently made available<a href="http://reducing-suffering.org/summary-beliefs-values-big-questions/">a table</a> summarizing his beliefs on various issues. I thought recording my own credences on these propositions would be a fun and potentially instructive exercise, and decided to make my answers public. To prevent myself from being influenced by Brian&rsquo;s responses, I copied the original table, pasted in on an Excel spreadsheet, deleted the column with his answers, and randomized the rows by sorting them in alphabetical order. Only after recording all my responses did I allow myself to look at Brian&rsquo;s, and I managed to resist the temptation to make any changes<em>ex post facto</em>. Overall, I was pleasantly surprised at the degree to which we agree, and not very surprised at the areas where we don&rsquo;t agree. I also suspect that a few of our disagreements (e.g. on compatibilism about free will) are<a href="http://consc.net/papers/verbal.pdf">merely verbal</a>. Below, I comment on the propositions on which we disagree the most.</p><p>If you think you might want to participate in this exercise, you can make a duplicate of<a href="https://docs.google.com/spreadsheets/d/14hKOHhLTyD1DkYPTdUriRGW2oLPfvxRic1FtzUXg6Ds/edit">this spreadsheet</a> and record your answers there before reading any further.</p><p><strong>Update</strong>: See also Michael Dickens&rsquo; responses in the comments section.</p><p><strong>Update 2</strong>: There is now<a href="/notes/my-beliefs-updated/">a new version</a> of the table below, which reflects my beliefs as of November 2020.</p><table><thead><tr><th><strong>Belief</strong></th><th><strong>Brian</strong></th><th><strong>Pablo</strong></th></tr></thead><tbody><tr><td>&ldquo;Aesthetic value: objective or subjective?&rdquo; Answer: subjective</td><td>99.50%</td><td>99.90%</td></tr><tr><td>Artificial general intelligence (AGI) is possible in principle</td><td>99%</td><td>95%</td></tr><tr><td>Compatibilism on free will</td><td>98%</td><td>5%</td></tr><tr><td>&ldquo;Abstract objects: Platonism or nominalism?&rdquo; Answer: nominalism</td><td>97%</td><td>90%</td></tr><tr><td>Moral anti-realism</td><td>96%</td><td>20%</td></tr><tr><td>Humans will eventually build human-level AGI conditional on no other major intervening disruptions to civilization as we know it</td><td>90%</td><td>90%</td></tr><tr><td>We live in at least a Level I multiverse</td><td>85%</td><td>60%</td></tr><tr><td>Type-A physicalism regarding consciousness</td><td>75%</td><td>25%</td></tr><tr><td>Eternalism on philosophy of time</td><td>75%</td><td>98%</td></tr><tr><td>Earth will eventually be controlled by a singleton of some sort</td><td>72%</td><td>70%</td></tr><tr><td>Human-inspired colonization of space will cause net suffering if it happens</td><td>71%</td><td>1%</td></tr><tr><td>Many worlds interpretation of quantum mechanics (or close kin)</td><td>70%</td><td>70%</td></tr><tr><td>Soft AGI takeoff</td><td>70%</td><td>55%</td></tr><tr><td>By at least 10 years before human-level AGI is built, debate about AGI risk will be as mainstream as global warming is in 2015</td><td>67%</td><td>70%</td></tr><tr><td>Human-controlled AGI would result in less expected suffering than uncontrolled, as judged by the beliefs I would hold if I thought about the problem for another 10 years</td><td>65%</td><td>5%</td></tr><tr><td>A government will build the first human-level AGI, assuming humans build one at all</td><td>62%</td><td>60%</td></tr><tr><td>Climate change will cause net suffering</td><td>60%</td><td>50%</td></tr><tr><td>By 2100, if biological humans still exist, most of them will regard factory farming as a great evil of the past</td><td>60%</td><td>10%</td></tr><tr><td>The effective-altruism movement, all things considered, reduces rather than increases suffering in the far future</td><td>60%</td><td>40%</td></tr><tr><td>Electing more liberal politicians reduces net suffering in the far future</td><td>57%</td><td>60%</td></tr><tr><td>Faster technological innovation increases net suffering in the far future</td><td>55%</td><td>55%</td></tr><tr><td>&ldquo;Science: scientific realism or scientific anti-realism?&rdquo; Answer: realism</td><td>60%</td><td>90%</td></tr><tr><td>At bottom, physics is digital</td><td>50%</td><td>—</td></tr><tr><td>Cognitive closure of some philosophical problems</td><td>50%</td><td>80%</td></tr><tr><td>Rare Earth explanation of Fermi Paradox</td><td>50%</td><td>25%</td></tr><tr><td>Crop cultivation prevents net suffering</td><td>50%</td><td>50%</td></tr><tr><td>Conditional on a government building the first human-level AGI, it will be the USA (rather than China, etc.)</td><td>50%</td><td>65%</td></tr><tr><td>Earth-originating intelligence will colonize the entire galaxy (ignoring anthropic arguments)</td><td>50%</td><td>10%</td></tr><tr><td>Faster economic growth will cause net suffering in the far future</td><td>43%</td><td>55%</td></tr><tr><td>Whole brain emulation will come before de novo AGI, assuming both are possible to build</td><td>42%</td><td>65%</td></tr><tr><td>Modal realism</td><td>40%</td><td>1%</td></tr><tr><td>The multiverse is finite</td><td>40%</td><td>70%</td></tr><tr><td>A world government will develop before human-level AGI</td><td>35%</td><td>15%</td></tr><tr><td>Wild-animal suffering will be a mainstream moral issue by 2100, conditional on biological humans still existing</td><td>15%</td><td>8%</td></tr><tr><td>Humans will go extinct within millions of years for some reason other than AGI</td><td>10%</td><td>10%</td></tr><tr><td>A design very close to CEV will be implemented in humanity&rsquo;s AGI, conditional on AGI being built (excluding other value-learning approaches and other machine-ethics proposals)</td><td>5%</td><td>10%</td></tr></tbody></table><p><strong>Values</strong></p><table><thead><tr><th><strong>Value system</strong></th><th><strong>Brian</strong></th><th><strong>Pablo</strong></th></tr></thead><tbody><tr><td>Negative utilitarianism focused on extreme suffering</td><td>90%</td><td>1%</td></tr><tr><td>Ethical pluralism for other values (happiness, love, friendship, knowledge, accomplishment, diversity, paperclips, and other things that agents care about)</td><td>10%</td><td>0.01%</td></tr></tbody></table><table><thead><tr><th><strong>The kind of suffering that matters most is…</strong></th><th><strong>Brian</strong></th><th><strong>Pablo</strong></th></tr></thead><tbody><tr><td>hedonic experience</td><td>70%</td><td>99%</td></tr><tr><td>preference frustration</td><td>30%</td><td>1%</td></tr></tbody></table><h2 id="comments">Comments</h2><p><em>Compatibilism on free will</em></p><p>If by &lsquo;free will&rsquo; we mean what most people mean by that expression, then I&rsquo;m almost certain that we don&rsquo;t have free will, and that free will is incompatible with determinism. Brian appears to believe otherwise because he thinks that the meaning of &lsquo;free will&rsquo; should ultimately be governed by instrumental considerations. I think this approach fosters muddled thinking and facilitates intellectual dishonesty.</p><p><em>Moral anti-realism</em></p><p>This is one in a series of very strong disagreements about questions in metaethics. I think some things in the world—pleasant states of consciousness—objectively have value, regardless of whether anyone desires them or has any other positive attitude towards them. This value, however, is realized in conscious experience and as such exists in the natural world, rather than being<em>sui generis</em>, as most moral realists believe. So the main arguments against moral realism, such as Mackie&rsquo;s argument from queerness, do not apply to the view I defend.</p><p><em>Type-A physicalism regarding consciousness</em></p><p>I&rsquo;m somewhat persuaded by David Chalmers&rsquo; arguments for dualism, though I discount the apparent force of this evidence by the good track-record of physicalist explanations in most other domains. About half of my probability mass for physicalism is concentrated on type-B physicalism—hence my relatively low credence on the type of physicalism that Brian favors.</p><p><em>Eternalism on philosophy of time</em></p><p>I assume Brian just meant belief in the static, or<em>tensless</em>, theory of time (what McTaggart called the &lsquo;B theory&rsquo;), rather than some subtler view about temporal becoming. If so, I think the arguments against the dynamic or tensed theory are roughly as strong as the arguments against free will: both of these views are primarily supported by introspection (&ldquo;it seems time flows&rdquo;, &ldquo;it seems I&rsquo;m free&rdquo;) and opposed by naturalism, and the latter is much better supported by the evidence.</p><p><em>Human-inspired colonization of space will cause net suffering if it happens</em></p><p>I&rsquo;m puzzled by Brian&rsquo;s answer here. I think it&rsquo;s quite unlikely that the future will contain a preponderance of suffering over happiness, since it will be optimized by agents who strongly prefer the latter and will have driven most other sentient lifeforms extinct. But maybe Brian meant that colonization will cause a surplus of suffering relative to the amount present before colonization. I think this is virtually certain; I&rsquo;d give it a 99% chance.</p><p><em>Human-controlled AGI would result in less expected suffering than uncontrolled, as judged by the beliefs I would hold if I thought about the problem for another 10 years</em></p><p>Uncontrolled AGI will likely result in no suffering at all, whereas human-controlled AGI will result in some suffering and much more happiness. Brian thinks the goal systems that uncontrolled AGI might create will resemble paradigmatic sentient beings enough to count themselves as sentient, but I do not share his radically subjectivist stance concerning the nature of suffering (on which something counts as suffering roughly if, and to the degree that, we decide to care about it).</p><p><em>By 2100, if biological humans still exist, most of them will regard factory farming as a great evil of the past</em></p><p>I slightly misread the sentence, which I took to state that most future people will regard factory farming as<em>the</em> great evil of the past. Given the high number of alternative candidates (from a non-enlightened, common-sense human morality), I thought it unlikely that our descendants would single out factory farming as the single greatest evil in human history. But it&rsquo;s much more likely (~60%) that they will regard it as<em>a</em> great evil, especially if mass production of<em>in vitro</em> meat displaces factory farms (and hence removes the main cognitive barrier to widespread recognition that all sentient beings matter morally, and matter equally).</p><p><em>Science: scientific realism or scientific anti-realism?" Answer: realism</em></p><p>I think the best explanation of the extraordinary success of science is that it describes the world as it really is; on anti-realism, this success is a mystery. So I think realism is much more likely.</p><p><em>The effective-altruism movement, all things considered, reduces rather than increases suffering in the far future</em></p><p>I think the EA movement somewhat increases the probability of far-future suffering by increasing the probability that such a future will exist at all, to a greater degree than it reduces the suffering of far-future sentients conditional on their existence.</p><p>(Note that I believe the EA movement<em>decreases</em> the overall probability of<em>net</em> suffering in the far future. That is, EA will cause, in expectation, more suffering, but even more happiness.)</p><p><em>Cognitive closure of some philosophical problems</em></p><p>Reflection about our evolutionary origins makes it quite likely that we lack the cognitive machinery necessary for solving at least some such problems. We are probably among the stupidest intelligent species possible, since we were the first to fill the niche and we haven&rsquo;t evolved much since. (But see<a href="http://metamagician3000.blogspot.com.ar/2009/09/interview-with-greg-egan.html">Greg Egan</a> for an opposing perspective.)</p><p><em>Earth-originating intelligence will colonize the entire galaxy (ignoring anthropic arguments)</em></p><p>I think extinction before colonization is quite likely; ~20% this century, and we have a long way to go.</p><p><em>Rare Earth explanation of Fermi Paradox</em></p><p>Very low confidence in my answer here; Brian is probably closer to the truth than I am.</p><p><em>Modal realism</em></p><p>Upon reflection, I think I was overconfident on this one; 5-10% seems like a more reasonable estimate. The main reason to believe modal realism is that it would provide an answer to the<a href="/notes/why-does-the-world-exist-a-bibliography/">ultimate question of existence</a>. However, the existence of nothing would have been an even more natural state of affairs than the existence of everything. Since this possibility manifestly does not obtain, that reduces the probability of modal realism (see Stephen Grover,<a href="/works/grover-1998-cosmological-fecundity/">Cosmological fecundity</a>,<em>Inquiry</em>, vol. 41, no. 3, 1998, pp. 277–299).</p><p><em>Negative utilitarianism focused on extreme suffering</em></p><p>I see no reason to deviate from symmetry: suffering of a given intensity is as bad as happiness of that intensity is good; and suffering twice as intense is (only) twice as bad. Brian thinks there isn&rsquo;t a natural intensity matching between happiness and suffering, but I disagree (and trust my judgment here).</p><p><em>Ethical pluralism for other values (happiness, love, friendship, knowledge, accomplishment, diversity, paperclips, and other things that agents care about)</em></p><p>I just cannot see how anything but experience could have value. As I view things, the choice is between some form of experientialism and nihilism,<em>tertium non datur</em>.</p><p><em>The kind of suffering that matters most is&hellip; preference frustration</em></p><p>Again, I have difficulty understanding how merely satisfying a preference, in the absence of any conscious<em>experience of satisfaction</em>, could matter at all morally. Preference theories are also beset by a number of problems; for example, it&rsquo;s unclear how they can deal with preferences whose objects are spatially or temporally very removed from the subject, without either restricting the class of relevant preferences arbitrarily or implying gross absurdities.</p><p><em>With thanks to Brian Tomasik, Peter McIntyre, and others for valuable discussion.</em></p>
]]></description></item><item><title>Carlos Santiago Nino: a bibliography</title><link>https://stafforini.com/notes/carlos-santiago-nino-a-bibliography/</link><pubDate>Sun, 08 Feb 2015 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/carlos-santiago-nino-a-bibliography/</guid><description>&lt;![CDATA[<figure><a href="/ox-hugo/carlos-santiago-nino-portrait.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/carlos-santiago-nino-portrait.jpg" alt="Carlos Santiago Nino"/></figure><blockquote><p>Carlos Nino was a publicly engaged intellectual of rare integrity and brilliance. In his dedication to human rights, the rule of law, and constitutional legitimacy he combined passion with wisdom and analytic clarity. His inexhaustible courage in fighting to restore decency to his nation provides a model for others working in the wake of dictatorship. We are fortunate to have in his writings a record of his remarkable thought and experience.</p></blockquote><p>Thomas Nagel</p><p>I started compiling this bibliography back when I was an undergraduate student at the university of Buenos Aires, and continued to work on it intermittently over the following few years. In 2007, my hard drive was damaged in an accident and most of the data stored in it was lost. I had since then assumed that the document containing the bibliography was among the affected files. A week ago, however, I stumbled upon a copy of it. Thinking that there might be sufficient interest in this information among legal scholars and other academics, I spent a few hours over the following days updating the references and formatting the bibliography for online publication. I would like to thank the staff at various institutions whose libraries I consulted in the course of preparing this document, in particular Universidad de San Andrés, Universidad Torcuato Di Tella, Universidad de Buenos Aires, Sociedad Argentina de Análisis Filosófico, Centro de Investigaciones Filosóficas, University of Oxford (Bodleian Law Library), Balliol College and University of Toronto (Robarts Library).</p><hr><h2 id="1966">1966</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1966-efectos-ilicito-civil/">Efectos del ilícito civil</a>,<em>Lecciones y ensayos</em>, vol. 32, 1966, pp. 157–168. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-efectos-ilicito-civil/">Efectos del ilícito civil</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 249–258.</li><li>Carlos Santiago Nino,<a href="/works/nino-1966-review-norberto-eduardo/">Review of Norberto Eduardo Spolanski's '<em>Nullum crimen sine lege</em>, error de prohibición y fallos plenarios'</a>,<em>Lecciones y ensayos</em>, vol. 35, 1966, pp. 157–8. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-review-norberto-eduardo/">Nota a N. Spolanski, Nullum crimen sine lege</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 101–102.</li></ol><h2 id="1967">1967</h2><ol><li>Carlos Santiago Nino and Jorge A. Bacqué,<a href="/works/nino-1967-lesiones-retorica-problema/">Lesiones y retórica: El problema de la ciencia del derecho y la ideología jurídica a propósito de las lesiones simultáneamente calificadas y atenuadas</a>,<em>La ley</em>, vol. 126, 1967, pp. 966–975. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-lesiones-retorica/">Lesiones y retórica</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 288–303.</li><li>Jorge A. Bacqué and Carlos Santiago Nino,<a href="/works/bacque-1967-tema-interpretacion-ley/">El tema de la interpretación de la ley en Alf Ross ejemplificado en dos fallos argentinos</a>,<em>Lecciones y ensayos</em>, vol. 36, 1967, pp. 31–38. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-interpretacion-ley-ross/">El tema de la interpretación de la ley según Alf Ross ejemplificado en dos fallos argentinos</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 259–265.</li></ol><h2 id="1968">1968</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1968-review-richard-robinson/">Review of Richard Robinson,<em>Definition</em></a>,<em>Lecciones y ensayos</em>, vol. 38, 1968, pp. 187–188.</li></ol><h2 id="1969">1969</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1969-definicion-delito/">La definición de "delito"</a>,<em>Notas de filosofía del derecho</em>, vol. 5, 1969, pp. 47–65. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-definicion-delito/">La definición de ``delito''</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 187–204.</li></ol><h2 id="1970">1970</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1970-dogmatica-juridica-sus/"><em>La dogmática jurídica: sus aspectos científicos y acientíficos (con especial referencia al derecho penal)</em></a>, 1970. Published with corrections as Carlos Santiago Nino,<a href="/works/nino-1984-consideraciones-sobre-dogmatica/"><em>Consideraciones sobre la dogmática jurídica (con referencia particular a la dogmática penal)</em></a>, México, 1984.</li><li>Carlos Santiago Nino,<a href="/works/nino-2007-racional-irracional-dogmatica/">Lo racional y lo irracional en la dogmática jurídica</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política I: metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 239–248.</li></ol><h2 id="1972">1972</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1972-concurso-derecho-penal/"><em>El concurso en el derecho penal: Criterios para clasificar los casos de varios hechos o de varias normas en la calificación penal de una conducta</em></a>, Buenos Aires, 1972.</li><li>Carlos Santiago Nino,<a href="/works/nino-1972-pequena-historia-dolo/">La pequeña historia del dolo y el tipo</a>,<em>La ley</em>, vol. 148, 1972, pp. 1063–1076. Based on a 1970 conference reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-pequena-historia-dolo/">La pequeña historia del "dolo y el tipo"</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 260–268.</li></ol><h2 id="1973">1973</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1973-definicion-derecho-norma/">La definición de "derecho" y de "norma jurídica"</a>, in Carlos Santiago Nino (ed.)<em>Notas de introducción al derecho</em>, Buenos Aires, 1973.</li><li>Carlos Santiago Nino,<a href="/works/nino-1973-conceptos-basicos-derecho/">Los conceptos básicos del derecho</a>, in Carlos Santiago Nino (ed.)<em>Notas de introducción al derecho</em>, Buenos Aires, 1973.</li></ol><h2 id="1974">1974</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1974-concepto-sistema-juridico/">El concepto de sistema jurídico y la validez moral del derecho</a>, in Carlos Santiago Nino (ed.)<em>Notas de introducción al derecho</em>, Buenos Aires, 1973.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-consideraciones-sobre-dogmatica/"><em>Consideraciones sobre la dogmática jurídica (con referencia particular a la dogmática penal)</em></a>, México, 1984.</li><li>Carlos Santiago Nino et al.,<a href="/works/nino-1974-concepto-accion-derecho/"><em>El concepto de acción en el derecho</em></a>, 1974.</li></ol><h2 id="1975">1975</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1975-ciencia-derecho-interpretacion/">La ciencia del derecho y la interpretación jurídica</a>, in Carlos Santiago Nino (ed.)<em>Notas de introducción al derecho</em>, Buenos Aires, 1973.</li></ol><h2 id="1976">1976</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1976-concepto-validez-problema/">El concepto de validez y el problema del conflicto entre normas de diferente jerarquía en la teoría pura del derecho</a>, in J. A. Bacqué (ed.)<em>Derecho, filosofía y lenguaje: Homenaje a Ambrosio L. Gioja</em>, Buenos Aires, 1976. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-concepto-validez-problema/">El concepto de validez y el problema del conflicto entre normas de diferente jerarquía</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 228–238 and, with corrections, as Carlos Santiago Nino,<a href="/works/nino-1985-concepto-validez-kelsen-aplicado/">El concepto de validez de Kelsen aplicado al problema del conflicto de normas de diferente jerarquía</a>,<em>El concepto de validez de Kelsen aplicado al problema del conflicto de normas de diferente jerarquía</em>, pp. 29–40.</li></ol><h2 id="1977">1977</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1977-general-strategy-criminal/"><em>Towards a general strategy for criminal law adjudication</em></a>, 1977. Published in Spanish, with corrections, as Carlos Santiago Nino,<a href="/works/nino-1980-limites-responsabilidad-penal/"><em>Los límites de la responsabilidad penal: Una teoría liberal del delito</em></a>, Buenos Aires, 1980.</li></ol><h2 id="1978">1978</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1978-concepciones-fundamentales-liberalismo/">Las concepciones fundamentales del liberalismo</a>,<em>Revista latinoamericana de filosofía</em>, vol. 4, no. 2, 1978, pp. 141–150. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-concepciones-fundamentales-liberalismo/">Las concepciones fundamentales del liberalismo</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 19–29.</li><li>Carlos Santiago Nino,<a href="/works/nino-1978-confusions-kelsen-concept/">Some confusions around Kelsen's concept of validity</a>,<em>Archiv für Rechts- und Sozialphilosophie</em>, vol. 64, no. 3, 1978, pp. 357–377. Reprinted, in abridged form, as Carlos Santiago Nino,<a href="/works/nino-1998-confusions-kelsen-abridged/">Some confusions surrounding Kelsen's concept of validity</a>, in Stanley L. Paulson and Bonnie Litschewski Paulson (eds.)<em>Normativity and norms: critical perspectives on Kelsenian themes</em>, Oxford, 1998, pp. 253–261. Reprinted in Spanish, with corrections, as Carlos Santiago Nino,<a href="/works/nino-1985-concepto-validez-kelsen/">El concepto de validez jurídica en la teoría de Kelsen</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 7–27.</li><li>Carlos Santiago Nino,<a href="/works/nino-2008-sobre-que-nos/">Sobre lo que nos espera cuando despidamos a Kant y Hegel</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 42–46.</li></ol><h2 id="1979">1979</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1979-algunos-modelos-metodologicos/"><em>Algunos modelos metodológicos de "ciencia" jurídica</em></a>, México, 1979.</li><li>Carlos Santiago Nino,<a href="/works/nino-1979-mismo-omitir-que/">¿Da lo mismo omitir que actuar? Acerca de la valoración moral de los delitos por omisión</a>,<em>La ley</em>, vol. C, 1979, pp. 801–817. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1985-mismo-omitir-gracia/">¿Da lo mismo omitir que actuar?</a>, in Jorge J. E. Gracia et al. (ed.)<em>El análisis filosófico en América latina</em>, México, 1985, pp. 91–104, and in Carlos Santiago Nino,<a href="/works/nino-2008-mismo-omitir-que/">¿Da lo mismo omitir que actuar?</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 205–230.</li><li>Carlos Santiago Nino,<a href="/works/nino-1979-es-tenencia-drogas/">¿Es la tenencia de drogas con fines de consumo personal una de “las acciones privadas de los hombres”?</a>,<em>La ley</em>, vol. D, 1979, pp. 743–758. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2000-tenencia-drogas-de-greiff/">¿Es la tenencia de drogas con fines de consumo personal una de ``las acciones privadas de los hombres''?</a>, in Pablo de Greiff and Gustavo de Greiff (eds.)<em>Moralidad, legalidad y drogas</em>, Buenos Aires, 2000.</li><li>Carlos Santiago Nino,<a href="/works/nino-1979-fundamentacion-legitima-defensa/">La fundamentación de la legítima defensa: réplica al profesor Fletcher</a>,<em>Doctrina penal</em>, vol. 2, no. 6, 1979, pp. 235–256. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-fundamentacion-legitima-defensa/">La fundamentación de la legítima defensa</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 269–287.</li></ol><h2 id="1980">1980</h2><ol><li><span class="cite-unresolved" title="No work page found for Nino1980IntroduccionAnalisisDerecho">Nino1980IntroduccionAnalisisDerecho</span>. Italian translation: Carlos Santiago Nino,<a href="/works/nino-1996-introduzione-all-analisi/"><em>Introduzione all'analisi del diritto</em></a>, Torino, 1996. Excerpt reprinted as Carlos Santiago Nino,<a href="/works/nino-1995-concepto-responsabilidad/">El concepto de responsabilidad</a>, in Roberto López Cabana and Atilio A. Alterini (eds.)<em>La responsabilidad: homenaje al profesor doctor Isidro H. Goldenberg</em>, Buenos Aires, 1995, pp. 15–20.</li><li>Carlos Santiago Nino,<a href="/works/nino-1980-limites-responsabilidad-penal/"><em>Los límites de la responsabilidad penal: Una teoría liberal del delito</em></a>, Buenos Aires, 1980. Revised Spanish translation of Carlos Santiago Nino,<a href="/works/nino-1977-general-strategy-criminal/"><em>Towards a general strategy for criminal law adjudication</em></a>, 1977.</li><li>Carlos Santiago Nino,<a href="/works/nino-1980-dworkin-legal-positivism/">Dworkin and legal positivism</a>,<em>Mind</em>, vol. 89, no. 356, 1980, pp. 519–543.</li><li>Carlos Santiago Nino,<a href="/works/nino-1980-dworkin-disolucion-controversia/">Dworkin y la disolución de la controversia “positivismo vs. iusnaturalismo”</a>,<em>Revista latinoamericana de filosofía</em>, vol. 6, no. 3, 1980, pp. 213–234. Revised Spanish translation of Carlos Santiago Nino,<a href="/works/nino-1980-dworkin-legal-positivism/">Dworkin and legal positivism</a>,<em>Mind</em>, vol. 89, no. 356, 1980, pp. 519–543. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1980-dworkin-disolucion-revista-ciencias/">Dworkin y la disolución de la controversia ``positivismo vs. iusnaturalismo''</a>,<em>Revista de ciencias sociales</em>, vol. 38, 1993, pp. 495–528. Reprinted with corrections as Carlos Santiago Nino,<a href="/works/nino-1985-superacion-controversia/">La superación de la controversia ``positivismo vs. iusnaturalismo'' a partir de la ofensiva antipositivista de Dworkin</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 145–173.</li><li>Carlos Santiago Nino,<a href="/works/nino-1980-libre-albedrio-responsabilidad/">Libre albedrío y responsabilidad penal</a>,<em>Archivos latinoamericanos de metodología y filosofía del derecho</em>, vol. 1, 1980, pp. 79. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-libre-albedrio/">Libre albedrío y responsabilidad penal</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 103–115.</li><li>Carlos Santiago Nino,<a href="/works/nino-1980-alf-ross-maestro/">Alf Ross: un maestro en el arte de disolver mitos</a>,<em>Doctrina penal</em>, vol. 3, no. 3, 1980, pp. 760–761.</li><li>Translation of Felix E. Oppenheim,<a href="/works/oppenheim-1980-lineamientos-analisis-logico/"><em>Lineamientos de un análisis lógico del derecho</em></a>, Valencia, Venezuela, 1980.</li></ol><h2 id="1981">1981</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1981-conceptos-derecho/">Los conceptos de derecho</a>,<em>Crítica</em>, vol. 13, no. 38, 1981, pp. 29–52. Reprinted with corrections as Carlos Santiago Nino,<a href="/works/nino-1985-enfoque-esencialista/">El enfoque esencialista del concepto de derecho</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 176–195.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-razones-prescripciones-respuesta/">Razones y prescripciones: una respuesta a Alchourrón</a>,<em>Análisis filosófico</em>, vol. 1, no. 2, 1981, pp. 41–47. Reprinted with corrections as Carlos Santiago Nino,<a href="/works/nino-1985-son-prescripciones/">¿Son prescripciones los juicios de valor?</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 109–123.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-razones-prescripciones-respuesta/">Razones y prescripciones: una respuesta a Alchourrón</a>,<em>Análisis filosófico</em>, vol. 1, no. 2, 1981, pp. 41–47. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-razones-prescripciones/">Razones y prescripciones: una respuesta a Alchourrón</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 42–48.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-respuesta-malamud-goti/">Respuesta a Malamud Goti</a>,<em>Doctrina penal</em>, vol. 4, no. 16, 1981, pp. 767–773. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-respuesta-malamud-goti/">Respuesta a Malamud Goti</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 176–184.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-pena-muerte-consentimiento/">Pena de muerte, consentimiento y protección social</a>,<em>La ley</em>, vol. A, 1981, pp. 708–721. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-pena-muerte-consentimiento/">Pena de muerte, consentimiento y protección social</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 155–175.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-review-stuart-hampshire/">Review of Stuart Hampshire (ed.),<em>Public and Private Morality</em></a>,<em>Análisis filosófico</em>, vol. 1, no. 1, 1981, pp. 102–3. Mistakenly reprinted in<em>Análisis filosófico</em>, vol. 1, no. 2, pp. 76-77.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-review-carlos-alchourron/">Review of Carlos Alchourrón & Eugenio Bulygin,<em>Sobre la existencia de las normas jurídicas</em></a>,<em>Análisis filosófico</em>, vol. 1, no. 1, 1981, pp. 99.</li></ol><h2 id="1982">1982</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1982-legitima-defensa-fundamentacion/"><em>La legítima defensa: fundamentación y régimen jurídico</em></a>, Buenos Aires, 1982.</li><li>Carlos Santiago Nino,<a href="/works/nino-1982-concurso-continuacion-delitos/">Concurso y continuación de delitos de omisión: a propósito de los plenarios “Guersi” y “Pitchon”</a>,<em>Doctrina penal</em>, vol. 5, no. 18, 1982, pp. 283–315. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-concurso-continuacion-delitos/">Concurso y continuación de delitos de omisión (a propósito de los plenarios “Guersi” y “Pitchon”)</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 231–259.</li></ol><h2 id="1983">1983</h2><ol><li>Eugenio Bulygin et al. (ed.),<a href="/works/bulygin-1983-lenguaje-derecho-homenaje/"><em>El lenguaje del derecho. Homenaje a Genaro R. Carrió</em></a>, Buenos Aires, 1983.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-concepto-poder-constituyente/">El concepto de poder constituyente originario y la justificación jurídica</a>, in Eugenio Bulygin et al. (ed.)<em>El lenguaje del derecho: homenaje a Genaro R. Carrió</em>, Buenos Aires, 1983, pp. 339–370. Reprinted with corrections as Carlos Santiago Nino,<a href="/works/nino-1985-competencia-constituyente/">La competencia del constituyente originario y el carácter moral de la justificación jurídica</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 41–68.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-caso-conciencia-cuestion/">Un caso de conciencia. La cuestión del deber de reverenciar los símbolos patrios</a>,<em>Doctrina penal</em>, vol. 6, no. 22, 1983, pp. 315–329.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-consensual-theory-punishment/">A consensual theory of punishment</a>,<em>Philosophy & Public Affairs</em>, vol. 12, no. 4, 1983, pp. 289–306. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1993-consensual-theory-duff/">A consensual theory of punishment</a>, in Anthony Duff (ed.)<em>Punishment</em>, Aldershot, 1993, pp. 197–214, and in Carlos Santiago Nino,<a href="/works/nino-1995-consensual-theory-simmons/">A consensual theory of punishment</a>, in A. John Simmons et al. (ed.)<em>Punishment</em>, Princeton, 1995, pp. 94–111. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2008-teoria-consensual-pena/">Una teoría consensual de la pena</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 116–132.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-nueva-estrategia-para/">Una nueva estrategia para el tratamiento de las normas “de facto”</a>,<em>La ley</em>, vol. D, 1983, pp. 935–946. Reprinted with corrections as Carlos Santiago Nino,<a href="/works/nino-1985-validez-normas-de-facto/">La validez de las normas “de facto”</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 89–107.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-concepcion-alf-ross/">La concepción de Alf Ross sobre los juicios de justicia</a>,<em>Anuario de filosofía jurídica y social</em>, vol. 3, 1983, pp. 159–174. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-concepcion-alf-ross/">La concepción de Alf Ross sobre los juicios de justicia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 172–183.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-legal-ethics-metaphysics/">Legal ethics: between metaphysics and futility</a>,<em>Oikeustiede-Jurisprudentia</em>, vol. 16, 1983, pp. 189–220. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-etica-legal-entre/">Ética legal: entre la metafísica y la futilidad</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política I: metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 111–136.</li><li>Carlos Santiago Nino and Jaime Malamud Goti,<a href="/works/nino-1985-responsabilidad-juridica-represion/">La responsabilidad jurídica en la represión del terrorismo</a>,<em>Civiles y militares: memoria secreta de la transición</em>, Buenos Aires, 1987, pp. 389–391. Published in Horacio Verbitsky,<a href="/works/verbitsky-1987-civiles-militares/"><em>Civiles y militares: memoria secreta de la transición</em></a>, Buenos Aires, 1987, pp. 389-391.</li><li>Carlos Santiago Nino,<a href="/works/nino-1983-review-julio-maier/">Review of Julio B. Maier,<em>Función normativa de la nulidad</em></a>,<em>Análisis filosófico</em>, vol. 3, no. 1, 1983, pp. 74–75.</li><li>Carlos Santiago Nino, Jaime Malamud Goti, and Genaro Carrió,<a href="/works/nino-1983-ley-amnistia/">Ley de amnistía</a>,<em>La Nación</em>, 1983, pp. 8.</li><li>Carlos Santiago Nino et al.,<a href="/works/nino-1966-prologo/">Prólogo</a>, in Eugenio Bulygin (ed.)<em>El lenguaje del derecho: Homenaje a Genaro R. Carrio</em>, Buenos Aires, 1966, pp. 7–9.</li></ol><h2 id="1984">1984</h2><ol><li><span class="cite-unresolved" title="No work page found for Nino1984EticaDerechosHumanos">Nino1984EticaDerechosHumanos</span>.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-legal-norms-reasons/">Legal norms and reasons for action</a>,<em>Rechtstheorie</em>, vol. 15, no. 4, 1984, pp. 489–502. Reprinted in Spanish, with corrections, as Carlos Santiago Nino,<a href="/works/nino-1985-normas-juridicas-razones/">Normas jurídicas y razones para actuar</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 125–143.</li><li>Carlos Santiago Nino and Jaime Malamud Goti,<a href="/works/nino-1984-proyecto-reformulacion-obediencia/"><em>Proyecto de reformulación de la obediencia debida</em></a>, 1984. Published in Horacio Verbitsky,<a href="/works/verbitsky-1987-civiles-militares/"><em>Civiles y militares: memoria secreta de la transición</em></a>, Buenos Aires, 1987, pp. 399-407.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-liberty-equality-causality/">Liberty, equality and causality</a>,<em>Rechtstheorie</em>, vol. 15, no. 1, 1984, pp. 23–38. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-libertad-igualdad-causalidad/">Libertad, igualdad y causalidad</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires:, 2007, pp. 52–67.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-limits-enforcement-morality/">The limits of the enforcement of morality through the criminal law</a>, in Jorge J. E. Gracia et al. (ed.)<em>Philosophical analysis in Latin America</em>, Dordrecht, 1984, pp. 93–113. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2008-limites-aplicacion-moral/">Los límites a la aplicación de la moral a través del derecho penal</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 47–64.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-ross-reforma-procedimiento/">Ross y la reforma del procedimiento de reforma constitucional</a>,<em>Revista de ciencias sociales</em>, vol. 25, no. 2, 1984, pp. 347–364. Reprinted, with corrections as, Carlos Santiago Nino,<a href="/works/nino-1985-puede-sistema-juridico/">¿Puede un sistema jurídico generar su propia validez?</a>,<em>La validez del derecho</em>, Buenos Aires, 1985, pp. 69–88.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-problemas-abiertos-filosofia/">Problemas abiertos en la filosofía del derecho</a>,<em>Doxa</em>, vol. 1, 1984, pp. 175–177.</li><li>Carlos Santiago Nino,<a href="/works/nino-1984-reforma-estudios-abogacia/">La reforma de los estudios de abogacía</a>,<em>La Nación</em>, 1984, pp. 9.</li></ol><h2 id="1985">1985</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1985-validez-derecho/"><em>La validez del derecho</em></a>, Buenos Aires, 1985.</li><li>Carlos Santiago Nino,<a href="/works/nino-1985-limitaciones-teoria-hart/">Las limitaciones de la teoría de Hart sobre las normas jurídicas</a>,<em>Anuario de filosofía jurídica y social</em>, vol. 5, 1985, pp. 75–93. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-limitaciones-teoria-hart/">Las limitaciones de la teoría de Hart sobre las normas jurídicas</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 198–210.</li><li>Carlos Santiago Nino,<a href="/works/nino-1985-human-rights-policy/">The human rights policy of the argentine constitutional government: A reply</a>,<em>Yale journal of international law</em>, vol. 11, no. 1, 1985, pp. 217–230.</li><li>Carlos Santiago Nino,<a href="/works/nino-1985-hombre-sus-derechos/">El hombre, sus derechos y el Derecho</a>,<em>Revista jurídica de Buenos Aires</em>, 1985, pp. 129–149. Reprinted with corrections in Carlos Santiago Nino,<a href="/works/nino-1989-hombre-sus-derechos/">El hombre, sus derechos y el Derecho</a>,<em>El constructivismo ético</em>, Madrid, 1989, pp. 356–365.</li><li>Carlos Santiago Nino,<a href="/works/nino-1985-que-es-democracia/">¿Qué es la democracia?</a>,<em>Clarín</em>, 1985. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-que-es-democracia/">Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 187–188.</li></ol><h2 id="1986">1986</h2><ol><li>Carlos Santiago Nino (ed.),<a href="/works/nino-1986-reforma-constitucional-dictamen/"><em>Reforma constitucional: dictamen preliminar</em></a>, Buenos Aires, 1986.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-informe-practica-constitucional/">Informe sobre la práctica constitucional de dos sistemas semi-presidenciales</a>, in Carlos Santiago Nino (ed.)<em>Reforma constitucional: dictamen preliminar</em>, Buenos Aires, 1986, pp. 386–399.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-exposicion-coordinador/">Exposición del coordinador del Consejo para la Consolidación de la Democracia</a>, in Carlos Santiago Nino (ed.)<em>Reforma constitucional: dictamen preliminar</em>, Buenos Aires, 1986, pp. 402–406.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-desafio-universidad-argentina/">El desafío a la universidad argentina</a>,<em>Plural</em>, vol. 2, no. 4, 1986, pp. 7–10.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-does-consent-override/">Does consent override proportionality?</a>,<em>Philosophy & public affairs</em>, vol. 15, no. 2, 1986, pp. 183–187. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2008-puede-consentimiento-anular/">¿Puede el consentimiento anular la proporcionalidad?</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 133–136.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-hechos-morales-concepcion/">Los hechos morales en una concepción constructivista</a>,<em>Cuadernos de ética</em>, vol. 1, no. 1, 1986, pp. 67–79. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1989-hechos-morales/">Los hechos morales en una concepción constructivista</a>,<em>El constructivismo ético</em>, Madrid, 1989, pp. 61–71.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-racionalismo-fundamentacion-etica/">El racionalismo crítico y la fundamentación de la ética</a>,<em>Manuscrito</em>, vol. 9, no. 2, 1986, pp. 39–52. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1989-racionalismo-fundamentacion/">El racionalismo crítico y la fundamentación de la ética</a>,<em>El constructivismo ético</em>, Madrid, 1989, pp. 75–89, and in Carlos Santiago Nino,<a href="/works/nino-1992-racionalismo-schuster/">El racionalismo crítico y la fundamentación de la ética</a>, in Felix Gustavo Schuster (ed.)<em>Popper y las ciencias sociales</em>, Buenos Aires, 1992, pp. 105–120.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-paradoja-irrelevancia-moral/">La paradoja de la irrelevancia moral del gobierno y el valor epistemológico de la democracia</a>,<em>Análisis filosófico</em>, vol. 6, no. 2, 1986, pp. 65–82. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1989-paradoja-irrelevancia/">La paradoja de la irrelevancia moral del gobierno y el valor epistemológico de la democracia</a>,<em>El constructivismo ético</em>, Madrid, 1989, pp. 113–133 and in Carlos Santiago Nino,<a href="/works/nino-1990-paradoja-vigo/">La paradoja de la irrelevancia moral del gobierno y el valor epistemológico de la democracia</a>, in Rodolfo Luis Vigo (ed.)<em>En torno a la democracia</em>, Santa Fe, 1990, pp. 97–114. Italian translation: Carlos Santiago Nino,<a href="/works/nino-1990-paradoja-irrilevanza-martino/">Il paradosso della irrelevanza morale del governo e il valore epistemologico della democrazia</a>, in Antonio A. Martino (ed.)<em>La giustificazione morale della democrazia</em>, Genova, 1990, pp. 15–42.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-justificacion-democracia-entre/">La justificación de la democracia: entre la negación de la justificación y la restricción de la democracia. Réplica a mis críticos</a>,<em>Análisis filosófico</em>, vol. 6, no. 2, 1986, pp. 103–114. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-justificacion-democracia/">La justificación de la democracia: entre la negación de la justificación y la restricción de la democracia: réplica a mis críticos</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 195–207. Italian translation: Carlos Santiago Nino,<a href="/works/nino-1990-giustificazione-martino/">La giustificazione della democrazia: tra la negazione della giustificazione e la restrizione della democrazia: replica ai miei critici</a>, in Antonio A. Martino (ed.)<em>La giustificazione morale della democrazia</em>, Genova, 1990, pp. 73–91.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-participacion-remedio-crisis/">La participación como remedio a la llamada 'crisis de la democracia'</a>, in Luis Aznar and others (eds.)<em>Alfonsín: discursos sobre el discurso</em>, Buenos Aires, 1987, pp. 123–137.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-concepto-derecho-hart/">El concepto de derecho de Hart</a>,<em>Revista de ciencias sociales</em>, vol. 28, no. 1, 1986, pp. 33–54. Revised version of Carlos Santiago Nino,<a href="/works/nino-1985-limitaciones-teoria-hart/">Las limitaciones de la teoría de Hart sobre las normas jurídicas</a>,<em>Anuario de filosofía jurídica y social</em>, vol. 5, 1985, pp. 75–93. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-concepto-derecho-hart/">El concepto de derecho de Hart</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 211–227.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-democracia-verdad-moral/">Democracia y verdad moral</a>,<em>La Nación</em>, 1986. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-democracia-verdad-moral/">Democracia y verdad moral</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 189–191.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-dictamen-reforma-constitucional/">Dictamen sobre la reforma constitucional</a>,<em>La Nación</em>, 1986, pp. 4–6.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-escepticismo-etico-justificacion/">El escepticismo ético frente a la justificación de la democracia</a>,<em>La Nación</em>, 1986. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-escepticismo-etico/">El escepticismo ético frente a la justificación de la democracia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 192–194.</li></ol><h2 id="1987">1987</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1987-introduccion-filosofia-accion/"><em>Introducción a la filosofía de la acción humana</em></a>, Buenos Aires, 1987.</li><li>Carlos Santiago Nino (ed.),<a href="/works/nino-1987-reforma-constitucional-segundo/"><em>Reforma constitucional: segundo dictamen del Consejo para la Consolidación de la Democracia</em></a>, Buenos Aires, 1987.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-voto-obligatorio/">El voto obligatorio</a>, in Carlos Santiago Nino (ed.)<em>Reforma constitucional: segundo dictamen del Consejo para la Consolidación de la Democracia</em>, Buenos Aires, 1987, pp. 219–227.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-speedy-trials-argentina/">Speedy trials for argentina's military?</a>,<em>The New York times</em>, 1987.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-concept-moral-person/">The concept of moral person</a>,<em>Crítica</em>, vol. 19, no. 56, 1987, pp. 47–75. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-1987-concepto-persona-valdivia/">Los titulares de derechos humanos: el concepto de persona moral</a>, in Lourdes Valdivia and Enrique Villanueva (eds.)<em>Filosofía del lenguaje, de la ciencia, de los derechos humanos y problemas de su enseñanza</em>, México, 1987. Another Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-concepto-persona-moral/">El concepto de persona moral</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 137–154.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-begriff-rechtfertigung/">Begriff und Rechtfertigung der ursprünglichen verfassungsgeben Gewalt</a>, in Eugenio Bulygin and Ernesto Garzón Valdés (eds.)<em>Argentinische Rechtstheorie und Rechtsphilosophie Heute</em>, Berlin, 1987, pp. 85–108.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-cuatrilema-consecuencialismo/">El cuatrilema del consecuencialismo</a>,<em>Doxa</em>, vol. 4, 1987, pp. 365–366. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-cuatrilema-consecuencialismo/">El cuatrilema del consecuencialismo</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 51–52.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-prologo-nudelman/">Prólogo</a>, in Ricardo Nudelman (ed.)<em>Raúl Alfonsín: el poder de la democracia</em>, Buenos Aires, 1987, pp. 11–17.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-derecho-constitucional-frente/">El derecho constitucional frente a la llamada "crisis de la democracia"</a>, in Héctor Fix-Zamudio (ed.)<em>Memoria del III Congreso Iberoamericano de Derecho Constitucional</em>, Mexico, 1987, pp. 305–319.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-defensa-democracia-convergencia/">Defensa de la democracia y convergencia</a>, in Alberto Ferrari, Francisco Herrera, and Francisco Herrera (eds.)<em>Los hombres del presidente</em>, Buenos Aires, 1987, pp. 129–134.</li><li>Carlos Santiago Nino,<a href="/works/nino-1987-sistemas-electorales/">Sobre los sistemas electorales</a>, in Luis Aznar and Mercedes Boschi (eds.)<em>Los sistemas electorales: sus consecuencias políticas y partidarias</em>, Buenos Aires, 1987, pp. 93–99.</li></ol><h2 id="1988">1988</h2><ol><li>Carlos Santiago Nino (ed.),<a href="/works/nino-1988-radiodifusion/"><em>Radiodifusión</em></a>, Buenos Aires, 1988.</li><li>Carlos Santiago Nino (ed.),<a href="/works/nino-1988-presidencialismo-vs-parlamentarismo/"><em>Presidencialismo vs. parlamentarismo: materiales para el estudio de la reforma constitucional</em></a>, Buenos Aires, 1988.</li><li>Carlos Santiago Nino,<a href="/works/nino-1988-presidencialismo-vs-parlamentarismo-articulo/">Presidencialismo vs. parlamentarismo</a>, in Carlos Santiago Nino (ed.)<em>Presidencialismo vs. parlamentarismo: materiales para el estudio de la reforma constitucional</em>, Buenos Aires, 1988, pp. 115–124.</li><li>Carlos Santiago Nino,<a href="/works/nino-1988-liberalismo-comunitarismo/">Liberalismo «versus» comunitarismo</a>,<em>Revista del Centro de Estudios Constitucionales</em>, vol. 1, no. Septiembre-diciembre, 1988, pp. 363–376.</li><li>Carlos Santiago Nino,<a href="/works/nino-1988-politica-derechos-humanos/">La política de derechos humanos en la primera mitad del período del gobierno democrático</a>, in Ernesto Garzón Valdés, Manfred Mols, and Arnolds Spitta (eds.)<em>La nueva democracia argentina (1983--1986)</em>, Buenos Aires, 1988, pp. 201–212.</li><li>Carlos Santiago Nino,<a href="/works/nino-1986-constructivismo-epistemologico-entre/">Constructivismo epistemológico: entre Rawls y Habermas</a>,<em>Doxa</em>, vol. 5, 1986, pp. 87–105. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1989-constructivismo-epistemologico/">Constructivismo epistemológico: entre Rawls y Habermas</a>,<em>El constructivismo ético</em>, Madrid, 1989, pp. 93–110.</li><li>Carlos Santiago Nino,<a href="/works/nino-1988-man-his-rights/">Man and his rights before the law</a>, in Stavros Panou et al. (ed.)<em>Human being and the cultural values: IVR 12th World Congress, Athens, 1985: proceedings, part 3</em>, Stuttgart, 1988, pp. 103–113.</li><li>Carlos Santiago Nino,<a href="/works/nino-1988-relacion-entre-derecho/">La relación entre el derecho y la justicia</a>,<em>Revista de la Asociación Argentina de Derecho Comparado</em>, vol. 7, 1988, pp. 35–36. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-relacion-derecho-justicia/">La relación entre el derecho y la justicia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 170–171.</li></ol><h2 id="1989">1989</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1989-constructivismo-etico/"><em>El constructivismo ético</em></a>, Madrid, 1989.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-etica-derechos-humanos/"><em>Ética y derechos humanos: un ensayo de fundamentación</em></a>, Buenos Aires, 1989.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-derivacion-principios-responsabilidad/">La derivación de los principios de responsabilidad penal de los fundamentos de los derechos humanos</a>,<em>Doctrina penal</em>, vol. 12, no. 45, 1989, pp. 29–48. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-derivacion-principios/">La derivación de los principios de responsabilidad penal de los fundamentos de los derechos humanos</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 25–41.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-presentacion/">Presentación</a>,<em>Lecciones y ensayos</em>, vol. 52, 1989, pp. 119–120.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-justicia-conciencia/">Justicia a la conciencia</a>,<em>La ley</em>, 1989, pp. 1197–1207.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-communitarian-challenge-liberal/">The communitarian challenge to liberal rights</a>,<em>Law and philosophy</em>, vol. 8, 1989, pp. 37–52. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1992-communitarian-challenge-reprint/">The communitarian challenge to liberal rights</a>, in Carlos Santiago Nino (ed.)<em>Rights</em>, New York, 1992, pp. 310–324.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-transition-democracy-corporatism/">Transition to democracy, corporatism and constitutional reform in Latin America</a>,<em>University of Miami Law review</em>, vol. 44, no. 1, 1989, pp. 129–164.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-consolidating-democracy/">Consolidating democracy</a>,<em>Yale law report</em>, vol. 12, 1989.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-moral-discourse/">Moral discourse and liberal rights</a>, in Neil MacCormick and Zenon Bankowski (eds.)<em>Enlightenment, rights and revolution: essays in legal and social philosophy</em>, Aberdeen, 1989, pp. 155–174. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-discurso-moral-derechos/">Discurso moral y derechos liberales</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 30–51.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-conciencia-crisis/">La conciencia de la crisis</a>, in Sergio Labourdette (ed.)<em>La encrucijada argentina</em>, Buenos Aires, 1989, pp. 27–33.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-democracy-criminal-law/">Democracy and criminal law</a>, in Ota Weinberger (ed.)<em>Aktuelle Probleme der Demokratie</em>, Wien, 1989, pp. 54–76. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2008-derecho-penal-democracia/">Derecho penal y democracia</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 13–24.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-filosofia-control-judicial/">La filosofía del control judicial de constitucionalidad</a>,<em>Revista del Centro de Estudios Constitucionales</em>, vol. 4, no. Septiembre-diciembre, 1989, pp. 79–88.</li><li>Carlos Santiago Nino,<a href="/works/nino-1981-respuesta-bayon/">Respuesta a Bayón</a>,<em>Doxa</em>, vol. 6, 1981, pp. 501–506. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-respuesta-bayon/">Respuesta a Bayón</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 53–57.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-justificacion-democracia-obligacion/">La justificación de la democracia y la obligación de obedecer el derecho</a>,<em>Revista de ciencias sociales</em>, vol. 34, 1989, pp. 147–187. Reprints Carlos Santiago Nino,<a href="/works/nino-1989-etica-derechos-humanos/"><em>Ética y derechos humanos: un ensayo de fundamentación</em></a>, Buenos Aires, 1989, pp. 225-254.</li><li>Carlos Santiago Nino,<a href="/works/nino-1989-indultos-conciencia-moral/">Indultos y conciencia moral</a>,<em>Relato</em>, vol. 1, 1989, pp. 25–35.</li></ol><h2 id="1990">1990</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1990-autonomia-necesidades-basicas/">Autonomía y necesidades básicas</a>,<em>Doxa</em>, vol. 7, 1990, pp. 21–34. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-autonomia-necesidades-basicas/">Autonomía y necesidades básicas</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 99–110.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-sobre-derechos-morales/">Sobre los derechos morales</a>,<em>Doxa</em>, vol. 7, 1990, pp. 311–325. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-sobre-derechos-morales/">Sobre los derechos morales</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 113–125.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-entrevista-genaro-carrio/">Entrevista a Genaro R. Carrió</a>,<em>Doxa</em>, vol. 7, 1990, pp. 343–352.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-constitucion-como-convencion/">La constitución como convención</a>,<em>Revista del Centro de Estudios Constitucionales</em>, vol. 6, no. Mayo-agosto, 1990, pp. 189–217.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-liberalismo-conservador-liberal/">Liberalismo conservador: ¿liberal o conservador?</a>,<em>Sistema: revista de ciencias sociales</em>, vol. 12, no. 101, 1991, pp. 63–86. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1990-liberalismo-conservador-sistema/">Liberalismo conservador: ¿liberal o conservador?</a>,<em>Sistema</em>, vol. 101, 1990, pp. 63–85 and in Carlos Santiago Nino,<a href="/works/nino-2007-liberalismo-conservador/">Liberalismo conservador: ¿liberal o conservador?</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 74–98.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-practica-derechos-fundamentales/">La práctica de los derechos fundamentales</a>,<em>Propuesta y control</em>, vol. 11, no. 2, 1990, pp. 135–143.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-discurso-blando-sobre/">El discurso blando sobre la Universidad</a>,<em>Propuesta y control</em>, vol. 12, 1990, pp. 1205–1209.</li><li>Carlos Santiago Nino,<a href="/works/nino-1990-presidencialismo-justificacion-estabilidad/">El presidencialismo y la justificación, estabilidad y eficiencia de la democracia</a>,<em>Propuesta y control</em>, vol. 13, 1990, pp. 1263–1283.</li></ol><h2 id="1991">1991</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1991-ethics-human-rights/"><em>The ethics of human rights</em></a>, Oxford, 1991. Revised English translation of Carlos Santiago Nino,<a href="/works/nino-1989-etica-derechos-humanos/"><em>Ética y derechos humanos: un ensayo de fundamentación</em></a>, Buenos Aires, 1989.</li><li>Carlos Santiago Nino et al. (ed.),<a href="/works/nino-1991-presidencialismo-estabilidad-democratica/"><em>Presidencialismo y estabilidad democrática en la Argentina</em></a>, Buenos Aires, 1991.</li><li>Carlos Santiago Nino et al. (ed.),<a href="/works/nino-1991-fundamentos-alcances-control/"><em>Fundamentos y alcances del control judicial de constitucionalidad: investigación colectiva del Centro de Estudios Institucionales de Buenos Aires</em></a>, Madrid, 1991.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-presidencialismo-justificacion-estabilidad-incollection/">El presidencialismo y la justificación, estabilidad y eficiencia de la democracia</a>, in Carlos Santiago Nino et al. (ed.)<em>Presidencialismo y estabilidad democrática en la Argentina</em>, Buenos Aires, 1991, pp. 11–27. Reprints Carlos Santiago Nino,<a href="/works/nino-1990-presidencialismo-justificacion-estabilidad/">El presidencialismo y la justificación, estabilidad y eficiencia de la democracia</a>,<em>Propuesta y control</em>, vol. 13, 1990, pp. 1263–1283?.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-huida-frente-penas/">La huida frente a las penas. A propósito del último libro de Eugenio R. Zaffaroni</a>,<em>No hay derecho</em>, vol. 2, no. 4, 1991, pp. 4–8. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-huida-frente-penas/">La huida frente a las penas</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 137–150.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-epistemological-moral-relevance/">The epistemological moral relevance of democracy</a>,<em>Ratio Juris</em>, vol. 4, no. 1, 1991, pp. 36–51. Revised English translation of Carlos Santiago Nino,<a href="/works/nino-1986-paradoja-irrelevancia-moral/">La paradoja de la irrelevancia moral del gobierno y el valor epistemológico de la democracia</a>,<em>Análisis filosófico</em>, vol. 6, no. 2, 1986, pp. 65–82? Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-relevancia-moral-epistemica/">La relevancia moral epistémica de la democracia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 218–234.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-duty-punish-abuses/">The duty to punish past abuses of human rights put into context: The case of argentina</a>,<em>Yale Law Journal</em>, vol. 100, no. 8, 1991, pp. 2619–2640. Reprinted, with a few truncated paragraphs, in Carlos Santiago Nino,<a href="/works/nino-1995-duty-punish-kritz/">The duty to punish past abuses of human rights put into context: the case of Argentina</a>, in Neil Kritz (ed.)<em>Transitional justice: how emerging democracies reckon with former regimes</em>, Washington, DC, 1995, pp. 417–436.</li><li>Carlos Santiago Nino,<a href="/works/nino-1991-fundamentos-control-judicial/">Los fundamentos del control judicial de constitucionalidad</a>, in Bruce A. Ackerman et al. (ed.)<em>Los fundamentos del control judicial de constitucionalidad</em>, Madrid, 1991, pp. 97–137.</li><li>Carlos Santiago Nino,<a href="/works/nino-democracia-epistemica-puesta/">La democracia epistémica puesta a prueba. Respuesta a Rosenkrantz y Ródenas</a>,<em>Doxa</em>, vol. 10, pp. 295–305. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-democracia-epistemica-puesta/">La democracia epistémica puesta a prueba. Respuesta a Rosenkrantz y Ródenas</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 208–217.</li><li>Carlos Santiago Nino et al.,<a href="/works/nino-1991-consideraciones-alternativas/">Consideraciones sobre alternativas semipresidenciales y parlamentarias de gobierno</a>,<em>Estudios públicos</em>, no. 42, 1991, pp. 7–44.</li></ol><h2 id="1992">1992</h2><ol><li><span class="cite-unresolved" title="No work page found for Nino1992FundamentosDerechoConstitucional">Nino1992FundamentosDerechoConstitucional</span>.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-pais-margen-ley/"><em>Un país al margen de la ley: Estudio de la anomia como componente del subdesarrollo argentino</em></a>, Buenos Aires, 1992.</li><li>Carlos Santiago Nino et al. (ed.),<a href="/works/nino-1992-presidencialismo-puesto-aprueba/"><em>El presidencialismo puesto a prueba</em></a>, Madrid, 1992.</li><li>Nino and others (eds.),<a href="/works/nino-1992-autonomia-personal-investigacion/"><em>La autonomía personal: investigación colectiva del Centro de Estudios Institucionales de Buenos Aires</em></a>, Madrid, 1992.</li><li>Carlos Santiago Nino (ed.),<a href="/works/nino-1992-rights/"><em>Rights</em></a>, New York, 1992.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-deliberative-democracy-complexity/"><em>Deliberative democracy and the complexity of constitutionalism</em></a>, 1992.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-hiperpresidencialismo-argentino/">El hiper-presidencialismo argentino y las concepciones de la democracia</a>, in Carlos Santiago Nino et al. (ed.)<em>El presidencialismo puesto a prueba</em>, Madrid, 1992, pp. 17–79.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-introduction-rights/">Introduction</a>, in Carlos Santiago Nino (ed.)<em>Rights</em>, New York, 1992, pp. xi–xxxiv.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-que-reforma-constitucional/">¿Qué reforma constitucional?</a>,<em>Propuesta y control</em>, vol. 6, no. 21, 1992, pp. 2307–2335.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-replica-maria-ines/">Réplica a María Inés Pazos</a>,<em>Doxa</em>, vol. 12, 1992, pp. 49–50. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-replica-pazos/">Réplica a María Inés Pazos</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 49–50.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-respuesta-moreso-navarro/">Respuesta a J. J. Moreso, P. E. Navarro y M. C. Redondo</a>,<em>Doxa</em>, vol. 13, 1993, pp. 261–264. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-respuesta-moreso-navarro/">Respuesta a J. J. Moreso, P. E. Navarro y M. C. Redondo</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 167–169.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-presentacion-fundamentos/">Fundamentos de derecho constitucional: examen jurídico, filosófico y politológico de la práctica constitucional argentina y comparada</a>,<em>No hay derecho</em>, vol. 2, no. 6, 1992, pp. 9.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-etica-analitica-actualidad/">Ética analítica en la actualidad</a>, in Victoria Camps, Osvaldo Guariglia, and Fernando Salmerón (eds.)<em>Concepciones de la ética: Enciclopedia iberoamericana de filosofía 2</em>, Madrid, 1992, pp. 131–151. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-etica-analitica-actualidad/">Ética analítica en la actualidad</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 21–41.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-consecuencialismo-debate-etico/">Consecuencialismo: debate ético y jurídico</a>,<em>Télos</em>, vol. 1, no. 1, 1992, pp. 73–96. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-consecuencialismo-debate/">Consecuencialismo: debate ético y jurídico</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 58–77.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-foundations-deliberative-conception/"><em>Foundations of a deliberative conception of democracy</em></a>, 1992.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-some-thoughts-abortion/">Some thoughts on the legal treatment of abortion and euthanasia</a>, in Werner Krawietz and Georg Henrik von Wright (eds.)<em>Öffentliche oder private Moral? Vom Geltungsgrunde un der Legitimität des Rechts: Festschrift für Ernesto Garzón Valdés</em>, Berlin, 1993, pp. 231–241. Revised English translation of Carlos Santiago Nino,<a href="/works/nino-2013-fundamentos-derecho-constitucional/"><em>Fundamentos de derecho constitucional: Análisis filosófico, jurídico y politológico de la práctica constitucional</em></a>, Buenos Aires, 2013, pp. 236-244, 252-254.</li><li>Carlos Santiago Nino,<a href="/works/nino-1992-autonomia-constitucional/">La autonomía constitucional</a>, in Carlos F. Rosenkrantz et al. (ed.)<em>El presidencialismo puesto a prueba</em>, Madrid, 1992, pp. 33–81.</li></ol><h2 id="1993">1993</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1993-breve-nota-sulla/">Breve nota sulla struttura del ragionamento giuridico</a>,<em>Ragion pratica</em>, vol. 1, 1993, pp. 32–37. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-breve-nota-sobre/">Breve nota sobre la estructura del razonamiento jurídico</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política I: metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 184–189.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-philosophical-reconstruction-judicial/">A philosophical reconstruction of judicial review</a>,<em>Cardozo law review</em>, vol. 14, no. 3--4, 1993, pp. 799–846. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1994-philosophical-reconstruction-rosenfeld/">A philosophical reconstruction of judicial review</a>, in Michel Rosenfeld (ed.)<em>Constitutionalism, identity, difference and legitimacy: theoretical perspectives</em>, Durham, 1994, pp. 285–332. Revised English translation of Carlos Santiago Nino,<a href="/works/nino-1991-fundamentos-control-judicial/">Los fundamentos del control judicial de constitucionalidad</a>, in Bruce A. Ackerman et al. (ed.)<em>Los fundamentos del control judicial de constitucionalidad</em>, Madrid, 1991, pp. 97–137?.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-social-rights/">On social rights</a>, in Aulis Aarnio et al. (ed.)<em>Rechtsnorm und Rechtswirklichkeit: Festschrift für Werner Krawietz zum 60. Geburtstag</em>, Berlin, 1993, pp. 295–299. Revised English translation of Carlos Santiago Nino,<a href="/works/nino-2013-fundamentos-derecho-constitucional/"><em>Fundamentos de derecho constitucional: Análisis filosófico, jurídico y politológico de la práctica constitucional</em></a>, Buenos Aires, 2013, pp. 398-403. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-1993-derechos-sociales-derecho-sociedad/">Los derechos sociales</a>,<em>Derecho y sociedad</em>, 1993. Reprinted as Carlos Santiago Nino,<a href="/works/nino-2000-sobre-derechos-sociales/">Sobre los derechos sociales</a>, in Miguel Carbonell, Juan A. Cruz Parcero, and Rodolfo Vázquez (eds.)<em>Derechos sociales y derechos de las minorías</em>, México, 2000, pp. 137–143. Another Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-sobre-derechos-sociales/">Sobre los derechos sociales</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 68–73.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-ciclo-conferencias/">Ciclo de conferencias sobre la reforma de la constitución nacional</a>,<em>Colección de temas jurídicos</em>, 1993.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-derecho-moral-politica/">Derecho, moral y política</a>,<em>Doxa</em>, vol. 14, 1993, pp. 35–46. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-derecho-moral-politica-articulo/">Derecho, moral y política</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 101–110.</li><li>Carlos Santiago Nino,<a href="/works/nino-1979-contexto-social-regimen/">Contexto social y régimen de gobierno</a>,<em>Doxa</em>, vol. 14, 1979, pp. 47–60.</li><li>Carlos Santiago Nino,<a href="/works/nino-2007-justicia/">Justicia</a>,<em>Doxa</em>, vol. 14, 2007, pp. 61–74. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1996-justicia-garzon-valdes/">Justicia</a>, in Ernesto. Garzón Valdés and Francisco J. Laporta (eds.)<em>El derecho y la justicia</em>, Madrid, 1996, pp. 467–480 and in Carlos Santiago Nino,<a href="/works/nino-2007-justicia-reprint/">Justicia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 78–90.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-se-acabo-debate/">Se acabó el debate</a>,<em>No hay derecho</em>, vol. 3, no. 8, 1993, pp. 25–26. Reprinted as Carlos Santiago Nino,<a href="/works/nino-2008-replica-zaffaroni/">Réplica a Zaffaroni</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 151–154.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-debate-constitutional-reform/">The debate over constitutional reform in Latin America</a>,<em>Fordham International law journal</em>, vol. 16, no. 3, 1993, pp. 635–651. German translation: Carlos Santiago Nino,<a href="/works/nino-1995-debatte-uber-verfassungsreform/">Die Debatte über die Verfassungsreform in Lateinamerika</a>, in Manfred H. Mols and Josef Thesing (eds.)<em>Der Staat in Lateinamerika</em>, Mainz, 1995, pp. 97–113.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-exercise-judicial-review/">On the exercise of judicial review in Argentina</a>, in Irwin P. Stotzky (ed.)<em>Transition to democracy in Latin America: the role of the judiciary</em>, Boulder, 1993, pp. 309–335.</li><li>Carlos Santiago Nino and Irwin P. Stotzky,<a href="/works/nino-1993-difficulties-transition-process/">The difficulties of the transition process</a>, in Irwin P. Stotzky (ed.)<em>Transition to democracy in Latin America: the role of the judiciary</em>, Boulder, 1993, pp. 3–20.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-presidencialismo-reforma-constitucional/">Presidencialismo y reforma constitucional en América latina</a>,<em>Contribuciones</em>, vol. 3, 1993, pp. 51–68.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-diritto-morale-politica/">Diritto, morale e politica</a>,<em>Analisi e diritto</em>, 1993, pp. 105–131.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-transition-democracy-presidentialism/">Transition to Democracy, corporatism and presidentialism with special reference to Latin America</a>, in Douglas Greenberg et al. (ed.)<em>Constitutionalism and democracy: transitions in the contemporary world: the American Council of Learned Societies comparative constitutionalism papers</em>, New York, 1993, pp. 46–64. Revised version of Carlos Santiago Nino,<a href="/works/nino-1989-transition-democracy-corporatism/">Transition to democracy, corporatism and constitutional reform in Latin America</a>,<em>University of Miami Law review</em>, vol. 44, no. 1, 1989, pp. 129–164.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-radical-evil-manuscript/"><em>Radical evil on trial</em></a>, 1993. Published, with revisions by Owen Fiss, as Carlos Santiago Nino,<a href="/works/nino-1996-radical-evil-trial/"><em>Radical evil on trial</em></a>, New Haven, 1996.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-constitution-deliberative-manuscript/"><em>The constitution of deliberative democracy</em></a>, 1993. Published, with revisions by Owen Fiss, as Carlos Santiago Nino,<a href="/works/nino-1996-constitution-deliberative-democracy/"><em>The constitution of deliberative democracy</em></a>, New Haven, 1996.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-preocupaciones-metafilosoficas/">Algunas preocupaciones meta-filosóficas y su reflejo en una concepción compleja de las normas jurídicas</a>, in Ernesto Garzón Valdés (ed.)<em>Derecho, ética y política</em>, Madrid, 1993.</li><li>Carlos Santiago Nino,<a href="/works/nino-1994-positivism-communitarianism-human/">Positivism and communitarianism: Between human rights and democracy</a>,<em>Ratio Juris</em>, vol. 7, no. 1, 1994, pp. 14–40. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-2007-positivismo-comunitarismo/">Positivismo y comunitarismo: sobre los derechos humanos y la democracia</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 155–184.</li><li>Carlos Santiago Nino,<a href="/works/nino-1993-when-just-punishment/">When just punishment is impossible...</a>, in András Sajó (ed.)<em>Truth and justice: The delicate balance: The documentation of prior regimes and individual rights</em>, Budapest, 1993, pp. 67–74.</li></ol><h2 id="1994">1994</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1994-derecho-moral-politica/"><em>Derecho, moral y política: una revisión de la teoría general del derecho</em></a>, Barcelona, 1994. Italian translation: Carlos Santiago Nino,<a href="/works/nino-1999-diritto-come-morale/"><em>Diritto come morale applicata</em></a>, Milano, 1999.</li><li>Carlos Santiago Nino,<a href="/works/nino-1994-positivism-communitarianism-human/">Positivism and communitarianism: Between human rights and democracy</a>,<em>Ratio Juris</em>, vol. 7, no. 1, 1994, pp. 14–40. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1996-positivism-alston/">Positivism and communitarianism: between human rights and democracy</a>, in Philip Alston (ed.)<em>Human rights law</em>, New York, 1996, pp. 357–383.</li><li>Carlos Santiago Nino,<a href="/works/nino-1994-reforma-menemista-signo/">Reforma menemista: signo de degradación de la democracia</a>,<em>La Ciudad Futura</em>, vol. 38, no. Suplemento/12, 1994.</li></ol><h2 id="1995">1995</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1995-etica-derechos-humanos/">Ética y derechos humanos (en un estado de guerra)</a>, in Cristina Motta and Adela Cortina Orts (eds.)<em>Ética y conflicto: lecturas para una transición democrática</em>, Bogotá, 1995, pp. 3–18. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-etica-derechos-humanos/">Ética y derechos humanos (en un estado de guerra)</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em>, Buenos Aires, 2007, pp. 126–136.</li></ol><h2 id="1996">1996</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1996-radical-evil-trial/"><em>Radical evil on trial</em></a>, New Haven, 1996. Prints, with corrections, the 1993 manuscript. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-1997-juicio-mal-absoluto/"><em>Juicio al mal absoluto: Los fundamentos y la historia del juicio a las juntas del Proceso</em></a>, Buenos Aires, 1997.</li><li>Carlos Santiago Nino,<a href="/works/nino-1996-constitution-deliberative-democracy/"><em>The constitution of deliberative democracy</em></a>, New Haven, 1996. Prints, with corrections, the 1993 manuscript. Spanish translation: Carlos Santiago Nino,<a href="/works/nino-1997-constitucion-democracia-deliberativa/"><em>La constitución de la democracia deliberativa</em></a>, Barcelona, 1997.</li><li>Carlos Santiago Nino,<a href="/works/nino-1996-hyperpresidentialism-constitutional-reform/">Hyperpresidentialism and constitutional reform in Argentina</a>, in A. Lijphart and C. H. Waisman (eds.)<em>Institutional design in new democracies: Eastern Europe and Latin America</em>, Boulder, 1996, pp. 161–174.</li><li>Carlos Santiago Nino,<a href="/works/nino-1996-kant-versus-hegel/">Kant versus Hegel, otra vez</a>,<em>Agora</em>, vol. 4, no. 2, 1996, pp. 87–102. Reprinted in Carlos Santiago Nino,<a href="/works/nino-1996-kant-versus-hegel-la-politica/">Kant versus Hegel, otra vez</a>,<em>La política</em>, vol. 1, 1996, pp. 123–135.</li></ol><h2 id="1998">1998</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1998-objecion-conciencia-libertad/">Objeción de conciencia, libertad religiosa, derecho a la vida e interés general</a>, in Renato Rabbi-Baldi Cabanillas (ed.)<em>Los derechos individuales ante el interés general: análisis de casos jurisprudenciales relevantes</em>, Buenos Aires, 1998, pp. 183–189.</li></ol><h2 id="1999">1999</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-1999-subjetivismo-objetivismo-derecho/">Subjetivismo y objetivismo en el derecho penal</a>,<em>Revista jurídica de la Universidad Autónoma de Madrid</em>, vol. 1, 1999, pp. 47–82. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2008-subjetivismo-objetivismo/">Subjetivismo y objetivismo en el derecho penal</a>, in Gustavo Maurino (ed.)<em>Fundamentos de derecho penal</em>, Buenos Aires, 2008, pp. 65–97.</li></ol><h2 id="2001">2001</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-2001-utilitarismo/">Utilitarismo</a>, in Torcuato S Di Tella et al. (ed.)<em>Diccionario de ciencias sociales y políticas</em>, Buenos Aires, 2001, pp. 709–714. Reprinted in Carlos Santiago Nino,<a href="/works/nino-2007-utilitarismo/">Utilitarismo</a>, in Gustavo Maurino (ed.)<em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em>, Buenos Aires, 2007, pp. 91–97.</li></ol><h2 id="2007">2007</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-2007-derecho-moral-politica/"><em>Derecho, moral y política 1: Metaética, ética normativa y teoría jurídica</em></a>, Buenos Aires, 2007.</li><li>Carlos Santiago Nino,<a href="/works/nino-2007-derecho-moral-politicaa/"><em>Derecho, moral y política 2: Fundamentos del liberalismo político: derechos humanos y democracia deliberativa</em></a>, Buenos Aires, 2007.</li></ol><h2 id="2008">2008</h2><ol><li>Gustavo Maurino (ed.),<a href="/works/maurino-2008-fundamentos-de-derecho-penal/"><em>Fundamentos de derecho penal</em></a>, Buenos Aires, 2008.</li></ol><h2 id="2013">2013</h2><ol><li>Carlos Santiago Nino,<a href="/works/nino-2013-ocho-lecciones-etica/"><em>Ocho lecciones sobre ética y derecho: para pensar la democracia</em></a>, Buenos Aires, 2013.</li><li>Carlos Santiago Nino,<a href="/works/nino-2013-teoria-justicia-democracia/"><em>Una teoría de la justicia para la democracia: hacer justicia, pensar la igualdad y defender libertades</em></a>, Buenos Aires, 2013.</li></ol>
]]></description></item><item><title>My beliefs, updated</title><link>https://stafforini.com/notes/my-beliefs-updated/</link><pubDate>Sun, 08 Nov 2020 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/my-beliefs-updated/</guid><description>&lt;![CDATA[<p>Back in 2015, I published<a href="/notes/my-beliefs/">a post</a> listing my beliefs on various propositions. This post updates that list to reflect what I currently believe. The new table also has a new column, indicating the resilience of each belief, defined as the likelihood that my credences will change if I thought more about the topic.</p><p>Note that, although the credences stated in the 2015 post are outdated, the substantive comments included there still largely reflect my current thinking. Accordingly, you may still want to check out that post if you are curious about why I hold these beliefs to the degree that I do.</p><table><thead><tr><th><strong>Proposition</strong></th><th><strong>Credence</strong></th><th><strong>Resilience</strong></th></tr></thead><tbody><tr><td>&ldquo;Aesthetic value: objective or subjective?&rdquo; Answer: subjective</td><td>100%</td><td>high</td></tr><tr><td>Artificial general intelligence (AGI) is possible in principle</td><td>95%</td><td>highish</td></tr><tr><td>Compatibilism on free will</td><td>10%</td><td>highish</td></tr><tr><td>&ldquo;Abstract objects: Platonism or nominalism?&rdquo; Answer: nominalism</td><td>95%</td><td>highish</td></tr><tr><td>Moral anti-realism</td><td>30%</td><td>medium</td></tr><tr><td>Humans will eventually build human-level AGI conditional on no other major intervening disruptions to civilization as we know it</td><td>85%</td><td>highish</td></tr><tr><td>We live in at least a Level I multiverse</td><td>30%</td><td>low</td></tr><tr><td>Type-A physicalism regarding consciousness</td><td>10%</td><td>medium</td></tr><tr><td>Eternalism on philosophy of time</td><td>95%</td><td>medium</td></tr><tr><td>Earth will eventually be controlled by a singleton of some sort</td><td>60%</td><td>medium</td></tr><tr><td>Human-inspired colonization of space will cause net suffering if it happens</td><td>10%</td><td>highish</td></tr><tr><td>Many worlds interpretation of quantum mechanics (or close kin)</td><td>55%</td><td>lowish</td></tr><tr><td>Soft AGI takeoff</td><td>60%</td><td>lowish</td></tr><tr><td>By at least 10 years before human-level AGI is built, debate about AGI risk will be as mainstream as global warming is in 2015</td><td>55%</td><td>medium</td></tr><tr><td>Human-controlled AGI would result in less expected suffering than uncontrolled, as judged by the beliefs I would hold if I thought about the problem for another 10 years</td><td>5%</td><td>highish</td></tr><tr><td>A government will build the first human-level AGI, assuming humans build one at all</td><td>35%</td><td>lowish</td></tr><tr><td>Climate change will cause net suffering</td><td>55%</td><td>lowish</td></tr><tr><td>By 2100, if biological humans still exist, most of them will regard factory farming as a great evil of the past</td><td>70%</td><td>medium</td></tr><tr><td>The effective-altruism movement, all things considered, reduces rather than increases suffering in the far future [NB: I think EA very likely reduces<em>net</em> suffering in expectation; see comments<a href="/notes/my-beliefs/">here</a>.]</td><td>35%</td><td>medium</td></tr><tr><td>Electing more liberal politicians reduces net suffering in the far future</td><td>55%</td><td>lowish</td></tr><tr><td>Faster technological innovation increases net suffering in the far future</td><td>50%</td><td>medium</td></tr><tr><td>&ldquo;Science: scientific realism or scientific anti-realism?&rdquo; Answer: realism</td><td>95%</td><td>highish</td></tr><tr><td>At bottom, physics is digital</td><td>15%</td><td>low</td></tr><tr><td>Cognitive closure of some philosophical problems</td><td>80%</td><td>medium</td></tr><tr><td>Rare Earth explanation of Fermi Paradox</td><td>10%</td><td>lowish</td></tr><tr><td>Crop cultivation prevents net suffering</td><td>50%</td><td>medium</td></tr><tr><td>Conditional on a government building the first human-level AGI, it will be the USA (rather than China, etc.)</td><td>45%</td><td>medium</td></tr><tr><td>Earth-originating intelligence will colonize the entire galaxy (ignoring anthropic arguments)</td><td>15%</td><td>medium</td></tr><tr><td>Faster economic growth will cause net suffering in the far future</td><td>50%</td><td>medium</td></tr><tr><td>Whole brain emulation will come before de novo AGI, assuming both are possible to build</td><td>40%</td><td>medium</td></tr><tr><td>Modal realism</td><td>20%</td><td>lowish</td></tr><tr><td>The multiverse is finite</td><td>70%</td><td>low</td></tr><tr><td>A world government will develop before human-level AGI</td><td>10%</td><td>highish</td></tr><tr><td>Wild-animal suffering will be a mainstream moral issue by 2100, conditional on biological humans still existing</td><td>15%</td><td>medium</td></tr><tr><td>Humans will go extinct within millions of years for some reason other than AGI</td><td>40%</td><td>medium</td></tr><tr><td>A design very close to CEV will be implemented in humanity&rsquo;s AGI, conditional on AGI being built (excluding other value-learning approaches and other machine-ethics proposals)</td><td>5%</td><td>medium</td></tr><tr><td>Negative utilitarianism focused on extreme suffering</td><td>1%</td><td>highish</td></tr><tr><td>Ethical pluralism for other values (happiness, love, friendship, knowledge, accomplishment, diversity, paperclips, and other things that agents care about)</td><td>0%</td><td>high</td></tr><tr><td>hedonic experience is most valuable</td><td>95%</td><td>high</td></tr><tr><td>preference frustration is most valuable</td><td>3%</td><td>high</td></tr></tbody></table>
]]></description></item><item><title>Situational Awareness LP</title><link>https://stafforini.com/notes/situational-awareness-lp/</link><pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/situational-awareness-lp/</guid><description>&lt;![CDATA[<p><strong>Situational Awareness LP</strong> is a hedge fund founded in 2024 by Leopold Aschenbrenner and co-managed by Carl Shulman. It is backed by Patrick &amp; John Collison, Daniel Gross, and Nat Friedman. The fund&rsquo;s thesis is explicitly AGI-focused, pursuing an opportunistic approach to public equities and strategic investments in semiconductor companies and energy infrastructure.</p><h2 id="the-copycat-approach">The copycat approach</h2><p>Investing directly in the fund requires a $25M minimum, a two-year lockup followed by quarterly redemptions over two more years, and Qualified Purchaser accreditation. The fund also has the standard &ldquo;2 and 20&rdquo; fee structure. If those barriers are too much for you, there is an alternative. Institutional investment managers with over $100M in qualifying assets must file Form 13F with the United States Securities and Exchange Commission (SEC) each quarter, disclosing their long equity positions, options, and convertible bonds. Filings are due 45 days after quarter-end and are published on the SEC&rsquo;s<a href="https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&amp;CIK=0002045724&amp;type=13F&amp;dateb=&amp;owner=include&amp;count=40">EDGAR system</a>.</p><p>This approach has significant limitations, however: the copycat sees each portfolio only after it is disclosed, not when the fund actually trades into it;<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 13F filings exclude short positions, foreign-listed securities, and non-equity assets; and, for options, filings report only the notional value of the underlying shares, omitting strike prices or expirations. Still, the loss of fidelity may be acceptable if one is sufficiently bullish on the fund&rsquo;s strategy and wants a simple way to get exposure to its public equity bets.</p><h2 id="backtesting-the-strategy">Backtesting the strategy</h2><p>A trader interested in pursuing the strategy would proceed as follows. Each time a 13F filing is published (the &ldquo;filing date&rdquo;, typically ~45 days after quarter-end), they would buy the disclosed portfolio at that day’s closing prices, weighting each position by its reported dollar value. They would hold that portfolio unchanged until the next filing is published, at which point they would rebalance to match the new disclosure.</p><p>We can backtest the strategy using all existing filings and calculating its returns to date. The script below computes compounded returns in two modes:<em>equity-only</em> (long stock positions reweighted to 100%, ignoring options) and<em>full exposure</em> (calls treated as long stock, puts as short stock—a rough proxy since, as noted, strikes and expirations are undisclosed). The last period always runs from the most recent filing date to today’s date, so re-evaluating the script updates that partial-period figure automatically.</p><details><summary>Code</summary><div class="details"><p><a id="code-snippet--sa-data"/></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># ── SA LP 13F data fetcher ─────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="c1"># Fetches all 13F-HR filings from SEC EDGAR for Situational Awareness LP,</span></span></span><span class="line"><span class="cl"><span class="c1"># parses the infotable XML, and resolves CUSIPs to tickers.</span></span></span><span class="line"><span class="cl"><span class="c1"># Output: JSON with one entry per quarterly filing, each containing</span></span></span><span class="line"><span class="cl"><span class="c1"># the filing date, quarter label, and a list of holdings.</span></span></span><span class="line"><span class="cl"><span class="c1"># Caches results in CACHE_DIR to avoid redundant SEC requests.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">urllib.request</span><span class="o">,</span><span class="nn">re</span><span class="o">,</span><span class="nn">json</span><span class="o">,</span><span class="nn">sys</span><span class="o">,</span><span class="nn">time</span><span class="o">,</span><span class="nn">os</span><span class="o">,</span><span class="nn">xml.etree.ElementTree</span><span class="k">as</span><span class="nn">ET</span></span></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">datetime</span><span class="kn">import</span><span class="n">datetime</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Configuration (update these for your environment) ──────────────</span></span></span><span class="line"><span class="cl"><span class="n">SEC_UA</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'SEC_USER_AGENT'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'stafforini.com situational-awareness-lp research; contact via stafforini.com'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">CACHE_DIR</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/.cache'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">CIK</span><span class="o">=</span><span class="s1">'2045724'</span></span></span><span class="line"><span class="cl"><span class="n">BASE</span><span class="o">=</span><span class="sa">f</span><span class="s1">'https://www.sec.gov/Archives/edgar/data/</span><span class="si">{</span><span class="n">CIK</span><span class="si">}</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="n">NS</span><span class="o">=</span><span class="p">{</span><span class="s1">'ns'</span><span class="p">:</span><span class="s1">'http://www.sec.gov/edgar/document/thirteenf/informationtable'</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">CACHE</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">CACHE_DIR</span><span class="p">,</span><span class="s1">'sa-lp-13f.json'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">CUSIP_TICKER</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'038169207'</span><span class="p">:</span><span class="s1">'APLD'</span><span class="p">,</span><span class="s1">'05614L209'</span><span class="p">:</span><span class="s1">'BW'</span><span class="p">,</span><span class="s1">'09173B107'</span><span class="p">:</span><span class="s1">'BITF'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'093712107'</span><span class="p">:</span><span class="s1">'BE'</span><span class="p">,</span><span class="s1">'093712AH0'</span><span class="p">:</span><span class="s1">'BE'</span><span class="p">,</span><span class="s1">'11135F101'</span><span class="p">:</span><span class="s1">'AVGO'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'12514G108'</span><span class="p">:</span><span class="s1">'CIFR'</span><span class="p">,</span><span class="s1">'17253J106'</span><span class="p">:</span><span class="s1">'CIFR'</span><span class="p">,</span><span class="s1">'17253JAA4'</span><span class="p">:</span><span class="s1">'CIFR'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'18452B209'</span><span class="p">:</span><span class="s1">'CLSK'</span><span class="p">,</span><span class="s1">'19247G107'</span><span class="p">:</span><span class="s1">'COHR'</span><span class="p">,</span><span class="s1">'21037T109'</span><span class="p">:</span><span class="s1">'CEG'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'21873S108'</span><span class="p">:</span><span class="s1">'CRWV'</span><span class="p">,</span><span class="s1">'21874A106'</span><span class="p">:</span><span class="s1">'CORZ'</span><span class="p">,</span><span class="s1">'26884L109'</span><span class="p">:</span><span class="s1">'EQT'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'36168Q104'</span><span class="p">:</span><span class="s1">'GLXY'</span><span class="p">,</span><span class="s1">'36317J209'</span><span class="p">:</span><span class="s1">'GLXY'</span><span class="p">,</span><span class="s1">'44282L109'</span><span class="p">:</span><span class="s1">'HUT'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'44812J104'</span><span class="p">:</span><span class="s1">'HUT'</span><span class="p">,</span><span class="s1">'456788108'</span><span class="p">:</span><span class="s1">'INFY'</span><span class="p">,</span><span class="s1">'458140100'</span><span class="p">:</span><span class="s1">'INTC'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'49338L103'</span><span class="p">:</span><span class="s1">'KRC'</span><span class="p">,</span><span class="s1">'49427F108'</span><span class="p">:</span><span class="s1">'KRC'</span><span class="p">,</span><span class="s1">'53115L104'</span><span class="p">:</span><span class="s1">'LBRT'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'55024U109'</span><span class="p">:</span><span class="s1">'LITE'</span><span class="p">,</span><span class="s1">'55024UAD1'</span><span class="p">:</span><span class="s1">'LITE'</span><span class="p">,</span><span class="s1">'573874104'</span><span class="p">:</span><span class="s1">'MRVL'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'577933104'</span><span class="p">:</span><span class="s1">'MRVL'</span><span class="p">,</span><span class="s1">'593787101'</span><span class="p">:</span><span class="s1">'MU'</span><span class="p">,</span><span class="s1">'593787105'</span><span class="p">:</span><span class="s1">'MU'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'595112103'</span><span class="p">:</span><span class="s1">'MU'</span><span class="p">,</span><span class="s1">'607828100'</span><span class="p">:</span><span class="s1">'MOD'</span><span class="p">,</span><span class="s1">'67066G104'</span><span class="p">:</span><span class="s1">'NVDA'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'683344105'</span><span class="p">:</span><span class="s1">'ONTO'</span><span class="p">,</span><span class="s1">'68340J108'</span><span class="p">:</span><span class="s1">'ONTO'</span><span class="p">,</span><span class="s1">'73933G202'</span><span class="p">:</span><span class="s1">'PSIX'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'73933H100'</span><span class="p">:</span><span class="s1">'PSIX'</span><span class="p">,</span><span class="s1">'743344109'</span><span class="p">:</span><span class="s1">'PUMP'</span><span class="p">,</span><span class="s1">'74347M108'</span><span class="p">:</span><span class="s1">'PUMP'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'76754A103'</span><span class="p">:</span><span class="s1">'RIOT'</span><span class="p">,</span><span class="s1">'767292105'</span><span class="p">:</span><span class="s1">'RIOT'</span><span class="p">,</span><span class="s1">'80004C200'</span><span class="p">:</span><span class="s1">'SNDK'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'80106M109'</span><span class="p">:</span><span class="s1">'SNDK'</span><span class="p">,</span><span class="s1">'83418M103'</span><span class="p">:</span><span class="s1">'SEI'</span><span class="p">,</span><span class="s1">'87422Q109'</span><span class="p">:</span><span class="s1">'TLN'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'87425V106'</span><span class="p">:</span><span class="s1">'TLN'</span><span class="p">,</span><span class="s1">'874039100'</span><span class="p">:</span><span class="s1">'TSM'</span><span class="p">,</span><span class="s1">'89854H102'</span><span class="p">:</span><span class="s1">'TSEM'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'92189F106'</span><span class="p">:</span><span class="s1">'SMH'</span><span class="p">,</span><span class="s1">'92189F676'</span><span class="p">:</span><span class="s1">'SMH'</span><span class="p">,</span><span class="s1">'92535P101'</span><span class="p">:</span><span class="s1">'VRT'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'92537N108'</span><span class="p">:</span><span class="s1">'VRT'</span><span class="p">,</span><span class="s1">'92840M102'</span><span class="p">:</span><span class="s1">'VST'</span><span class="p">,</span><span class="s1">'958102105'</span><span class="p">:</span><span class="s1">'WDC'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'958102AT2'</span><span class="p">:</span><span class="s1">'WDC'</span><span class="p">,</span><span class="s1">'98321C108'</span><span class="p">:</span><span class="s1">'WYFI'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'G1110V104'</span><span class="p">:</span><span class="s1">'BITF'</span><span class="p">,</span><span class="s1">'G1189L107'</span><span class="p">:</span><span class="s1">'BTDR'</span><span class="p">,</span><span class="s1">'G11448100'</span><span class="p">:</span><span class="s1">'BTDR'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'G7945J104'</span><span class="p">:</span><span class="s1">'STX'</span><span class="p">,</span><span class="s1">'G7997R103'</span><span class="p">:</span><span class="s1">'STX'</span><span class="p">,</span><span class="s1">'G96115103'</span><span class="p">:</span><span class="s1">'WYFI'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'M87915274'</span><span class="p">:</span><span class="s1">'TSEM'</span><span class="p">,</span><span class="s1">'Q4982L109'</span><span class="p">:</span><span class="s1">'IREN'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">fetch</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">req</span><span class="o">=</span><span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s1">'User-Agent'</span><span class="p">:</span><span class="n">SEC_UA</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="k">with</span><span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">)</span><span class="k">as</span><span class="n">resp</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">resp</span><span class="o">.</span><span class="n">read</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">find_infotable_filename</span><span class="p">(</span><span class="n">acc</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Discover the infotable XML filename for a filing via EFTS, then -index.htm."""</span></span></span><span class="line"><span class="cl"><span class="c1"># EFTS search (fast, reliable)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">efts</span><span class="o">=</span><span class="sa">f</span><span class="s1">'https://efts.sec.gov/LATEST/search-index?q=%22</span><span class="si">{</span><span class="n">acc</span><span class="si">}</span><span class="s1">%22'</span></span></span><span class="line"><span class="cl"><span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">fetch</span><span class="p">(</span><span class="n">efts</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">hit</span><span class="ow">in</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'hits'</span><span class="p">,</span><span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'hits'</span><span class="p">,</span><span class="p">[]):</span></span></span><span class="line"><span class="cl"><span class="n">doc_id</span><span class="o">=</span><span class="n">hit</span><span class="p">[</span><span class="s1">'_id'</span><span class="p">]</span><span class="c1"># format: "accession:filename"</span></span></span><span class="line"><span class="cl"><span class="n">filename</span><span class="o">=</span><span class="n">doc_id</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">,</span><span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="k">if</span><span class="s1">':'</span><span class="ow">in</span><span class="n">doc_id</span><span class="k">else</span><span class="s1">''</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">filename</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">'.xml'</span><span class="p">)</span><span class="ow">and</span><span class="s1">'primary_doc'</span><span class="ow">not</span><span class="ow">in</span><span class="n">filename</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">filename</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">pass</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: filing index page</span></span></span><span class="line"><span class="cl"><span class="n">acc_path</span><span class="o">=</span><span class="n">acc</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'-'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">html</span><span class="o">=</span><span class="n">fetch</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">BASE</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="n">acc_path</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="n">acc</span><span class="si">}</span><span class="s1">-index.htm'</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">href</span><span class="ow">in</span><span class="n">re</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="sa">r</span><span class="s1">'href="([^"]*\.xml)"'</span><span class="p">,</span><span class="n">html</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">fn</span><span class="o">=</span><span class="n">href</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">fn</span><span class="o">!=</span><span class="s1">'primary_doc.xml'</span><span class="ow">and</span><span class="s1">'xslForm'</span><span class="ow">not</span><span class="ow">in</span><span class="n">href</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">fn</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">pass</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">parse_infotable</span><span class="p">(</span><span class="n">xml_data</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">root</span><span class="o">=</span><span class="n">ET</span><span class="o">.</span><span class="n">fromstring</span><span class="p">(</span><span class="n">xml_data</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">info</span><span class="ow">in</span><span class="n">root</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s1">'.//ns:infoTable'</span><span class="p">,</span><span class="n">NS</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">cusip</span><span class="o">=</span><span class="n">info</span><span class="o">.</span><span class="n">findtext</span><span class="p">(</span><span class="s1">'ns:cusip'</span><span class="p">,</span><span class="s1">''</span><span class="p">,</span><span class="n">NS</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">value</span><span class="o">=</span><span class="nb">int</span><span class="p">(</span><span class="n">info</span><span class="o">.</span><span class="n">findtext</span><span class="p">(</span><span class="s1">'ns:value'</span><span class="p">,</span><span class="s1">'0'</span><span class="p">,</span><span class="n">NS</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">putcall</span><span class="o">=</span><span class="n">info</span><span class="o">.</span><span class="n">findtext</span><span class="p">(</span><span class="s1">'ns:putCall'</span><span class="p">,</span><span class="s1">''</span><span class="p">,</span><span class="n">NS</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="n">CUSIP_TICKER</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cusip</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">ticker</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">issuer</span><span class="o">=</span><span class="n">info</span><span class="o">.</span><span class="n">findtext</span><span class="p">(</span><span class="s1">'ns:nameOfIssuer'</span><span class="p">,</span><span class="s1">''</span><span class="p">,</span><span class="n">NS</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"WARNING: Unknown CUSIP</span><span class="si">{</span><span class="n">cusip</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">issuer</span><span class="si">}</span><span class="s2">)"</span><span class="p">,</span><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="sa">f</span><span class="s2">"UNKNOWN_</span><span class="si">{</span><span class="n">cusip</span><span class="si">}</span><span class="s2">"</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="o">=</span><span class="s1">'put'</span><span class="k">if</span><span class="n">putcall</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="s1">'call'</span><span class="k">if</span><span class="n">putcall</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="s1">'long'</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">"ticker"</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span><span class="s2">"type"</span><span class="p">:</span><span class="n">pos_type</span><span class="p">,</span><span class="s2">"value"</span><span class="p">:</span><span class="n">value</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">holdings</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">quarter_from_filing_date</span><span class="p">(</span><span class="n">fdate</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">fdate</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">m</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="n">d</span><span class="o">.</span><span class="n">month</span><span class="p">,</span><span class="n">d</span><span class="o">.</span><span class="n">year</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">m</span><span class="o">&lt;=</span><span class="mi">3</span><span class="p">:</span><span class="k">return</span><span class="sa">f</span><span class="s1">'Q4_</span><span class="si">{</span><span class="n">y</span><span class="o">-</span><span class="mi">1</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">y</span><span class="o">-</span><span class="mi">1</span><span class="si">}</span><span class="s1">-12-31'</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">m</span><span class="o">&lt;=</span><span class="mi">6</span><span class="p">:</span><span class="k">return</span><span class="sa">f</span><span class="s1">'Q1_</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">-03-31'</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">m</span><span class="o">&lt;=</span><span class="mi">9</span><span class="p">:</span><span class="k">return</span><span class="sa">f</span><span class="s1">'Q2_</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">-06-30'</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span><span class="k">return</span><span class="sa">f</span><span class="s1">'Q3_</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s1">-09-30'</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">load_cache</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">CACHE</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">with</span><span class="nb">open</span><span class="p">(</span><span class="n">CACHE</span><span class="p">)</span><span class="k">as</span><span class="n">f</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{</span><span class="s2">"filings"</span><span class="p">:</span><span class="p">[]}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">save_cache</span><span class="p">(</span><span class="n">data</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">CACHE</span><span class="p">),</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">with</span><span class="nb">open</span><span class="p">(</span><span class="n">CACHE</span><span class="p">,</span><span class="s1">'w'</span><span class="p">)</span><span class="k">as</span><span class="n">f</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="n">f</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cached</span><span class="o">=</span><span class="n">load_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">cached_quarters</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">cached</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]}</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{</span><span class="s2">"filings"</span><span class="p">:</span><span class="nb">list</span><span class="p">(</span><span class="n">cached</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">])}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">subs_url</span><span class="o">=</span><span class="sa">f</span><span class="s1">'https://data.sec.gov/submissions/CIK</span><span class="si">{</span><span class="n">CIK</span><span class="o">.</span><span class="n">zfill</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span><span class="si">}</span><span class="s1">.json'</span></span></span><span class="line"><span class="cl"><span class="n">subs</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">fetch</span><span class="p">(</span><span class="n">subs_url</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">recent</span><span class="o">=</span><span class="n">subs</span><span class="p">[</span><span class="s1">'filings'</span><span class="p">][</span><span class="s1">'recent'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">accessions</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="p">[(</span><span class="n">recent</span><span class="p">[</span><span class="s1">'filingDate'</span><span class="p">][</span><span class="n">i</span><span class="p">],</span><span class="n">recent</span><span class="p">[</span><span class="s1">'accessionNumber'</span><span class="p">][</span><span class="n">i</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">recent</span><span class="p">[</span><span class="s1">'form'</span><span class="p">]))</span><span class="k">if</span><span class="n">recent</span><span class="p">[</span><span class="s1">'form'</span><span class="p">][</span><span class="n">i</span><span class="p">]</span><span class="o">==</span><span class="s1">'13F-HR'</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">fdate</span><span class="p">,</span><span class="n">acc</span><span class="ow">in</span><span class="n">accessions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">quarter</span><span class="p">,</span><span class="n">quarter_end</span><span class="o">=</span><span class="n">quarter_from_filing_date</span><span class="p">(</span><span class="n">fdate</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">quarter</span><span class="ow">in</span><span class="n">cached_quarters</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">filename</span><span class="o">=</span><span class="n">find_infotable_filename</span><span class="p">(</span><span class="n">acc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">filename</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not find infotable for</span><span class="si">{</span><span class="n">acc</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">acc_path</span><span class="o">=</span><span class="n">acc</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'-'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">xml</span><span class="o">=</span><span class="n">fetch</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">BASE</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="n">acc_path</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="n">parse_infotable</span><span class="p">(</span><span class="n">xml</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s2">"quarter"</span><span class="p">:</span><span class="n">quarter</span><span class="p">,</span><span class="s2">"quarter_end"</span><span class="p">:</span><span class="n">quarter_end</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"filing_date"</span><span class="p">:</span><span class="n">fdate</span><span class="p">,</span><span class="s2">"holdings"</span><span class="p">:</span><span class="n">holdings</span><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">f</span><span class="p">:</span><span class="n">f</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="n">save_cache</span><span class="p">(</span><span class="n">result</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="k">as</span><span class="n">e</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">result</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"SEC fetch error (</span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">); using cache"</span><span class="p">,</span><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">raise</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">result</span><span class="p">)</span></span></span></code></pre></div><p><a id="code-snippet--sa-perf"/></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">json</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">yfinance</span><span class="k">as</span><span class="nn">yf</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">pandas</span><span class="k">as</span><span class="nn">pd</span></span></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">datetime</span><span class="kn">import</span><span class="n">datetime</span><span class="p">,</span><span class="n">timedelta</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">numpy</span><span class="k">as</span><span class="nn">np</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">requests</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">time</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">os</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">warnings</span></span></span><span class="line"><span class="cl"><span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s1">'ignore'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Parse data from the scraper block</span></span></span><span class="line"><span class="cl"><span class="n">parsed</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="nb">str</span><span class="p">)</span><span class="k">else</span><span class="n">data</span></span></span><span class="line"><span class="cl"><span class="n">filings</span><span class="o">=</span><span class="n">parsed</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Build internal structures</span></span></span><span class="line"><span class="cl"><span class="n">filing_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarter_end_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter_end"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarters</span><span class="o">=</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Convert holdings list to dict keyed by quarter.</span></span></span><span class="line"><span class="cl"><span class="c1"># Multiple positions in the same ticker with different types are aggregated</span></span></span><span class="line"><span class="cl"><span class="c1"># by value per (ticker, type) pair.</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">f</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">value</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"value"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="n">positions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]]</span><span class="o">=</span><span class="n">positions</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">get_prices</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">dates</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch close prices for tickers on specific dates."""</span></span></span><span class="line"><span class="cl"><span class="n">unique_tickers</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">tickers</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">dates</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="nb">min</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="nb">max</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">unique_tickers</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># yf.download returns MultiIndex columns (metric, ticker) for multiple tickers</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">unique_tickers</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">unique_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">series</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">date_str</span><span class="ow">in</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">target</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">after</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">after</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">after</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">before</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">before</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">before</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">prices</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the first available price on/after target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the last available price on/before target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&lt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_period_price_pair</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return start/end prices for a period using sensible boundary alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">start</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">end</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">p0</span><span class="o">=</span><span class="n">start</span></span></span><span class="line"><span class="cl"><span class="n">end_actual</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">end</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">end_actual</span><span class="o">&lt;</span><span class="n">start_actual</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_return</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">prices</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'equity_only'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_prices</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute weighted portfolio return between two dates.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions (call/put): if option_prices contains actual</span></span></span><span class="line"><span class="cl"><span class="s2"> historical option prices for the ticker, compute returns directly from</span></span></span><span class="line"><span class="cl"><span class="s2"> those prices. Otherwise fall back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> the parameters in option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_px</span><span class="o">=</span><span class="n">option_prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span><span class="k">if</span><span class="n">option_prices</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="nb">bool</span><span class="p">(</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">opt_px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">px</span><span class="o">=</span><span class="n">prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="n">p1</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing when no option price data</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">is_option</span><span class="ow">and</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="n">days_between</span><span class="p">(</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">)</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="c1"># When using actual option/BS prices the return already reflects</span></span></span><span class="line"><span class="cl"><span class="c1"># the directional bet, so sign is +1. The -1 for puts applies</span></span></span><span class="line"><span class="cl"><span class="c1"># only to the raw stock-price proxy path.</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_option_px</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="n">value</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">weighted_return</span><span class="o">/</span><span class="n">total_value</span><span class="k">if</span><span class="n">total_value</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">annualize</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">days</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Annualize a return over a given number of calendar days."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">days</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="mf">365.25</span><span class="o">/</span><span class="n">days</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">days_between</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="n">d2</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d2</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span><span class="o">.</span><span class="n">days</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">fmt</span><span class="p">(</span><span class="n">ret</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ret</span><span class="o">*</span><span class="mi">100</span><span class="si">:</span><span class="s2">+.2f</span><span class="si">}</span><span class="s2">%"</span><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="s2">"N/A"</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Collect all tickers and dates</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">positions</span><span class="ow">in</span><span class="n">holdings</span><span class="o">.</span><span class="n">values</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_</span><span class="p">)</span><span class="ow">in</span><span class="n">positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">'SPY'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">first_date</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="nb">set</span><span class="p">(</span><span class="n">filing_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="nb">set</span><span class="p">(</span><span class="n">quarter_end_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="p">{</span><span class="n">today</span><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="n">get_prices</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">),</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_dates</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Resolve `today` to the actual last available closing date.</span></span></span><span class="line"><span class="cl"><span class="c1"># yfinance may not have data for today (market still open or holiday),</span></span></span><span class="line"><span class="cl"><span class="c1"># so we look up what date SPY's price actually corresponds to.</span></span></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">requested_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return the actual trading date of the price stored under requested_date."""</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="s1">'SPY'</span><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">prices</span><span class="k">else</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">prices</span><span class="p">),</span><span class="kc">None</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">ref</span><span class="ow">or</span><span class="n">requested_date</span><span class="ow">not</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="n">target_price</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">][</span><span class="n">requested_date</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="c1"># Re-download a small window to find the real date of this price</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">ref</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">][</span><span class="n">ref</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="s1">'Close'</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">iloc</span><span class="p">[:,</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">dt</span><span class="p">,</span><span class="n">px</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">val</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">)</span><span class="k">else</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">abs</span><span class="p">(</span><span class="n">val</span><span class="o">-</span><span class="n">target_price</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ts</span><span class="o">=</span><span class="n">dt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span><span class="nb">tuple</span><span class="p">)</span><span class="k">else</span><span class="n">dt</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">ts</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today_resolved</span><span class="o">=</span><span class="n">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today_resolved</span><span class="o">!=</span><span class="n">today</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">today_resolved</span><span class="p">]</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">today_resolved</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_daily</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download daily close prices from yfinance, handling MultiIndex.</span></span></span><span class="line"><span class="cl"><span class="s2"> Dates are 'YYYY-MM-DD' strings. Adds a small buffer for trading-day alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">tickers_sorted</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">tickers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">start_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">end_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">tickers_sorted</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">tickers_sorted</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">close</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Historical option prices via Alpha Vantage ----------------------------</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_DIR</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/notes/.sa-lp-option-cache'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_AV_BASE</span><span class="o">=</span><span class="s1">'https://www.alphavantage.co/query'</span></span></span><span class="line"><span class="cl"><span class="n">_AV_RATE_DELAY</span><span class="o">=</span><span class="mf">0.85</span><span class="c1"># seconds between requests (75 req/min limit)</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_COLUMNS</span><span class="o">=</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="ow">not</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">raise</span><span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unsupported option type:</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_empty_option_cache</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">columns</span><span class="o">=</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">-</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Load cached option data for a ticker/type. Returns DataFrame or empty."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">=</span><span class="p">[</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="c1"># Pre-fix caches were call-only and named TICKER.csv. They are safe to</span></span></span><span class="line"><span class="cl"><span class="c1"># reuse for calls but must not be reused for puts.</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">legacy_path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy_path</span><span class="ow">not</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">legacy_path</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">path</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'option_type'</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="s1">'call'</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_datetime</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span><span class="o">.</span><span class="n">dt</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">.</span><span class="n">fillna</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">frames</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="n">frames</span><span class="p">,</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_numeric</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">cache</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">df</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Persist typed option cache to CSV."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">path</span><span class="p">,</span><span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch the full option chain for ticker on a given date from Alpha Vantage."""</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'function'</span><span class="p">:</span><span class="s1">'HISTORICAL_OPTIONS'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'symbol'</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">date_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'apikey'</span><span class="p">:</span><span class="n">api_key</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">=</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_AV_BASE</span><span class="p">,</span><span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">body</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">json</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">body</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span><span class="p">[])</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">270</span><span class="p">),</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">456</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'option_type'</span><span class="p">,</span><span class="n">option_type</span><span class="p">))</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">strike</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">contract</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_best_contract</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Select the best-matching call/put contract from an option chain.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Criteria: matching option type, expiry 9-15 months from ref_date,</span></span></span><span class="line"><span class="cl"><span class="s2"> absolute delta closest to 0.15. Returns dict with type, strike, expiry,</span></span></span><span class="line"><span class="cl"><span class="s2"> delta, price or None.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">abs_delta</span><span class="o">=</span><span class="nb">abs</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">abs_delta</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="c1"># Price: prefer mid if available, else last</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="c1"># Pick contract with absolute delta closest to 0.15.</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_parse_option_price</span><span class="p">(</span><span class="n">contract</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Extract a price from an Alpha Vantage option contract record."""</span></span></span><span class="line"><span class="cl"><span class="n">bid</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'bid'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">ask</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ask'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">last</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'last'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">bid</span><span class="ow">and</span><span class="n">ask</span><span class="ow">and</span><span class="n">bid</span><span class="o">&gt;</span><span class="mi">0</span><span class="ow">and</span><span class="n">ask</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">bid</span><span class="o">+</span><span class="n">ask</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">last</span><span class="ow">and</span><span class="n">last</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">last</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_safe_float</span><span class="p">(</span><span class="n">val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="n">val</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_cached_contract_price</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">price</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_extract_contract_price</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Find the price of a specific option contract."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">])</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'expiration'</span><span class="p">)</span><span class="o">==</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_option_prices</span><span class="p">(</span><span class="n">option_positions</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">holdings</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download historical option prices from Alpha Vantage.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each (ticker, option_type) and each filing period:</span></span></span><span class="line"><span class="cl"><span class="s2"> 1. On the first trading day, fetch the chain and select the best contract</span></span></span><span class="line"><span class="cl"><span class="s2"> (matching type, expiry 9-15 months out, |delta| closest to 0.15).</span></span></span><span class="line"><span class="cl"><span class="s2"> 2. Lock in that contract for the period.</span></span></span><span class="line"><span class="cl"><span class="s2"> 3. Fetch the price of that contract on each subsequent trading day.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Returns</span></span></span><span class="line"><span class="cl"><span class="s2"> -------</span></span></span><span class="line"><span class="cl"><span class="s2"> per_period : dict {quarter_str: {(ticker, type): {date_str: float}}}</span></span></span><span class="line"><span class="cl"><span class="s2"> Option prices keyed by filing period then option position. Each period</span></span></span><span class="line"><span class="cl"><span class="s2"> has its own contract's prices, avoiding cross-contract mixing at</span></span></span><span class="line"><span class="cl"><span class="s2"> boundary dates where one period ends and the next begins.</span></span></span><span class="line"><span class="cl"><span class="s2"> fallback_positions : set</span></span></span><span class="line"><span class="cl"><span class="s2"> Option positions where no option data was found (need BS fallback).</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_positions</span><span class="o">=</span><span class="nb">sorted</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ALPHA_VANTAGE_KEY'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache_only</span><span class="o">=</span><span class="ow">not</span><span class="nb">bool</span><span class="p">(</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"WARNING: ALPHA_VANTAGE_KEY not set; using cached option "</span></span></span><span class="line"><span class="cl"><span class="s2">"prices where available and BS repricing elsewhere."</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">=</span><span class="p">{}</span><span class="c1"># {q: {(ticker, type): {date_str: price}}}</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip quarters where this exact option position is absent.</span></span></span><span class="line"><span class="cl"><span class="n">has_opts</span><span class="o">=</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">has_opts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="p">(</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">trading_days</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">bdate_range</span><span class="p">(</span><span class="n">period_start</span><span class="p">,</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">trading_days</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">first_day</span><span class="o">=</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Select contract on first trading day --</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">first_day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_best_contract</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">first_day</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">expiry</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Collect prices for this period (fresh dict per period) --</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">from_cache</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Fast path: read all matching prices from cache (no API calls).</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&lt;=</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Slow path: fetch each trading day from API</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">first_day</span><span class="p">]</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day</span><span class="ow">in</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cached_price</span><span class="o">=</span><span class="n">_cached_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cached_price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">cached_price</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_extract_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">day_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">expiry</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Accumulate per-period prices</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})[</span><span class="n">opt_key</span><span class="p">]</span><span class="o">=</span><span class="n">period_prices</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Persist new data to cache</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">new_rows</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">new_rows</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">([</span><span class="n">cache</span><span class="p">,</span><span class="n">new_df</span><span class="p">],</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">position_has_data</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">fetched</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">sys</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[options] Fetched</span><span class="si">{</span><span class="n">fetched</span><span class="si">}</span><span class="s2"> chain snapshots from Alpha Vantage"</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">per_period</span><span class="p">,</span><span class="n">fallback</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Fallback: Black-Scholes repricing for tickers without option data -----</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">scipy.stats</span><span class="kn">import</span><span class="n">norm</span><span class="k">as</span><span class="n">_norm</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_realized_vol</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">download_daily_fn</span><span class="p">,</span><span class="n">today_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute annualized realized vol from trailing 1-year daily returns."""</span></span></span><span class="line"><span class="cl"><span class="n">vol_start</span><span class="o">=</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">today_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">400</span><span class="p">))</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_df</span><span class="o">=</span><span class="n">download_daily_fn</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">vol_start</span><span class="p">,</span><span class="n">today_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">vol_df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">vol_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">series</span><span class="p">)</span><span class="o">&gt;</span><span class="mi">20</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">log_rets</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">series</span><span class="o">/</span><span class="n">series</span><span class="o">.</span><span class="n">shift</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span><span class="o">.</span><span class="n">tail</span><span class="p">(</span><span class="mi">252</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">log_rets</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">252</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_price</span><span class="p">(</span><span class="n">S</span><span class="p">,</span><span class="n">K</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Black-Scholes option price (assumes zero risk-free rate and dividends)."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">T</span><span class="o">&lt;=</span><span class="mi">0</span><span class="ow">or</span><span class="n">sigma</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">S</span><span class="o">-</span><span class="n">K</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">K</span><span class="o">-</span><span class="n">S</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">d1</span><span class="o">=</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">S</span><span class="o">/</span><span class="n">K</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">T</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">d2</span><span class="o">=</span><span class="n">d1</span><span class="o">-</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d1</span><span class="p">)</span><span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d2</span><span class="p">)</span><span class="o">-</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_option_return</span><span class="p">(</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">delta_t</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute option return from stock return using Black-Scholes repricing.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Normalizes S_0 = 1, so S_1 = 1 + stock_return and K = K_over_S.</span></span></span><span class="line"><span class="cl"><span class="s2"> T is time to expiry at period start; delta_t is time elapsed.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">V0</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">V1</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="o">+</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="nb">max</span><span class="p">(</span><span class="n">T</span><span class="o">-</span><span class="n">delta_t</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">V0</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">stock_return</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">V1</span><span class="o">/</span><span class="n">V0</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_DELTA</span><span class="o">=</span><span class="mf">0.15</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_T</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">build_option_params</span><span class="p">(</span><span class="n">option_tickers</span><span class="p">,</span><span class="n">ticker_vol</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build {ticker: (K_over_S_call, K_over_S_put, sigma)} for BS fallback."""</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">t</span><span class="ow">in</span><span class="n">option_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">t</span><span class="ow">not</span><span class="ow">in</span><span class="n">ticker_vol</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="o">=</span><span class="n">ticker_vol</span><span class="p">[</span><span class="n">t</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">srt</span><span class="o">=</span><span class="n">sigma</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">**</span><span class="mf">0.5</span></span></span><span class="line"><span class="cl"><span class="c1"># Call: delta = N(d1) = OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_call</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_call</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1"># Put: delta = N(d1) - 1 = -OPTION_DELTA, so N(d1) = 1 - OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_put</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_put</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_put</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">t</span><span class="p">]</span><span class="o">=</span><span class="p">(</span><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">daily_cumulative</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="n">mode</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">per_period_opt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build a daily series of cumulative growth factors for a given mode.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each filing period the portfolio weights are fixed. Each trading</span></span></span><span class="line"><span class="cl"><span class="s2"> day's weighted return is computed relative to the period's starting</span></span></span><span class="line"><span class="cl"><span class="s2"> prices, then chained with the prior period's cumulative growth.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions: uses per-period option prices from per_period_opt</span></span></span><span class="line"><span class="cl"><span class="s2"> when available; otherwise falls back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span></span></span><span class="line"><span class="cl"><span class="n">ps</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pe</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Trading days in this period</span></span></span><span class="line"><span class="cl"><span class="n">mask</span><span class="o">=</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">)</span><span class="o">&amp;</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">period_close</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_close</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Option prices for this period (keyed by (ticker, type) → prices)</span></span></span><span class="line"><span class="cl"><span class="n">quarter_opt</span><span class="o">=</span><span class="n">per_period_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})</span><span class="k">if</span><span class="n">per_period_opt</span><span class="k">else</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Determine portfolio weights and starting prices</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">weights</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="o">=</span><span class="p">{}</span><span class="c1"># track which positions use option prices</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Select price source for this position</span></span></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">has_opt</span><span class="o">=</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">quarter_opt</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">has_opt</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ticker_opt</span><span class="o">=</span><span class="n">quarter_opt</span><span class="p">[</span><span class="n">opt_key</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">opt_dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">ticker_opt</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">opt_dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">ticker_opt</span><span class="p">[</span><span class="n">opt_dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">src</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">avail</span><span class="o">=</span><span class="n">src</span><span class="p">[</span><span class="n">src</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avail</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">avail</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">weights</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">has_opt</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total_value</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Daily weighted return relative to period start</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip first day of subsequent periods (already recorded as last day</span></span></span><span class="line"><span class="cl"><span class="c1"># of the prior period) to avoid duplicate boundary dates.</span></span></span><span class="line"><span class="cl"><span class="n">start_idx</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="n">i</span><span class="o">&gt;</span><span class="mi">0</span><span class="k">else</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="c1"># Forward-fill: track last known option price so that gaps in</span></span></span><span class="line"><span class="cl"><span class="c1"># option data don't cause positions to vanish mid-period.</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="o">=</span><span class="p">{</span><span class="n">k</span><span class="p">:</span><span class="n">v</span><span class="k">for</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="ow">in</span><span class="n">start_prices</span><span class="o">.</span><span class="n">items</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">k</span><span class="p">)}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day_idx</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="n">start_idx</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">period_close</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">day</span><span class="o">=</span><span class="n">period_close</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">weights</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">quarter_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">,</span><span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">day_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">p1_val</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">last_opt</span><span class="o">.</span><span class="n">get</span><span class="p">((</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">period_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">period_close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1_val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1_val</span><span class="p">)</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing for option positions without option data</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="ow">not</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]):</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="p">(</span><span class="n">day</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="p">(</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span><span class="p">)</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cum_growth</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">weighted_return</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Chain: next period starts from the last day's growth factor</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">values_out</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="n">values_out</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">dates_out</span><span class="p">,</span><span class="n">values_out</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Compute copycat returns</span></span></span><span class="line"><span class="cl"><span class="n">header</span><span class="o">=</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Period'</span><span class="si">:</span><span class="s2">&lt;16</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Dates'</span><span class="si">:</span><span class="s2">&lt;24</span><span class="si">}</span><span class="s2"> "</span></span></span><span class="line"><span class="cl"><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Eq. only'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Full exp.'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'SPY'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"COPYCAT STRATEGY RETURNS"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"="</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">header</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"-"</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cum_eq</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">cum_full</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">cum_spy</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span></span></span><span class="line"><span class="cl"><span class="n">suffix</span><span class="o">=</span><span class="s2">" †"</span><span class="k">if</span><span class="n">i</span><span class="o">==</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="s2">""</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret_eq</span><span class="o">=</span><span class="n">compute_return</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">],</span><span class="n">prices</span><span class="p">,</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="p">,</span><span class="s1">'equity_only'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ret_full</span><span class="o">=</span><span class="n">compute_return</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">],</span><span class="n">prices</span><span class="p">,</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="p">,</span><span class="s1">'full'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ret_spy</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">prices</span><span class="ow">and</span><span class="n">start</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">]</span><span class="ow">and</span><span class="n">end</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">spy_p0</span><span class="p">,</span><span class="n">spy_p1</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">][</span><span class="n">start</span><span class="p">],</span><span class="n">prices</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">][</span><span class="n">end</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">spy_p0</span><span class="o">!=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ret_spy</span><span class="o">=</span><span class="p">(</span><span class="n">spy_p1</span><span class="o">-</span><span class="n">spy_p0</span><span class="p">)</span><span class="o">/</span><span class="n">spy_p0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret_eq</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_eq</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret_eq</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret_full</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_full</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret_full</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret_spy</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_spy</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret_spy</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_str</span><span class="o">=</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">start</span><span class="si">}</span><span class="s2"> to</span><span class="si">{</span><span class="n">end</span><span class="si">}</span><span class="s2">"</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">q</span><span class="o">+</span><span class="n">suffix</span><span class="si">:</span><span class="s2">&lt;16</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">dates_str</span><span class="si">:</span><span class="s2">&lt;24</span><span class="si">}</span><span class="s2"> "</span></span></span><span class="line"><span class="cl"><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">ret_eq</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">ret_full</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">ret_spy</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"-"</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cum_eq_ret</span><span class="o">=</span><span class="n">cum_eq</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">cum_full_ret</span><span class="o">=</span><span class="n">cum_full</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">cum_spy_ret</span><span class="o">=</span><span class="n">cum_spy</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">dates_str</span><span class="o">=</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">first_date</span><span class="si">}</span><span class="s2"> to</span><span class="si">{</span><span class="n">today</span><span class="si">}</span><span class="s2">"</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Cumulative'</span><span class="si">:</span><span class="s2">&lt;16</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">dates_str</span><span class="si">:</span><span class="s2">&lt;24</span><span class="si">}</span><span class="s2"> "</span></span></span><span class="line"><span class="cl"><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_eq_ret</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_full_ret</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_spy_ret</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"† = partial period (still holding; updates on re-evaluation)"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"Eq. only = long equity positions only"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"Full exp. = options treated as underlying exposure proxy"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Risk-adjusted returns ──────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="n">daily_close</span><span class="o">=</span><span class="n">download_daily</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">,</span><span class="n">first_date</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">daily_returns_series</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">daily_close</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="p">,</span><span class="n">mode</span><span class="p">,</span><span class="n">per_period_opt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute daily portfolio return series for a given mode.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Uses per-period option prices when available; falls back to</span></span></span><span class="line"><span class="cl"><span class="s2"> Black-Scholes repricing using option_params otherwise.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">daily_close</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">returns</span><span class="p">,</span><span class="n">dates</span><span class="o">=</span><span class="p">[],</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">ps</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="n">pe</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">period</span><span class="o">=</span><span class="n">daily_close</span><span class="p">[(</span><span class="n">daily_close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">)</span><span class="o">&amp;</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">daily_close</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pe</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">period</span><span class="p">)</span><span class="o">&lt;</span><span class="mi">2</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">quarter_opt</span><span class="o">=</span><span class="n">per_period_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})</span><span class="k">if</span><span class="n">per_period_opt</span><span class="k">else</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">weights</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">use_opt</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">has_opt</span><span class="o">=</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">quarter_opt</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">has_opt</span><span class="ow">and</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">daily_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">weights</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">use_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">has_opt</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total_value</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Forward-fill: track last known option price per position</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day_idx</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">period</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">daily_ret</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">day_curr</span><span class="o">=</span><span class="n">period</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">day_prev</span><span class="o">=</span><span class="n">period</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">d_curr</span><span class="o">=</span><span class="n">day_curr</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">d_prev</span><span class="o">=</span><span class="n">day_prev</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">weights</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ticker_opt</span><span class="o">=</span><span class="n">quarter_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">,</span><span class="p">{})</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">ticker_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">d_prev</span><span class="p">,</span><span class="n">last_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="n">raw_p1</span><span class="o">=</span><span class="n">ticker_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">d_curr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">p1</span><span class="o">=</span><span class="n">raw_p1</span><span class="k">if</span><span class="n">raw_p1</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">raw_p1</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">raw_p1</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">p0</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">p1</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">period</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">period</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">p1</span><span class="o">=</span><span class="n">period</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p0</span><span class="p">)</span><span class="ow">or</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="ow">or</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">-</span><span class="nb">float</span><span class="p">(</span><span class="n">p0</span><span class="p">))</span><span class="o">/</span><span class="nb">float</span><span class="p">(</span><span class="n">p0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="ow">not</span><span class="n">use_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]):</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="p">(</span><span class="n">day_curr</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="c1"># Reconstruct cumulative stock return for BS repricing</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">period</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">s0</span><span class="o">=</span><span class="n">period</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">s0</span><span class="ow">and</span><span class="ow">not</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span><span class="ow">and</span><span class="n">s0</span><span class="o">!=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_stock_ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">period</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">])</span><span class="o">-</span><span class="nb">float</span><span class="p">(</span><span class="n">s0</span><span class="p">))</span><span class="o">/</span><span class="nb">float</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cum_opt_ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">cum_stock_ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">dt_prev</span><span class="o">=</span><span class="p">(</span><span class="n">day_prev</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">cum_stock_ret_prev</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">period</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span><span class="o">-</span><span class="nb">float</span><span class="p">(</span><span class="n">s0</span><span class="p">))</span><span class="o">/</span><span class="nb">float</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cum_opt_ret_prev</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">cum_stock_ret_prev</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt_prev</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">cum_opt_ret</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">cum_opt_ret_prev</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">cum_opt_ret_prev</span><span class="p">)</span><span class="o">!=</span><span class="mi">0</span><span class="k">else</span><span class="n">ret</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">daily_ret</span><span class="o">+=</span><span class="p">(</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span><span class="p">)</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"><span class="n">returns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">daily_ret</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">period</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="n">returns</span><span class="p">,</span><span class="n">index</span><span class="o">=</span><span class="n">dates</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret_eq_d</span><span class="o">=</span><span class="n">daily_returns_series</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">daily_close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="s1">'equity_only'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">ret_full_d</span><span class="o">=</span><span class="n">daily_returns_series</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">daily_close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="s1">'full'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">daily_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">spy_close</span><span class="o">=</span><span class="n">daily_close</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">spy_period</span><span class="o">=</span><span class="n">spy_close</span><span class="p">[</span><span class="n">spy_close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">first_date</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">ret_spy_d</span><span class="o">=</span><span class="n">spy_period</span><span class="o">.</span><span class="n">pct_change</span><span class="p">()</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ret_spy_d</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">sharpe</span><span class="p">(</span><span class="n">daily_rets</span><span class="p">,</span><span class="n">rf_annual</span><span class="o">=</span><span class="mf">0.04</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">daily_rets</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="s1">'nan'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">rf_daily</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">rf_annual</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">252</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">excess</span><span class="o">=</span><span class="n">daily_rets</span><span class="o">-</span><span class="n">rf_daily</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">excess</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">==</span><span class="mi">0</span><span class="ow">or</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">excess</span><span class="o">.</span><span class="n">std</span><span class="p">()):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="s1">'nan'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="n">excess</span><span class="o">.</span><span class="n">mean</span><span class="p">()</span><span class="o">/</span><span class="n">excess</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="mi">252</span><span class="o">**</span><span class="mf">0.5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">max_drawdown</span><span class="p">(</span><span class="n">daily_rets</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">daily_rets</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="s1">'nan'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cum</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">daily_rets</span><span class="p">)</span><span class="o">.</span><span class="n">cumprod</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(((</span><span class="n">cum</span><span class="o">-</span><span class="n">cum</span><span class="o">.</span><span class="n">cummax</span><span class="p">())</span><span class="o">/</span><span class="n">cum</span><span class="o">.</span><span class="n">cummax</span><span class="p">())</span><span class="o">.</span><span class="n">min</span><span class="p">()</span><span class="o">*</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"RISK-ADJUSTED RETURNS"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"="</span><span class="o">*</span><span class="mi">55</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Metric'</span><span class="si">:</span><span class="s2">&lt;25</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Eq. only'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Full exp.'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'SPY'</span><span class="si">:</span><span class="s2">&gt;9</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"-"</span><span class="o">*</span><span class="mi">55</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">vol_eq</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">ret_eq_d</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="mi">252</span><span class="o">**</span><span class="mf">0.5</span><span class="o">*</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_full</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">ret_full_d</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="mi">252</span><span class="o">**</span><span class="mf">0.5</span><span class="o">*</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_spy</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">ret_spy_d</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="mi">252</span><span class="o">**</span><span class="mf">0.5</span><span class="o">*</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Ann. volatility'</span><span class="si">:</span><span class="s2">&lt;25</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">vol_eq</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%</span><span class="si">{</span><span class="n">vol_full</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%</span><span class="si">{</span><span class="n">vol_spy</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">sh_eq</span><span class="o">=</span><span class="n">sharpe</span><span class="p">(</span><span class="n">ret_eq_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">sh_full</span><span class="o">=</span><span class="n">sharpe</span><span class="p">(</span><span class="n">ret_full_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">sh_spy</span><span class="o">=</span><span class="n">sharpe</span><span class="p">(</span><span class="n">ret_spy_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Sharpe (rf=4%)'</span><span class="si">:</span><span class="s2">&lt;25</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">sh_eq</span><span class="si">:</span><span class="s2">&gt;9.2f</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">sh_full</span><span class="si">:</span><span class="s2">&gt;9.2f</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">sh_spy</span><span class="si">:</span><span class="s2">&gt;9.2f</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">mdd_eq</span><span class="o">=</span><span class="n">max_drawdown</span><span class="p">(</span><span class="n">ret_eq_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">mdd_full</span><span class="o">=</span><span class="n">max_drawdown</span><span class="p">(</span><span class="n">ret_full_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">mdd_spy</span><span class="o">=</span><span class="n">max_drawdown</span><span class="p">(</span><span class="n">ret_spy_d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Max drawdown'</span><span class="si">:</span><span class="s2">&lt;25</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">mdd_eq</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%</span><span class="si">{</span><span class="n">mdd_full</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%</span><span class="si">{</span><span class="n">mdd_spy</span><span class="si">:</span><span class="s2">&gt;8.1f</span><span class="si">}</span><span class="s2">%"</span><span class="p">)</span></span></span></code></pre></div><p><a id="code-snippet--sa-chart"/></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">json</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">yfinance</span><span class="k">as</span><span class="nn">yf</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">pandas</span><span class="k">as</span><span class="nn">pd</span></span></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">datetime</span><span class="kn">import</span><span class="n">datetime</span><span class="p">,</span><span class="n">timedelta</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">numpy</span><span class="k">as</span><span class="nn">np</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">requests</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">time</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">os</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">warnings</span></span></span><span class="line"><span class="cl"><span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s1">'ignore'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Parse data from the scraper block</span></span></span><span class="line"><span class="cl"><span class="n">parsed</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="nb">str</span><span class="p">)</span><span class="k">else</span><span class="n">data</span></span></span><span class="line"><span class="cl"><span class="n">filings</span><span class="o">=</span><span class="n">parsed</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Build internal structures</span></span></span><span class="line"><span class="cl"><span class="n">filing_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarter_end_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter_end"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarters</span><span class="o">=</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Convert holdings list to dict keyed by quarter.</span></span></span><span class="line"><span class="cl"><span class="c1"># Multiple positions in the same ticker with different types are aggregated</span></span></span><span class="line"><span class="cl"><span class="c1"># by value per (ticker, type) pair.</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">f</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">value</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"value"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="n">positions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]]</span><span class="o">=</span><span class="n">positions</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">get_prices</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">dates</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch close prices for tickers on specific dates."""</span></span></span><span class="line"><span class="cl"><span class="n">unique_tickers</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">tickers</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">dates</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="nb">min</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="nb">max</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">unique_tickers</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># yf.download returns MultiIndex columns (metric, ticker) for multiple tickers</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">unique_tickers</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">unique_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">series</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">date_str</span><span class="ow">in</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">target</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">after</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">after</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">after</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">before</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">before</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">before</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">prices</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the first available price on/after target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the last available price on/before target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&lt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_period_price_pair</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return start/end prices for a period using sensible boundary alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">start</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">end</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">p0</span><span class="o">=</span><span class="n">start</span></span></span><span class="line"><span class="cl"><span class="n">end_actual</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">end</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">end_actual</span><span class="o">&lt;</span><span class="n">start_actual</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_return</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">prices</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'equity_only'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_prices</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute weighted portfolio return between two dates.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions (call/put): if option_prices contains actual</span></span></span><span class="line"><span class="cl"><span class="s2"> historical option prices for the ticker, compute returns directly from</span></span></span><span class="line"><span class="cl"><span class="s2"> those prices. Otherwise fall back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> the parameters in option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_px</span><span class="o">=</span><span class="n">option_prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span><span class="k">if</span><span class="n">option_prices</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="nb">bool</span><span class="p">(</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">opt_px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">px</span><span class="o">=</span><span class="n">prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="n">p1</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing when no option price data</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">is_option</span><span class="ow">and</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="n">days_between</span><span class="p">(</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">)</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="c1"># When using actual option/BS prices the return already reflects</span></span></span><span class="line"><span class="cl"><span class="c1"># the directional bet, so sign is +1. The -1 for puts applies</span></span></span><span class="line"><span class="cl"><span class="c1"># only to the raw stock-price proxy path.</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_option_px</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="n">value</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">weighted_return</span><span class="o">/</span><span class="n">total_value</span><span class="k">if</span><span class="n">total_value</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">annualize</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">days</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Annualize a return over a given number of calendar days."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">days</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="mf">365.25</span><span class="o">/</span><span class="n">days</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">days_between</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="n">d2</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d2</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span><span class="o">.</span><span class="n">days</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">fmt</span><span class="p">(</span><span class="n">ret</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ret</span><span class="o">*</span><span class="mi">100</span><span class="si">:</span><span class="s2">+.2f</span><span class="si">}</span><span class="s2">%"</span><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="s2">"N/A"</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Collect all tickers and dates</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">positions</span><span class="ow">in</span><span class="n">holdings</span><span class="o">.</span><span class="n">values</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_</span><span class="p">)</span><span class="ow">in</span><span class="n">positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">'SPY'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">first_date</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="nb">set</span><span class="p">(</span><span class="n">filing_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="nb">set</span><span class="p">(</span><span class="n">quarter_end_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="p">{</span><span class="n">today</span><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="n">get_prices</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">),</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_dates</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Resolve `today` to the actual last available closing date.</span></span></span><span class="line"><span class="cl"><span class="c1"># yfinance may not have data for today (market still open or holiday),</span></span></span><span class="line"><span class="cl"><span class="c1"># so we look up what date SPY's price actually corresponds to.</span></span></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">requested_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return the actual trading date of the price stored under requested_date."""</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="s1">'SPY'</span><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">prices</span><span class="k">else</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">prices</span><span class="p">),</span><span class="kc">None</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">ref</span><span class="ow">or</span><span class="n">requested_date</span><span class="ow">not</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="n">target_price</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">][</span><span class="n">requested_date</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="c1"># Re-download a small window to find the real date of this price</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">ref</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">][</span><span class="n">ref</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="s1">'Close'</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">iloc</span><span class="p">[:,</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">dt</span><span class="p">,</span><span class="n">px</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">val</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">)</span><span class="k">else</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">abs</span><span class="p">(</span><span class="n">val</span><span class="o">-</span><span class="n">target_price</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ts</span><span class="o">=</span><span class="n">dt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span><span class="nb">tuple</span><span class="p">)</span><span class="k">else</span><span class="n">dt</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">ts</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today_resolved</span><span class="o">=</span><span class="n">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today_resolved</span><span class="o">!=</span><span class="n">today</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">today_resolved</span><span class="p">]</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">today_resolved</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_daily</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download daily close prices from yfinance, handling MultiIndex.</span></span></span><span class="line"><span class="cl"><span class="s2"> Dates are 'YYYY-MM-DD' strings. Adds a small buffer for trading-day alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">tickers_sorted</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">tickers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">start_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">end_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">tickers_sorted</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">tickers_sorted</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">close</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Historical option prices via Alpha Vantage ----------------------------</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_DIR</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/notes/.sa-lp-option-cache'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_AV_BASE</span><span class="o">=</span><span class="s1">'https://www.alphavantage.co/query'</span></span></span><span class="line"><span class="cl"><span class="n">_AV_RATE_DELAY</span><span class="o">=</span><span class="mf">0.85</span><span class="c1"># seconds between requests (75 req/min limit)</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_COLUMNS</span><span class="o">=</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="ow">not</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">raise</span><span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unsupported option type:</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_empty_option_cache</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">columns</span><span class="o">=</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">-</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Load cached option data for a ticker/type. Returns DataFrame or empty."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">=</span><span class="p">[</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="c1"># Pre-fix caches were call-only and named TICKER.csv. They are safe to</span></span></span><span class="line"><span class="cl"><span class="c1"># reuse for calls but must not be reused for puts.</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">legacy_path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy_path</span><span class="ow">not</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">legacy_path</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">path</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'option_type'</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="s1">'call'</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_datetime</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span><span class="o">.</span><span class="n">dt</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">.</span><span class="n">fillna</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">frames</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="n">frames</span><span class="p">,</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_numeric</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">cache</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">df</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Persist typed option cache to CSV."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">path</span><span class="p">,</span><span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch the full option chain for ticker on a given date from Alpha Vantage."""</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'function'</span><span class="p">:</span><span class="s1">'HISTORICAL_OPTIONS'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'symbol'</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">date_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'apikey'</span><span class="p">:</span><span class="n">api_key</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">=</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_AV_BASE</span><span class="p">,</span><span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">body</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">json</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">body</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span><span class="p">[])</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">270</span><span class="p">),</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">456</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'option_type'</span><span class="p">,</span><span class="n">option_type</span><span class="p">))</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">strike</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">contract</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_best_contract</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Select the best-matching call/put contract from an option chain.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Criteria: matching option type, expiry 9-15 months from ref_date,</span></span></span><span class="line"><span class="cl"><span class="s2"> absolute delta closest to 0.15. Returns dict with type, strike, expiry,</span></span></span><span class="line"><span class="cl"><span class="s2"> delta, price or None.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">abs_delta</span><span class="o">=</span><span class="nb">abs</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">abs_delta</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="c1"># Price: prefer mid if available, else last</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="c1"># Pick contract with absolute delta closest to 0.15.</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_parse_option_price</span><span class="p">(</span><span class="n">contract</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Extract a price from an Alpha Vantage option contract record."""</span></span></span><span class="line"><span class="cl"><span class="n">bid</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'bid'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">ask</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ask'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">last</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'last'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">bid</span><span class="ow">and</span><span class="n">ask</span><span class="ow">and</span><span class="n">bid</span><span class="o">&gt;</span><span class="mi">0</span><span class="ow">and</span><span class="n">ask</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">bid</span><span class="o">+</span><span class="n">ask</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">last</span><span class="ow">and</span><span class="n">last</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">last</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_safe_float</span><span class="p">(</span><span class="n">val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="n">val</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_cached_contract_price</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">price</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_extract_contract_price</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Find the price of a specific option contract."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">])</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'expiration'</span><span class="p">)</span><span class="o">==</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_option_prices</span><span class="p">(</span><span class="n">option_positions</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">holdings</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download historical option prices from Alpha Vantage.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each (ticker, option_type) and each filing period:</span></span></span><span class="line"><span class="cl"><span class="s2"> 1. On the first trading day, fetch the chain and select the best contract</span></span></span><span class="line"><span class="cl"><span class="s2"> (matching type, expiry 9-15 months out, |delta| closest to 0.15).</span></span></span><span class="line"><span class="cl"><span class="s2"> 2. Lock in that contract for the period.</span></span></span><span class="line"><span class="cl"><span class="s2"> 3. Fetch the price of that contract on each subsequent trading day.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Returns</span></span></span><span class="line"><span class="cl"><span class="s2"> -------</span></span></span><span class="line"><span class="cl"><span class="s2"> per_period : dict {quarter_str: {(ticker, type): {date_str: float}}}</span></span></span><span class="line"><span class="cl"><span class="s2"> Option prices keyed by filing period then option position. Each period</span></span></span><span class="line"><span class="cl"><span class="s2"> has its own contract's prices, avoiding cross-contract mixing at</span></span></span><span class="line"><span class="cl"><span class="s2"> boundary dates where one period ends and the next begins.</span></span></span><span class="line"><span class="cl"><span class="s2"> fallback_positions : set</span></span></span><span class="line"><span class="cl"><span class="s2"> Option positions where no option data was found (need BS fallback).</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_positions</span><span class="o">=</span><span class="nb">sorted</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ALPHA_VANTAGE_KEY'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache_only</span><span class="o">=</span><span class="ow">not</span><span class="nb">bool</span><span class="p">(</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"WARNING: ALPHA_VANTAGE_KEY not set; using cached option "</span></span></span><span class="line"><span class="cl"><span class="s2">"prices where available and BS repricing elsewhere."</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">=</span><span class="p">{}</span><span class="c1"># {q: {(ticker, type): {date_str: price}}}</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip quarters where this exact option position is absent.</span></span></span><span class="line"><span class="cl"><span class="n">has_opts</span><span class="o">=</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">has_opts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="p">(</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">trading_days</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">bdate_range</span><span class="p">(</span><span class="n">period_start</span><span class="p">,</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">trading_days</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">first_day</span><span class="o">=</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Select contract on first trading day --</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">first_day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_best_contract</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">first_day</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">expiry</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Collect prices for this period (fresh dict per period) --</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">from_cache</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Fast path: read all matching prices from cache (no API calls).</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&lt;=</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Slow path: fetch each trading day from API</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">first_day</span><span class="p">]</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day</span><span class="ow">in</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cached_price</span><span class="o">=</span><span class="n">_cached_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cached_price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">cached_price</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_extract_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">day_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">expiry</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Accumulate per-period prices</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})[</span><span class="n">opt_key</span><span class="p">]</span><span class="o">=</span><span class="n">period_prices</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Persist new data to cache</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">new_rows</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">new_rows</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">([</span><span class="n">cache</span><span class="p">,</span><span class="n">new_df</span><span class="p">],</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">position_has_data</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">fetched</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">sys</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[options] Fetched</span><span class="si">{</span><span class="n">fetched</span><span class="si">}</span><span class="s2"> chain snapshots from Alpha Vantage"</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">per_period</span><span class="p">,</span><span class="n">fallback</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Fallback: Black-Scholes repricing for tickers without option data -----</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">scipy.stats</span><span class="kn">import</span><span class="n">norm</span><span class="k">as</span><span class="n">_norm</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_realized_vol</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">download_daily_fn</span><span class="p">,</span><span class="n">today_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute annualized realized vol from trailing 1-year daily returns."""</span></span></span><span class="line"><span class="cl"><span class="n">vol_start</span><span class="o">=</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">today_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">400</span><span class="p">))</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_df</span><span class="o">=</span><span class="n">download_daily_fn</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">vol_start</span><span class="p">,</span><span class="n">today_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">vol_df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">vol_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">series</span><span class="p">)</span><span class="o">&gt;</span><span class="mi">20</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">log_rets</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">series</span><span class="o">/</span><span class="n">series</span><span class="o">.</span><span class="n">shift</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span><span class="o">.</span><span class="n">tail</span><span class="p">(</span><span class="mi">252</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">log_rets</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">252</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_price</span><span class="p">(</span><span class="n">S</span><span class="p">,</span><span class="n">K</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Black-Scholes option price (assumes zero risk-free rate and dividends)."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">T</span><span class="o">&lt;=</span><span class="mi">0</span><span class="ow">or</span><span class="n">sigma</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">S</span><span class="o">-</span><span class="n">K</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">K</span><span class="o">-</span><span class="n">S</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">d1</span><span class="o">=</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">S</span><span class="o">/</span><span class="n">K</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">T</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">d2</span><span class="o">=</span><span class="n">d1</span><span class="o">-</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d1</span><span class="p">)</span><span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d2</span><span class="p">)</span><span class="o">-</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_option_return</span><span class="p">(</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">delta_t</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute option return from stock return using Black-Scholes repricing.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Normalizes S_0 = 1, so S_1 = 1 + stock_return and K = K_over_S.</span></span></span><span class="line"><span class="cl"><span class="s2"> T is time to expiry at period start; delta_t is time elapsed.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">V0</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">V1</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="o">+</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="nb">max</span><span class="p">(</span><span class="n">T</span><span class="o">-</span><span class="n">delta_t</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">V0</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">stock_return</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">V1</span><span class="o">/</span><span class="n">V0</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_DELTA</span><span class="o">=</span><span class="mf">0.15</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_T</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">build_option_params</span><span class="p">(</span><span class="n">option_tickers</span><span class="p">,</span><span class="n">ticker_vol</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build {ticker: (K_over_S_call, K_over_S_put, sigma)} for BS fallback."""</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">t</span><span class="ow">in</span><span class="n">option_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">t</span><span class="ow">not</span><span class="ow">in</span><span class="n">ticker_vol</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="o">=</span><span class="n">ticker_vol</span><span class="p">[</span><span class="n">t</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">srt</span><span class="o">=</span><span class="n">sigma</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">**</span><span class="mf">0.5</span></span></span><span class="line"><span class="cl"><span class="c1"># Call: delta = N(d1) = OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_call</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_call</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1"># Put: delta = N(d1) - 1 = -OPTION_DELTA, so N(d1) = 1 - OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_put</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_put</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_put</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">t</span><span class="p">]</span><span class="o">=</span><span class="p">(</span><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">daily_cumulative</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="n">mode</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">per_period_opt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build a daily series of cumulative growth factors for a given mode.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each filing period the portfolio weights are fixed. Each trading</span></span></span><span class="line"><span class="cl"><span class="s2"> day's weighted return is computed relative to the period's starting</span></span></span><span class="line"><span class="cl"><span class="s2"> prices, then chained with the prior period's cumulative growth.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions: uses per-period option prices from per_period_opt</span></span></span><span class="line"><span class="cl"><span class="s2"> when available; otherwise falls back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span></span></span><span class="line"><span class="cl"><span class="n">ps</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pe</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Trading days in this period</span></span></span><span class="line"><span class="cl"><span class="n">mask</span><span class="o">=</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">)</span><span class="o">&amp;</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">period_close</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_close</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Option prices for this period (keyed by (ticker, type) → prices)</span></span></span><span class="line"><span class="cl"><span class="n">quarter_opt</span><span class="o">=</span><span class="n">per_period_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})</span><span class="k">if</span><span class="n">per_period_opt</span><span class="k">else</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Determine portfolio weights and starting prices</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">weights</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="o">=</span><span class="p">{}</span><span class="c1"># track which positions use option prices</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Select price source for this position</span></span></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">has_opt</span><span class="o">=</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">quarter_opt</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">has_opt</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ticker_opt</span><span class="o">=</span><span class="n">quarter_opt</span><span class="p">[</span><span class="n">opt_key</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">opt_dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">ticker_opt</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">opt_dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">ticker_opt</span><span class="p">[</span><span class="n">opt_dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">src</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">avail</span><span class="o">=</span><span class="n">src</span><span class="p">[</span><span class="n">src</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avail</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">avail</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">weights</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">has_opt</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total_value</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Daily weighted return relative to period start</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip first day of subsequent periods (already recorded as last day</span></span></span><span class="line"><span class="cl"><span class="c1"># of the prior period) to avoid duplicate boundary dates.</span></span></span><span class="line"><span class="cl"><span class="n">start_idx</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="n">i</span><span class="o">&gt;</span><span class="mi">0</span><span class="k">else</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="c1"># Forward-fill: track last known option price so that gaps in</span></span></span><span class="line"><span class="cl"><span class="c1"># option data don't cause positions to vanish mid-period.</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="o">=</span><span class="p">{</span><span class="n">k</span><span class="p">:</span><span class="n">v</span><span class="k">for</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="ow">in</span><span class="n">start_prices</span><span class="o">.</span><span class="n">items</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">k</span><span class="p">)}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day_idx</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="n">start_idx</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">period_close</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">day</span><span class="o">=</span><span class="n">period_close</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">weights</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">quarter_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">,</span><span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">day_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">p1_val</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">last_opt</span><span class="o">.</span><span class="n">get</span><span class="p">((</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">period_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">period_close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1_val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1_val</span><span class="p">)</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing for option positions without option data</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="ow">not</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]):</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="p">(</span><span class="n">day</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="p">(</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span><span class="p">)</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cum_growth</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">weighted_return</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Chain: next period starts from the last day's growth factor</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">values_out</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="n">values_out</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">dates_out</span><span class="p">,</span><span class="n">values_out</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">plotly.graph_objects</span><span class="k">as</span><span class="nn">go</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">HUGO_BASE</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/repos/stafforini.com'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Fetch daily prices ────────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">download_daily</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">,</span><span class="n">first_date</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_eq</span><span class="p">,</span><span class="n">vals_eq</span><span class="o">=</span><span class="n">daily_cumulative</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="s1">'equity_only'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_full</span><span class="p">,</span><span class="n">vals_full</span><span class="o">=</span><span class="n">daily_cumulative</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="s1">'full'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Compute SPY benchmark ─────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="n">spy_series</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="s1">'SPY'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">spy_start</span><span class="o">=</span><span class="n">spy_series</span><span class="p">[</span><span class="n">spy_series</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">first_date</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">spy_start</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">spy_p0</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">spy_start</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="n">spy_dates</span><span class="o">=</span><span class="n">spy_start</span><span class="o">.</span><span class="n">index</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">spy_vals</span><span class="o">=</span><span class="p">[</span><span class="nb">float</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="o">/</span><span class="n">spy_p0</span><span class="k">for</span><span class="n">p</span><span class="ow">in</span><span class="n">spy_start</span><span class="o">.</span><span class="n">values</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">spy_dates</span><span class="p">,</span><span class="n">spy_vals</span><span class="o">=</span><span class="p">[],</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Plot with Plotly ───────────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="n">eq_pct</span><span class="o">=</span><span class="p">[</span><span class="nb">round</span><span class="p">((</span><span class="n">v</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">100</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="k">for</span><span class="n">v</span><span class="ow">in</span><span class="n">vals_eq</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">full_pct</span><span class="o">=</span><span class="p">[</span><span class="nb">round</span><span class="p">((</span><span class="n">v</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">100</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="k">for</span><span class="n">v</span><span class="ow">in</span><span class="n">vals_full</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">spy_pct</span><span class="o">=</span><span class="p">[</span><span class="nb">round</span><span class="p">((</span><span class="n">v</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">100</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="k">for</span><span class="n">v</span><span class="ow">in</span><span class="n">spy_vals</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">=</span><span class="n">go</span><span class="o">.</span><span class="n">Figure</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_trace</span><span class="p">(</span><span class="n">go</span><span class="o">.</span><span class="n">Scatter</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">x</span><span class="o">=</span><span class="n">dates_eq</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="n">eq_pct</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'lines'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">name</span><span class="o">=</span><span class="s1">'Equity only'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">line</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="s1">'#2563eb'</span><span class="p">,</span><span class="n">width</span><span class="o">=</span><span class="mi">2</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_trace</span><span class="p">(</span><span class="n">go</span><span class="o">.</span><span class="n">Scatter</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">x</span><span class="o">=</span><span class="n">dates_full</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="n">full_pct</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'lines'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">name</span><span class="o">=</span><span class="s1">'Full exposure proxy'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">line</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="s1">'#dc2626'</span><span class="p">,</span><span class="n">width</span><span class="o">=</span><span class="mi">2</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_trace</span><span class="p">(</span><span class="n">go</span><span class="o">.</span><span class="n">Scatter</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">x</span><span class="o">=</span><span class="n">spy_dates</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="n">spy_pct</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'lines'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">name</span><span class="o">=</span><span class="s1">'S&amp;P 500 (SPY)'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">line</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="s1">'#16a34a'</span><span class="p">,</span><span class="n">width</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="n">dash</span><span class="o">=</span><span class="s1">'dot'</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Vertical lines at filing dates (rebalancing points)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">fd</span><span class="ow">in</span><span class="n">filing_dates</span><span class="o">.</span><span class="n">values</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_vline</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">fd</span><span class="p">,</span><span class="n">line</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="s1">'gray'</span><span class="p">,</span><span class="n">width</span><span class="o">=</span><span class="mf">0.5</span><span class="p">),</span><span class="n">opacity</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_hline</span><span class="p">(</span><span class="n">y</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="n">line</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="s1">'gray'</span><span class="p">,</span><span class="n">width</span><span class="o">=</span><span class="mf">0.8</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">update_layout</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">title</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s1">'SA LP copycat: cumulative returns'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">font</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">15</span><span class="p">)),</span></span></span><span class="line"><span class="cl"><span class="n">yaxis</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s1">'Cumulative return'</span><span class="p">,</span><span class="n">hoverformat</span><span class="o">=</span><span class="s1">'+.1f'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">ticksuffix</span><span class="o">=</span><span class="s1">'%'</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">hovermode</span><span class="o">=</span><span class="s1">'x unified'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">xaxis</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">spikemode</span><span class="o">=</span><span class="s1">'across'</span><span class="p">,</span><span class="n">spikethickness</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">spikedash</span><span class="o">=</span><span class="s1">'solid'</span><span class="p">,</span><span class="n">spikecolor</span><span class="o">=</span><span class="s1">'gray'</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">template</span><span class="o">=</span><span class="s1">'plotly_white'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">legend</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mf">0.02</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="mf">0.98</span><span class="p">,</span><span class="n">bgcolor</span><span class="o">=</span><span class="s1">'rgba(255,255,255,0.8)'</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">margin</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">l</span><span class="o">=</span><span class="mi">60</span><span class="p">,</span><span class="n">r</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="n">t</span><span class="o">=</span><span class="mi">50</span><span class="p">,</span><span class="n">b</span><span class="o">=</span><span class="mi">40</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">height</span><span class="o">=</span><span class="mi">500</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Generate HTML with dark-mode support ──────────────────────────</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">re</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">chart_html</span><span class="o">=</span><span class="n">fig</span><span class="o">.</span><span class="n">to_html</span><span class="p">(</span><span class="n">full_html</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">include_plotlyjs</span><span class="o">=</span><span class="s1">'cdn'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s1">'responsive'</span><span class="p">:</span><span class="kc">True</span><span class="p">,</span><span class="s1">'displayModeBar'</span><span class="p">:</span><span class="kc">False</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">div_id</span><span class="o">=</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">r</span><span class="s1">'id="([^"]+)"'</span><span class="p">,</span><span class="n">chart_html</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dark_script</span><span class="o">=</span><span class="s2">"""</span></span></span><span class="line"><span class="cl"><span class="s2">&lt;script&gt;</span></span></span><span class="line"><span class="cl"><span class="s2">(function() {</span></span></span><span class="line"><span class="cl"><span class="s2"> var gd = document.getElementById('</span><span class="si">%s</span><span class="s2">');</span></span></span><span class="line"><span class="cl"><span class="s2"> function isDark() {</span></span></span><span class="line"><span class="cl"><span class="s2"> try { return parent.document.documentElement.getAttribute('data-theme') === 'dark'; }</span></span></span><span class="line"><span class="cl"><span class="s2"> catch(e) { return window.matchMedia('(prefers-color-scheme: dark)').matches; }</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> function apply() {</span></span></span><span class="line"><span class="cl"><span class="s2"> var dk = isDark();</span></span></span><span class="line"><span class="cl"><span class="s2"> Plotly.relayout(gd, {</span></span></span><span class="line"><span class="cl"><span class="s2"> paper_bgcolor: 'rgba(0,0,0,0)',</span></span></span><span class="line"><span class="cl"><span class="s2"> plot_bgcolor: dk ? 'rgba(30,30,30,0.5)' : 'rgba(255,255,255,0.8)',</span></span></span><span class="line"><span class="cl"><span class="s2"> font: {color: dk ? '#d4d4d4' : '#333'},</span></span></span><span class="line"><span class="cl"><span class="s2"> 'title.font.color': dk ? '#d4d4d4' : '#333',</span></span></span><span class="line"><span class="cl"><span class="s2"> 'xaxis.gridcolor': dk ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)',</span></span></span><span class="line"><span class="cl"><span class="s2"> 'yaxis.gridcolor': dk ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)',</span></span></span><span class="line"><span class="cl"><span class="s2"> 'legend.bgcolor': dk ? 'rgba(30,30,30,0.8)' : 'rgba(255,255,255,0.8)',</span></span></span><span class="line"><span class="cl"><span class="s2"> 'legend.font.color': dk ? '#d4d4d4' : '#333',</span></span></span><span class="line"><span class="cl"><span class="s2"> });</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> apply();</span></span></span><span class="line"><span class="cl"><span class="s2"> new MutationObserver(function() { apply(); }).observe(</span></span></span><span class="line"><span class="cl"><span class="s2"> parent.document.documentElement, {attributes: true, attributeFilter: ['data-theme']});</span></span></span><span class="line"><span class="cl"><span class="s2">})();</span></span></span><span class="line"><span class="cl"><span class="s2">&lt;/script&gt;"""</span><span class="o">%</span><span class="n">div_id</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">outpath</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">HUGO_BASE</span><span class="p">,</span><span class="s1">'static'</span><span class="p">,</span><span class="s1">'images'</span><span class="p">,</span><span class="s1">'sa-lp-returns.html'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">with</span><span class="nb">open</span><span class="p">(</span><span class="n">outpath</span><span class="p">,</span><span class="s1">'w'</span><span class="p">)</span><span class="k">as</span><span class="n">f</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'&lt;!DOCTYPE html&gt;</span><span class="se">\n</span><span class="s1">&lt;html&gt;</span><span class="se">\n</span><span class="s1">&lt;head&gt;&lt;meta charset="utf-8"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;style&gt;body { margin: 0; background: transparent; }&lt;/style&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;/head&gt;</span><span class="se">\n</span><span class="s1">&lt;body&gt;</span><span class="se">\n</span><span class="s1">'</span><span class="o">+</span><span class="n">chart_html</span><span class="o">+</span><span class="n">dark_script</span><span class="o">+</span></span></span><span class="line"><span class="cl"><span class="s1">'</span><span class="se">\n</span><span class="s1">&lt;/body&gt;</span><span class="se">\n</span><span class="s1">&lt;/html&gt;'</span><span class="p">)</span></span></span></code></pre></div></div></details><iframe id="sa-lp-chart" width="100%" height="520" style="border:none;" scrolling="no"/><script>document.getElementById('sa-lp-chart').src = '/images/sa-lp-returns.html?' + Date.now();</script><p>The &ldquo;equity only&rdquo; line uses only the fund’s long equity positions, ignoring its options book.</p><p>The &ldquo;full exposure&rdquo; line is a directional exposure proxy, not a true fund-return estimate. For option rows,<a href="https://www.sec.gov/rules-regulations/staff-guidance/division-investment-management-frequently-asked-questions/frequently-asked-questions-about-form-13f">SEC guidance</a> says that most Form 13F information-table entries are reported in terms of the underlying security rather than the option contract itself. The filings omit the contracts’ strike prices, expiration dates, and premiums. The model therefore treats calls as long exposure to the underlying stock and puts as short exposure to the underlying stock, weighted by the reported 13F value. This is useful for estimating the direction and rough size of the disclosed bets, but it is not an executable options backtest.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p><h2 id="copycat-delays">Copycat delays</h2><p>Between one filing and the next (~90 days), the copycat holds a fixed portfolio while the fund’s actual portfolio evolves continuously. We only observe the fund’s positions at quarter-end snapshots; its actual holdings between snapshots are unknown. Furthermore, these snapshots are not published immediately, but after 45 days or so. These two delays—between the fund’s quarterly rebalance and quarter-end, and between quarter-end and filing date—create a gap where the copycat’s holdings are stale compared to the fund’s actual positions, depressing copycat returns.</p><p>Let \(Q_i\) denote the fund’s disclosed portfolio at the end of quarter \(i\). To estimate this cost, we can model the fund as switching from \(Q_{i-1}\) to \(Q_i\) at a single (unknown) point, uniformly distributed over the trading days in quarter \(i\).<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> Let \(R(P, s, t)\) denote the return of portfolio \(P\) from date \(s\) to date \(t\), and let \(T_i\) denote the last day of the quarter \(i\). For each possible switch day \(d\), the delay cost is \(R(Q_i, d, T_i) - R(Q_{i-1}, d, T_i)\): the return the fund earned on its new positions that the copycat missed. Averaging over all \(d\) gives the expected intra-quarter delay cost.</p><p>The same logic extends to the ~45-day gap between quarter-end and filing date. During this period, the copycat still holds \(Q_{i-1}\), while the fund may continue holding \(Q_i\) or may have already started trading toward \(Q_{i+1}\). We apply the same uniform-switch model over the full span of quarter \(i+1\): for each possible switch day during the gap, the fund earns a blend of \(Q_i\) and \(Q_{i+1}\) returns. We average over all scenarios—including those where the switch occurs after the gap—weighted by their probability.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p><details><summary>Code</summary><div class="details"><p><a id="code-snippet--sa-delay"/></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">json</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">yfinance</span><span class="k">as</span><span class="nn">yf</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">pandas</span><span class="k">as</span><span class="nn">pd</span></span></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">datetime</span><span class="kn">import</span><span class="n">datetime</span><span class="p">,</span><span class="n">timedelta</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">numpy</span><span class="k">as</span><span class="nn">np</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">requests</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">time</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">os</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">warnings</span></span></span><span class="line"><span class="cl"><span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s1">'ignore'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Parse data from the scraper block</span></span></span><span class="line"><span class="cl"><span class="n">parsed</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="nb">str</span><span class="p">)</span><span class="k">else</span><span class="n">data</span></span></span><span class="line"><span class="cl"><span class="n">filings</span><span class="o">=</span><span class="n">parsed</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Build internal structures</span></span></span><span class="line"><span class="cl"><span class="n">filing_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarter_end_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter_end"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarters</span><span class="o">=</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Convert holdings list to dict keyed by quarter.</span></span></span><span class="line"><span class="cl"><span class="c1"># Multiple positions in the same ticker with different types are aggregated</span></span></span><span class="line"><span class="cl"><span class="c1"># by value per (ticker, type) pair.</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">f</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">value</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"value"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="n">positions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]]</span><span class="o">=</span><span class="n">positions</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">get_prices</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">dates</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch close prices for tickers on specific dates."""</span></span></span><span class="line"><span class="cl"><span class="n">unique_tickers</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">tickers</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">dates</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="nb">min</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="nb">max</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">unique_tickers</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># yf.download returns MultiIndex columns (metric, ticker) for multiple tickers</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">unique_tickers</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">unique_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">series</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">date_str</span><span class="ow">in</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">target</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">after</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">after</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">after</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">before</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">before</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">before</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">prices</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the first available price on/after target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the last available price on/before target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&lt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_period_price_pair</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return start/end prices for a period using sensible boundary alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">start</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">end</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">p0</span><span class="o">=</span><span class="n">start</span></span></span><span class="line"><span class="cl"><span class="n">end_actual</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">end</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">end_actual</span><span class="o">&lt;</span><span class="n">start_actual</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_return</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">prices</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'equity_only'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_prices</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute weighted portfolio return between two dates.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions (call/put): if option_prices contains actual</span></span></span><span class="line"><span class="cl"><span class="s2"> historical option prices for the ticker, compute returns directly from</span></span></span><span class="line"><span class="cl"><span class="s2"> those prices. Otherwise fall back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> the parameters in option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_px</span><span class="o">=</span><span class="n">option_prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span><span class="k">if</span><span class="n">option_prices</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="nb">bool</span><span class="p">(</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">opt_px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">px</span><span class="o">=</span><span class="n">prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="n">p1</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing when no option price data</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">is_option</span><span class="ow">and</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="n">days_between</span><span class="p">(</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">)</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="c1"># When using actual option/BS prices the return already reflects</span></span></span><span class="line"><span class="cl"><span class="c1"># the directional bet, so sign is +1. The -1 for puts applies</span></span></span><span class="line"><span class="cl"><span class="c1"># only to the raw stock-price proxy path.</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_option_px</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="n">value</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">weighted_return</span><span class="o">/</span><span class="n">total_value</span><span class="k">if</span><span class="n">total_value</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">annualize</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">days</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Annualize a return over a given number of calendar days."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">days</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="mf">365.25</span><span class="o">/</span><span class="n">days</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">days_between</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="n">d2</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d2</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span><span class="o">.</span><span class="n">days</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">fmt</span><span class="p">(</span><span class="n">ret</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ret</span><span class="o">*</span><span class="mi">100</span><span class="si">:</span><span class="s2">+.2f</span><span class="si">}</span><span class="s2">%"</span><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="s2">"N/A"</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Collect all tickers and dates</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">positions</span><span class="ow">in</span><span class="n">holdings</span><span class="o">.</span><span class="n">values</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_</span><span class="p">)</span><span class="ow">in</span><span class="n">positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">'SPY'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">first_date</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="nb">set</span><span class="p">(</span><span class="n">filing_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="nb">set</span><span class="p">(</span><span class="n">quarter_end_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="p">{</span><span class="n">today</span><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="n">get_prices</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">),</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_dates</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Resolve `today` to the actual last available closing date.</span></span></span><span class="line"><span class="cl"><span class="c1"># yfinance may not have data for today (market still open or holiday),</span></span></span><span class="line"><span class="cl"><span class="c1"># so we look up what date SPY's price actually corresponds to.</span></span></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">requested_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return the actual trading date of the price stored under requested_date."""</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="s1">'SPY'</span><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">prices</span><span class="k">else</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">prices</span><span class="p">),</span><span class="kc">None</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">ref</span><span class="ow">or</span><span class="n">requested_date</span><span class="ow">not</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="n">target_price</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">][</span><span class="n">requested_date</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="c1"># Re-download a small window to find the real date of this price</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">ref</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">][</span><span class="n">ref</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="s1">'Close'</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">iloc</span><span class="p">[:,</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">dt</span><span class="p">,</span><span class="n">px</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">val</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">)</span><span class="k">else</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">abs</span><span class="p">(</span><span class="n">val</span><span class="o">-</span><span class="n">target_price</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ts</span><span class="o">=</span><span class="n">dt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span><span class="nb">tuple</span><span class="p">)</span><span class="k">else</span><span class="n">dt</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">ts</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today_resolved</span><span class="o">=</span><span class="n">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today_resolved</span><span class="o">!=</span><span class="n">today</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">today_resolved</span><span class="p">]</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">today_resolved</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_daily</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download daily close prices from yfinance, handling MultiIndex.</span></span></span><span class="line"><span class="cl"><span class="s2"> Dates are 'YYYY-MM-DD' strings. Adds a small buffer for trading-day alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">tickers_sorted</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">tickers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">start_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">end_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">tickers_sorted</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">tickers_sorted</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">close</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Historical option prices via Alpha Vantage ----------------------------</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_DIR</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/notes/.sa-lp-option-cache'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_AV_BASE</span><span class="o">=</span><span class="s1">'https://www.alphavantage.co/query'</span></span></span><span class="line"><span class="cl"><span class="n">_AV_RATE_DELAY</span><span class="o">=</span><span class="mf">0.85</span><span class="c1"># seconds between requests (75 req/min limit)</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_COLUMNS</span><span class="o">=</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="ow">not</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">raise</span><span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unsupported option type:</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_empty_option_cache</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">columns</span><span class="o">=</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">-</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Load cached option data for a ticker/type. Returns DataFrame or empty."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">=</span><span class="p">[</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="c1"># Pre-fix caches were call-only and named TICKER.csv. They are safe to</span></span></span><span class="line"><span class="cl"><span class="c1"># reuse for calls but must not be reused for puts.</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">legacy_path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy_path</span><span class="ow">not</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">legacy_path</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">path</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'option_type'</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="s1">'call'</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_datetime</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span><span class="o">.</span><span class="n">dt</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">.</span><span class="n">fillna</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">frames</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="n">frames</span><span class="p">,</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_numeric</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">cache</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">df</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Persist typed option cache to CSV."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">path</span><span class="p">,</span><span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch the full option chain for ticker on a given date from Alpha Vantage."""</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'function'</span><span class="p">:</span><span class="s1">'HISTORICAL_OPTIONS'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'symbol'</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">date_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'apikey'</span><span class="p">:</span><span class="n">api_key</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">=</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_AV_BASE</span><span class="p">,</span><span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">body</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">json</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">body</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span><span class="p">[])</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">270</span><span class="p">),</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">456</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'option_type'</span><span class="p">,</span><span class="n">option_type</span><span class="p">))</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">strike</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">contract</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_best_contract</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Select the best-matching call/put contract from an option chain.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Criteria: matching option type, expiry 9-15 months from ref_date,</span></span></span><span class="line"><span class="cl"><span class="s2"> absolute delta closest to 0.15. Returns dict with type, strike, expiry,</span></span></span><span class="line"><span class="cl"><span class="s2"> delta, price or None.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">abs_delta</span><span class="o">=</span><span class="nb">abs</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">abs_delta</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="c1"># Price: prefer mid if available, else last</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="c1"># Pick contract with absolute delta closest to 0.15.</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_parse_option_price</span><span class="p">(</span><span class="n">contract</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Extract a price from an Alpha Vantage option contract record."""</span></span></span><span class="line"><span class="cl"><span class="n">bid</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'bid'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">ask</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ask'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">last</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'last'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">bid</span><span class="ow">and</span><span class="n">ask</span><span class="ow">and</span><span class="n">bid</span><span class="o">&gt;</span><span class="mi">0</span><span class="ow">and</span><span class="n">ask</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">bid</span><span class="o">+</span><span class="n">ask</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">last</span><span class="ow">and</span><span class="n">last</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">last</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_safe_float</span><span class="p">(</span><span class="n">val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="n">val</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_cached_contract_price</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">price</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_extract_contract_price</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Find the price of a specific option contract."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">])</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'expiration'</span><span class="p">)</span><span class="o">==</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_option_prices</span><span class="p">(</span><span class="n">option_positions</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">holdings</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download historical option prices from Alpha Vantage.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each (ticker, option_type) and each filing period:</span></span></span><span class="line"><span class="cl"><span class="s2"> 1. On the first trading day, fetch the chain and select the best contract</span></span></span><span class="line"><span class="cl"><span class="s2"> (matching type, expiry 9-15 months out, |delta| closest to 0.15).</span></span></span><span class="line"><span class="cl"><span class="s2"> 2. Lock in that contract for the period.</span></span></span><span class="line"><span class="cl"><span class="s2"> 3. Fetch the price of that contract on each subsequent trading day.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Returns</span></span></span><span class="line"><span class="cl"><span class="s2"> -------</span></span></span><span class="line"><span class="cl"><span class="s2"> per_period : dict {quarter_str: {(ticker, type): {date_str: float}}}</span></span></span><span class="line"><span class="cl"><span class="s2"> Option prices keyed by filing period then option position. Each period</span></span></span><span class="line"><span class="cl"><span class="s2"> has its own contract's prices, avoiding cross-contract mixing at</span></span></span><span class="line"><span class="cl"><span class="s2"> boundary dates where one period ends and the next begins.</span></span></span><span class="line"><span class="cl"><span class="s2"> fallback_positions : set</span></span></span><span class="line"><span class="cl"><span class="s2"> Option positions where no option data was found (need BS fallback).</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_positions</span><span class="o">=</span><span class="nb">sorted</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ALPHA_VANTAGE_KEY'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache_only</span><span class="o">=</span><span class="ow">not</span><span class="nb">bool</span><span class="p">(</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"WARNING: ALPHA_VANTAGE_KEY not set; using cached option "</span></span></span><span class="line"><span class="cl"><span class="s2">"prices where available and BS repricing elsewhere."</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">=</span><span class="p">{}</span><span class="c1"># {q: {(ticker, type): {date_str: price}}}</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip quarters where this exact option position is absent.</span></span></span><span class="line"><span class="cl"><span class="n">has_opts</span><span class="o">=</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">has_opts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="p">(</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">trading_days</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">bdate_range</span><span class="p">(</span><span class="n">period_start</span><span class="p">,</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">trading_days</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">first_day</span><span class="o">=</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Select contract on first trading day --</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">first_day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_best_contract</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">first_day</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">expiry</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Collect prices for this period (fresh dict per period) --</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">from_cache</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Fast path: read all matching prices from cache (no API calls).</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&lt;=</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Slow path: fetch each trading day from API</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">first_day</span><span class="p">]</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day</span><span class="ow">in</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cached_price</span><span class="o">=</span><span class="n">_cached_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cached_price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">cached_price</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_extract_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">day_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">expiry</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Accumulate per-period prices</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})[</span><span class="n">opt_key</span><span class="p">]</span><span class="o">=</span><span class="n">period_prices</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Persist new data to cache</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">new_rows</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">new_rows</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">([</span><span class="n">cache</span><span class="p">,</span><span class="n">new_df</span><span class="p">],</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">position_has_data</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">fetched</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">sys</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[options] Fetched</span><span class="si">{</span><span class="n">fetched</span><span class="si">}</span><span class="s2"> chain snapshots from Alpha Vantage"</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">per_period</span><span class="p">,</span><span class="n">fallback</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Fallback: Black-Scholes repricing for tickers without option data -----</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">scipy.stats</span><span class="kn">import</span><span class="n">norm</span><span class="k">as</span><span class="n">_norm</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_realized_vol</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">download_daily_fn</span><span class="p">,</span><span class="n">today_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute annualized realized vol from trailing 1-year daily returns."""</span></span></span><span class="line"><span class="cl"><span class="n">vol_start</span><span class="o">=</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">today_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">400</span><span class="p">))</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_df</span><span class="o">=</span><span class="n">download_daily_fn</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">vol_start</span><span class="p">,</span><span class="n">today_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">vol_df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">vol_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">series</span><span class="p">)</span><span class="o">&gt;</span><span class="mi">20</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">log_rets</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">series</span><span class="o">/</span><span class="n">series</span><span class="o">.</span><span class="n">shift</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span><span class="o">.</span><span class="n">tail</span><span class="p">(</span><span class="mi">252</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">log_rets</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">252</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_price</span><span class="p">(</span><span class="n">S</span><span class="p">,</span><span class="n">K</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Black-Scholes option price (assumes zero risk-free rate and dividends)."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">T</span><span class="o">&lt;=</span><span class="mi">0</span><span class="ow">or</span><span class="n">sigma</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">S</span><span class="o">-</span><span class="n">K</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">K</span><span class="o">-</span><span class="n">S</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">d1</span><span class="o">=</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">S</span><span class="o">/</span><span class="n">K</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">T</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">d2</span><span class="o">=</span><span class="n">d1</span><span class="o">-</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d1</span><span class="p">)</span><span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d2</span><span class="p">)</span><span class="o">-</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_option_return</span><span class="p">(</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">delta_t</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute option return from stock return using Black-Scholes repricing.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Normalizes S_0 = 1, so S_1 = 1 + stock_return and K = K_over_S.</span></span></span><span class="line"><span class="cl"><span class="s2"> T is time to expiry at period start; delta_t is time elapsed.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">V0</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">V1</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="o">+</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="nb">max</span><span class="p">(</span><span class="n">T</span><span class="o">-</span><span class="n">delta_t</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">V0</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">stock_return</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">V1</span><span class="o">/</span><span class="n">V0</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_DELTA</span><span class="o">=</span><span class="mf">0.15</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_T</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">build_option_params</span><span class="p">(</span><span class="n">option_tickers</span><span class="p">,</span><span class="n">ticker_vol</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build {ticker: (K_over_S_call, K_over_S_put, sigma)} for BS fallback."""</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">t</span><span class="ow">in</span><span class="n">option_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">t</span><span class="ow">not</span><span class="ow">in</span><span class="n">ticker_vol</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="o">=</span><span class="n">ticker_vol</span><span class="p">[</span><span class="n">t</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">srt</span><span class="o">=</span><span class="n">sigma</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">**</span><span class="mf">0.5</span></span></span><span class="line"><span class="cl"><span class="c1"># Call: delta = N(d1) = OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_call</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_call</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1"># Put: delta = N(d1) - 1 = -OPTION_DELTA, so N(d1) = 1 - OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_put</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_put</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_put</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">t</span><span class="p">]</span><span class="o">=</span><span class="p">(</span><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">daily_cumulative</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="n">mode</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">per_period_opt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build a daily series of cumulative growth factors for a given mode.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each filing period the portfolio weights are fixed. Each trading</span></span></span><span class="line"><span class="cl"><span class="s2"> day's weighted return is computed relative to the period's starting</span></span></span><span class="line"><span class="cl"><span class="s2"> prices, then chained with the prior period's cumulative growth.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions: uses per-period option prices from per_period_opt</span></span></span><span class="line"><span class="cl"><span class="s2"> when available; otherwise falls back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span></span></span><span class="line"><span class="cl"><span class="n">ps</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pe</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Trading days in this period</span></span></span><span class="line"><span class="cl"><span class="n">mask</span><span class="o">=</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">)</span><span class="o">&amp;</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">period_close</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_close</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Option prices for this period (keyed by (ticker, type) → prices)</span></span></span><span class="line"><span class="cl"><span class="n">quarter_opt</span><span class="o">=</span><span class="n">per_period_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})</span><span class="k">if</span><span class="n">per_period_opt</span><span class="k">else</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Determine portfolio weights and starting prices</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">weights</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="o">=</span><span class="p">{}</span><span class="c1"># track which positions use option prices</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Select price source for this position</span></span></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">has_opt</span><span class="o">=</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">quarter_opt</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">has_opt</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ticker_opt</span><span class="o">=</span><span class="n">quarter_opt</span><span class="p">[</span><span class="n">opt_key</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">opt_dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">ticker_opt</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">opt_dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">ticker_opt</span><span class="p">[</span><span class="n">opt_dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">src</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">avail</span><span class="o">=</span><span class="n">src</span><span class="p">[</span><span class="n">src</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avail</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">avail</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">weights</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">has_opt</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total_value</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Daily weighted return relative to period start</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip first day of subsequent periods (already recorded as last day</span></span></span><span class="line"><span class="cl"><span class="c1"># of the prior period) to avoid duplicate boundary dates.</span></span></span><span class="line"><span class="cl"><span class="n">start_idx</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="n">i</span><span class="o">&gt;</span><span class="mi">0</span><span class="k">else</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="c1"># Forward-fill: track last known option price so that gaps in</span></span></span><span class="line"><span class="cl"><span class="c1"># option data don't cause positions to vanish mid-period.</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="o">=</span><span class="p">{</span><span class="n">k</span><span class="p">:</span><span class="n">v</span><span class="k">for</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="ow">in</span><span class="n">start_prices</span><span class="o">.</span><span class="n">items</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">k</span><span class="p">)}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day_idx</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="n">start_idx</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">period_close</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">day</span><span class="o">=</span><span class="n">period_close</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">weights</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">quarter_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">,</span><span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">day_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">p1_val</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">last_opt</span><span class="o">.</span><span class="n">get</span><span class="p">((</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">period_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">period_close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1_val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1_val</span><span class="p">)</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing for option positions without option data</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="ow">not</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]):</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="p">(</span><span class="n">day</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="p">(</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span><span class="p">)</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cum_growth</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">weighted_return</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Chain: next period starts from the last day's growth factor</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">values_out</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="n">values_out</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">dates_out</span><span class="p">,</span><span class="n">values_out</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">first_qe</span><span class="o">=</span><span class="n">quarter_end_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">last_fd</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">dc</span><span class="o">=</span><span class="n">download_daily</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">),</span><span class="n">first_qe</span><span class="p">,</span><span class="n">last_fd</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">pf_ret</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">close_df</span><span class="p">,</span><span class="n">i0</span><span class="p">,</span><span class="n">i1</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'equity_only'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Weighted portfolio return between index positions i0 and i1."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">i0</span><span class="o">&gt;=</span><span class="n">i1</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="mf">0.0</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">close_df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">close_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">i0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">p1</span><span class="o">=</span><span class="n">close_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">i1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p0</span><span class="p">)</span><span class="ow">or</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="ow">or</span><span class="nb">float</span><span class="p">(</span><span class="n">p0</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">-</span><span class="nb">float</span><span class="p">(</span><span class="n">p0</span><span class="p">))</span><span class="o">/</span><span class="nb">float</span><span class="p">(</span><span class="n">p0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="n">value</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">weighted_return</span><span class="o">/</span><span class="n">total_value</span><span class="k">if</span><span class="n">total_value</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">slice_dc</span><span class="p">(</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Slice the daily close DataFrame to a date range (inclusive)."""</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">dc</span><span class="p">[(</span><span class="n">dc</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">start_date</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">dc</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">end_date</span><span class="p">))]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Unified delay cost analysis ──────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="c1"># The copycat holds Q_{i-1} from filing_{i-1} to filing_i. We model</span></span></span><span class="line"><span class="cl"><span class="c1"># the fund as switching from Q_{i-1} to Q_i uniformly during quarter i,</span></span></span><span class="line"><span class="cl"><span class="c1"># and from Q_i to Q_{i+1} uniformly during quarter i+1.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"COPYCAT DELAY COST (equity-only, uniform switch model)"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"="</span><span class="o">*</span><span class="mi">57</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Transition'</span><span class="si">:</span><span class="s2">&lt;19</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Intra-Q'</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Gap'</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="s1">'Total'</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"-"</span><span class="o">*</span><span class="mi">57</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cum_intra</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">cum_gap</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">cum_total</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">prev_q</span><span class="o">=</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">curr_q</span><span class="o">=</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">next_q</span><span class="o">=</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span><span class="k">if</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">qe_prev</span><span class="o">=</span><span class="n">quarter_end_dates</span><span class="p">[</span><span class="n">prev_q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">qe_curr</span><span class="o">=</span><span class="n">quarter_end_dates</span><span class="p">[</span><span class="n">curr_q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">fd_curr</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">curr_q</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Intra-quarter: qe[i-1] to qe[i] ─────────────────────────</span></span></span><span class="line"><span class="cl"><span class="c1"># For each trading day d, compute R(Q_i, d, T) - R(Q_{i-1}, d, T).</span></span></span><span class="line"><span class="cl"><span class="n">pc_q</span><span class="o">=</span><span class="n">slice_dc</span><span class="p">(</span><span class="n">qe_prev</span><span class="p">,</span><span class="n">qe_curr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">N_q</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="n">pc_q</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">intra_costs</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="n">N_q</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">r_new</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">curr_q</span><span class="p">],</span><span class="n">pc_q</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">N_q</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">r_old</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">prev_q</span><span class="p">],</span><span class="n">pc_q</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">N_q</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">r_new</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">r_old</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">intra_costs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r_new</span><span class="o">-</span><span class="n">r_old</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">avg_intra</span><span class="o">=</span><span class="nb">sum</span><span class="p">(</span><span class="n">intra_costs</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">intra_costs</span><span class="p">)</span><span class="k">if</span><span class="n">intra_costs</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Gap: qe[i] to filing[i] ─────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="c1"># The fund may hold Q_i or may have already switched to Q_{i+1}.</span></span></span><span class="line"><span class="cl"><span class="n">pc_g</span><span class="o">=</span><span class="n">slice_dc</span><span class="p">(</span><span class="n">qe_curr</span><span class="p">,</span><span class="n">fd_curr</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">M</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="n">pc_g</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="c1"># trading days in the gap</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">M</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="mf">0.0</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">next_q</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Count trading days in quarter i+1 for probabilities</span></span></span><span class="line"><span class="cl"><span class="n">qe_next</span><span class="o">=</span><span class="n">quarter_end_dates</span><span class="p">[</span><span class="n">next_q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pc_full</span><span class="o">=</span><span class="n">slice_dc</span><span class="p">(</span><span class="n">qe_curr</span><span class="p">,</span><span class="n">qe_next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">N_full</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="n">pc_full</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">pc_full</span><span class="p">)</span><span class="o">&gt;</span><span class="mi">1</span><span class="k">else</span><span class="mi">63</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">r_copy</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">prev_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">M</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">r_copy</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># No-switch: fund holds Q_i for entire gap (switch after gap)</span></span></span><span class="line"><span class="cl"><span class="n">r_qi</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">curr_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">M</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">no_switch</span><span class="o">=</span><span class="p">(</span><span class="n">r_qi</span><span class="o">-</span><span class="n">r_copy</span><span class="p">)</span><span class="k">if</span><span class="n">r_qi</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Switch on day d: fund holds Q_i for [0, d], Q_{i+1} for [d, M]</span></span></span><span class="line"><span class="cl"><span class="n">switch_costs</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">M</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">r_a</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">curr_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">r_b</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">next_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">M</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">r_a</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">r_b</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">r_fund</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">r_a</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">r_b</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">switch_costs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r_fund</span><span class="o">-</span><span class="n">r_copy</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">p_no</span><span class="o">=</span><span class="p">(</span><span class="n">N_full</span><span class="o">-</span><span class="n">M</span><span class="p">)</span><span class="o">/</span><span class="n">N_full</span></span></span><span class="line"><span class="cl"><span class="n">p_each</span><span class="o">=</span><span class="mi">1</span><span class="o">/</span><span class="n">N_full</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">no_switch</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="n">p_no</span><span class="o">*</span><span class="n">no_switch</span><span class="o">+</span><span class="n">p_each</span><span class="o">*</span><span class="nb">sum</span><span class="p">(</span><span class="n">switch_costs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">switch_costs</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="n">p_each</span><span class="o">*</span><span class="nb">sum</span><span class="p">(</span><span class="n">switch_costs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Q_{i+1} not available: simple Q_i vs Q_{i-1}</span></span></span><span class="line"><span class="cl"><span class="n">r_qi</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">curr_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">M</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">r_old</span><span class="o">=</span><span class="n">pf_ret</span><span class="p">(</span><span class="n">holdings</span><span class="p">[</span><span class="n">prev_q</span><span class="p">],</span><span class="n">pc_g</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">M</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">r_qi</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">r_old</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="n">r_qi</span><span class="o">-</span><span class="n">r_old</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">avg_gap</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># ── Total ────────────────────────────────────────────────────</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avg_intra</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">avg_gap</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">total</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">avg_intra</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">avg_gap</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">avg_intra</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">total</span><span class="o">=</span><span class="n">avg_intra</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">avg_gap</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">total</span><span class="o">=</span><span class="n">avg_gap</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">total</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avg_intra</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_intra</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">avg_intra</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avg_gap</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_gap</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">avg_gap</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_total</span><span class="o">*=</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">total</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">suffix</span><span class="o">=</span><span class="s2">"</span><span class="se">\u2020</span><span class="s2">"</span><span class="k">if</span><span class="n">next_q</span><span class="ow">is</span><span class="kc">None</span><span class="k">else</span><span class="s2">""</span></span></span><span class="line"><span class="cl"><span class="n">label</span><span class="o">=</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">prev_q</span><span class="si">}</span><span class="s2"/><span class="se">\u2192</span><span class="s2"/><span class="si">{</span><span class="n">curr_q</span><span class="si">}</span><span class="s2">"</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">label</span><span class="o">+</span><span class="n">suffix</span><span class="si">:</span><span class="s2">&lt;19</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">avg_intra</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">avg_gap</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">total</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"-"</span><span class="o">*</span><span class="mi">57</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="s1">'Cumulative'</span><span class="si">:</span><span class="s2">&lt;19</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_intra</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_gap</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2"/><span class="si">{</span><span class="n">fmt</span><span class="p">(</span><span class="n">cum_total</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="si">:</span><span class="s2">&gt;10</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"Intra-Q = avg cost of fund switching to Q_i during quarter i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"Gap = cost during ~45-day gap, with possible Q_i</span><span class="se">\u2192</span><span class="s2"> Q_{i+1} switch"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\u2020</span><span class="s2"> = Q_{i+1} not yet available; gap uses simple Q_i vs Q_{i-1}"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"Positive = delay hurts the copycat"</span><span class="p">)</span></span></span></code></pre></div></div></details><p>For evaluating the copycat strategy in isolation, this analysis adds little: the historical returns already price in these delay costs. Where it is more relevant is in comparing the copycat against the fund itself. The delay cost estimates one observable component of the tracking gap; the other limitations discussed<a href="/notes/situational-awareness-lp/">above</a> remain unobserved and could move the realized gap in either direction.</p><p>As noted, the compounded delay cost over four quarterly transitions (approximately one year) is 85.97%. This estimate uses only equity positions. The true gap between the copycat and the fund could be larger or smaller depending on the fund’s undisclosed option contracts, short positions, foreign-listed securities, non-equity assets, and actual trading path, so I would treat the figure as evidence that disclosure lag matters rather than as a literal estimate of the fund’s net investor return.</p><h2 id="portfolio-calculator">Portfolio calculator</h2><p>The calculator below converts the most recent 13F filing into a concrete trade list. In equity-only mode, it allocates whole shares in proportion to the fund&rsquo;s reported equity weights. In full-exposure mode, option rows are treated as underlying notional targets; when a cached representative contract is available, the calculator estimates contract counts and premium cost, but the exact option contracts remain undisclosed. An optional cutoff drops positions below a given portfolio percentage and redistributes their weight among the rest. You can also exclude individual rows, or include rows below the cutoff, by selecting the relevant checkboxes.</p><details><summary>Code</summary><div class="details"><p><a id="code-snippet--sa-calc"/></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">json</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">yfinance</span><span class="k">as</span><span class="nn">yf</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">pandas</span><span class="k">as</span><span class="nn">pd</span></span></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">datetime</span><span class="kn">import</span><span class="n">datetime</span><span class="p">,</span><span class="n">timedelta</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">numpy</span><span class="k">as</span><span class="nn">np</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">requests</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">time</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">os</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">warnings</span></span></span><span class="line"><span class="cl"><span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s1">'ignore'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Parse data from the scraper block</span></span></span><span class="line"><span class="cl"><span class="n">parsed</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="nb">str</span><span class="p">)</span><span class="k">else</span><span class="n">data</span></span></span><span class="line"><span class="cl"><span class="n">filings</span><span class="o">=</span><span class="n">parsed</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Build internal structures</span></span></span><span class="line"><span class="cl"><span class="n">filing_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarter_end_dates</span><span class="o">=</span><span class="p">{</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]:</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter_end"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">quarters</span><span class="o">=</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Convert holdings list to dict keyed by quarter.</span></span></span><span class="line"><span class="cl"><span class="c1"># Multiple positions in the same ticker with different types are aggregated</span></span></span><span class="line"><span class="cl"><span class="c1"># by value per (ticker, type) pair.</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">f</span><span class="ow">in</span><span class="n">filings</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">f</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">ticker</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">value</span><span class="o">=</span><span class="n">h</span><span class="p">[</span><span class="s2">"value"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="n">positions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">holdings</span><span class="p">[</span><span class="n">f</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]]</span><span class="o">=</span><span class="n">positions</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">get_prices</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">dates</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch close prices for tickers on specific dates."""</span></span></span><span class="line"><span class="cl"><span class="n">unique_tickers</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">tickers</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">dates</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="nb">min</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="nb">max</span><span class="p">(</span><span class="n">all_dates</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">unique_tickers</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># yf.download returns MultiIndex columns (metric, ticker) for multiple tickers</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">unique_tickers</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">unique_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">not</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">series</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">date_str</span><span class="ow">in</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">target</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">after</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">after</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">after</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">before</span><span class="o">=</span><span class="n">series</span><span class="p">[</span><span class="n">series</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">target</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">before</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">date_str</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">before</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">prices</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the first available price on/after target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">target_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return (date, price) for the last available price on/before target."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">px_by_date</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">px_by_date</span><span class="k">if</span><span class="n">d</span><span class="o">&lt;=</span><span class="n">target_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">d</span><span class="o">=</span><span class="n">dates</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">d</span><span class="p">,</span><span class="n">px_by_date</span><span class="p">[</span><span class="n">d</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_period_price_pair</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return start/end prices for a period using sensible boundary alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">_price_on_or_after</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">start_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">_price_on_or_before</span><span class="p">(</span><span class="n">px_by_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">start</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">end</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">p0</span><span class="o">=</span><span class="n">start</span></span></span><span class="line"><span class="cl"><span class="n">end_actual</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">end</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">end_actual</span><span class="o">&lt;</span><span class="n">start_actual</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_return</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">prices</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="s1">'equity_only'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_prices</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute weighted portfolio return between two dates.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions (call/put): if option_prices contains actual</span></span></span><span class="line"><span class="cl"><span class="s2"> historical option prices for the ticker, compute returns directly from</span></span></span><span class="line"><span class="cl"><span class="s2"> those prices. Otherwise fall back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> the parameters in option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_px</span><span class="o">=</span><span class="n">option_prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span><span class="k">if</span><span class="n">option_prices</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="nb">bool</span><span class="p">(</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">opt_px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">use_option_px</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">px</span><span class="o">=</span><span class="n">prices</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pair</span><span class="o">=</span><span class="n">_period_price_pair</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pair</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">,</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="o">=</span><span class="n">pair</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="n">p1</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing when no option price data</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">is_option</span><span class="ow">and</span><span class="ow">not</span><span class="n">use_option_px</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="n">days_between</span><span class="p">(</span><span class="n">start_actual</span><span class="p">,</span><span class="n">end_actual</span><span class="p">)</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="c1"># When using actual option/BS prices the return already reflects</span></span></span><span class="line"><span class="cl"><span class="c1"># the directional bet, so sign is +1. The -1 for puts applies</span></span></span><span class="line"><span class="cl"><span class="c1"># only to the raw stock-price proxy path.</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_option_px</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="n">value</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">weighted_return</span><span class="o">/</span><span class="n">total_value</span><span class="k">if</span><span class="n">total_value</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">annualize</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">days</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Annualize a return over a given number of calendar days."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">days</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">ret</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="mf">365.25</span><span class="o">/</span><span class="n">days</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">days_between</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="n">d2</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d2</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d1</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">))</span><span class="o">.</span><span class="n">days</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">fmt</span><span class="p">(</span><span class="n">ret</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">ret</span><span class="o">*</span><span class="mi">100</span><span class="si">:</span><span class="s2">+.2f</span><span class="si">}</span><span class="s2">%"</span><span class="k">if</span><span class="n">ret</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="k">else</span><span class="s2">"N/A"</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Collect all tickers and dates</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">positions</span><span class="ow">in</span><span class="n">holdings</span><span class="o">.</span><span class="n">values</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_</span><span class="p">)</span><span class="ow">in</span><span class="n">positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">all_tickers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">'SPY'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">first_date</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">all_dates</span><span class="o">=</span><span class="nb">set</span><span class="p">(</span><span class="n">filing_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="nb">set</span><span class="p">(</span><span class="n">quarter_end_dates</span><span class="o">.</span><span class="n">values</span><span class="p">())</span><span class="o">|</span><span class="p">{</span><span class="n">today</span><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">prices</span><span class="o">=</span><span class="n">get_prices</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_tickers</span><span class="p">),</span><span class="nb">sorted</span><span class="p">(</span><span class="n">all_dates</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Resolve `today` to the actual last available closing date.</span></span></span><span class="line"><span class="cl"><span class="c1"># yfinance may not have data for today (market still open or holiday),</span></span></span><span class="line"><span class="cl"><span class="c1"># so we look up what date SPY's price actually corresponds to.</span></span></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">requested_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Return the actual trading date of the price stored under requested_date."""</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="s1">'SPY'</span><span class="k">if</span><span class="s1">'SPY'</span><span class="ow">in</span><span class="n">prices</span><span class="k">else</span><span class="nb">next</span><span class="p">(</span><span class="nb">iter</span><span class="p">(</span><span class="n">prices</span><span class="p">),</span><span class="kc">None</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">ref</span><span class="ow">or</span><span class="n">requested_date</span><span class="ow">not</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="n">target_price</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ref</span><span class="p">][</span><span class="n">requested_date</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="c1"># Re-download a small window to find the real date of this price</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">requested_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">ref</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">][</span><span class="n">ref</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="s1">'Close'</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">iloc</span><span class="p">[:,</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">dt</span><span class="p">,</span><span class="n">px</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">val</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">px</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">)</span><span class="k">else</span><span class="nb">float</span><span class="p">(</span><span class="n">px</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">abs</span><span class="p">(</span><span class="n">val</span><span class="o">-</span><span class="n">target_price</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ts</span><span class="o">=</span><span class="n">dt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span><span class="nb">tuple</span><span class="p">)</span><span class="k">else</span><span class="n">dt</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">ts</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">requested_date</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">today_resolved</span><span class="o">=</span><span class="n">_resolve_price_date</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today_resolved</span><span class="o">!=</span><span class="n">today</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">today</span><span class="ow">in</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">today_resolved</span><span class="p">]</span><span class="o">=</span><span class="n">prices</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="o">=</span><span class="n">today_resolved</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_daily</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">start_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download daily close prices from yfinance, handling MultiIndex.</span></span></span><span class="line"><span class="cl"><span class="s2"> Dates are 'YYYY-MM-DD' strings. Adds a small buffer for trading-day alignment."""</span></span></span><span class="line"><span class="cl"><span class="n">tickers_sorted</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">tickers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">start</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">start_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">end</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">end_date</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">yf</span><span class="o">.</span><span class="n">download</span><span class="p">(</span><span class="n">tickers_sorted</span><span class="p">,</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">progress</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span><span class="n">auto_adjust</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">,</span><span class="n">pd</span><span class="o">.</span><span class="n">MultiIndex</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">df</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">=</span><span class="n">df</span><span class="p">[[</span><span class="s1">'Close'</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="o">=</span><span class="n">tickers_sorted</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">close</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Historical option prices via Alpha Vantage ----------------------------</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_DIR</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/notes/.sa-lp-option-cache'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_AV_BASE</span><span class="o">=</span><span class="s1">'https://www.alphavantage.co/query'</span></span></span><span class="line"><span class="cl"><span class="n">_AV_RATE_DELAY</span><span class="o">=</span><span class="mf">0.85</span><span class="c1"># seconds between requests (75 req/min limit)</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_CACHE_COLUMNS</span><span class="o">=</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="ow">not</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">raise</span><span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unsupported option type:</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_empty_option_cache</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">columns</span><span class="o">=</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">ticker</span><span class="si">}</span><span class="s1">-</span><span class="si">{</span><span class="n">option_type</span><span class="si">}</span><span class="s1">.csv'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Load cached option data for a ticker/type. Returns DataFrame or empty."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">=</span><span class="p">[</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="c1"># Pre-fix caches were call-only and named TICKER.csv. They are safe to</span></span></span><span class="line"><span class="cl"><span class="c1"># reuse for calls but must not be reused for puts.</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">legacy_path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">legacy</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">legacy_path</span><span class="ow">not</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">legacy_path</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">path</span><span class="ow">in</span><span class="n">paths</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="s1">'option_type'</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="s1">'call'</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_datetime</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span><span class="o">.</span><span class="n">dt</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">.</span><span class="n">fillna</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">frames</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">frames</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">(</span><span class="n">frames</span><span class="p">,</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'delta'</span><span class="p">,</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">to_numeric</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">col</span><span class="p">],</span><span class="n">errors</span><span class="o">=</span><span class="s1">'coerce'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">cache</span><span class="p">[</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">df</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Persist typed option cache to CSV."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">path</span><span class="o">=</span><span class="n">_option_cache_path</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">df</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">_empty_option_cache</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">=</span><span class="n">df</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">=</span><span class="n">option_type</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">col</span><span class="ow">in</span><span class="n">OPTION_CACHE_COLUMNS</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">col</span><span class="ow">not</span><span class="ow">in</span><span class="n">df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">path</span><span class="p">,</span><span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Fetch the full option chain for ticker on a given date from Alpha Vantage."""</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'function'</span><span class="p">:</span><span class="s1">'HISTORICAL_OPTIONS'</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'symbol'</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">date_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'apikey'</span><span class="p">:</span><span class="n">api_key</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">=</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_AV_BASE</span><span class="p">,</span><span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">resp</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">body</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">json</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">body</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span><span class="p">[])</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="ne">Exception</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">ref</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">270</span><span class="p">),</span><span class="n">ref</span><span class="o">+</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">456</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'option_type'</span><span class="p">,</span><span class="n">option_type</span><span class="p">))</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'strike'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">strike</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_contract_from_cache_row</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">contract</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_select_best_contract</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">ref_date_str</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Select the best-matching call/put contract from an option chain.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Criteria: matching option type, expiry 9-15 months from ref_date,</span></span></span><span class="line"><span class="cl"><span class="s2"> absolute delta closest to 0.15. Returns dict with type, strike, expiry,</span></span></span><span class="line"><span class="cl"><span class="s2"> delta, price or None.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">lo</span><span class="p">,</span><span class="n">hi</span><span class="o">=</span><span class="n">_contract_window</span><span class="p">(</span><span class="n">ref_date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">exp</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="p">(</span><span class="n">lo</span><span class="o">&lt;=</span><span class="n">exp</span><span class="o">&lt;=</span><span class="n">hi</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">delta</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'delta'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">delta</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">abs_delta</span><span class="o">=</span><span class="nb">abs</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">abs_delta</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="c1"># Price: prefer mid if available, else last</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="kc">None</span><span class="ow">or</span><span class="n">price</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">c</span><span class="p">[</span><span class="s1">'expiration'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">delta</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">candidates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="c1"># Pick contract with absolute delta closest to 0.15.</span></span></span><span class="line"><span class="cl"><span class="n">candidates</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">])</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">candidates</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_parse_option_price</span><span class="p">(</span><span class="n">contract</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Extract a price from an Alpha Vantage option contract record."""</span></span></span><span class="line"><span class="cl"><span class="n">bid</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'bid'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">ask</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ask'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">last</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'last'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">bid</span><span class="ow">and</span><span class="n">ask</span><span class="ow">and</span><span class="n">bid</span><span class="o">&gt;</span><span class="mi">0</span><span class="ow">and</span><span class="n">ask</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="p">(</span><span class="n">bid</span><span class="o">+</span><span class="n">ask</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">last</span><span class="ow">and</span><span class="n">last</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">last</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_safe_float</span><span class="p">(</span><span class="n">val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">float</span><span class="p">(</span><span class="n">val</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_cached_contract_price</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">date_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">==</span><span class="n">date_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_safe_float</span><span class="p">(</span><span class="n">row</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="ow">and</span><span class="n">price</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">_extract_contract_price</span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Find the price of a specific option contract."""</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">chain</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'type'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">!=</span><span class="n">option_type</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">try</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">])</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'expiration'</span><span class="p">)</span><span class="o">==</span><span class="n">expiry</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">_parse_option_price</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">except</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span><span class="ne">TypeError</span><span class="p">,</span><span class="ne">ValueError</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="kc">None</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">download_option_prices</span><span class="p">(</span><span class="n">option_positions</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">holdings</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">today</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Download historical option prices from Alpha Vantage.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each (ticker, option_type) and each filing period:</span></span></span><span class="line"><span class="cl"><span class="s2"> 1. On the first trading day, fetch the chain and select the best contract</span></span></span><span class="line"><span class="cl"><span class="s2"> (matching type, expiry 9-15 months out, |delta| closest to 0.15).</span></span></span><span class="line"><span class="cl"><span class="s2"> 2. Lock in that contract for the period.</span></span></span><span class="line"><span class="cl"><span class="s2"> 3. Fetch the price of that contract on each subsequent trading day.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Returns</span></span></span><span class="line"><span class="cl"><span class="s2"> -------</span></span></span><span class="line"><span class="cl"><span class="s2"> per_period : dict {quarter_str: {(ticker, type): {date_str: float}}}</span></span></span><span class="line"><span class="cl"><span class="s2"> Option prices keyed by filing period then option position. Each period</span></span></span><span class="line"><span class="cl"><span class="s2"> has its own contract's prices, avoiding cross-contract mixing at</span></span></span><span class="line"><span class="cl"><span class="s2"> boundary dates where one period ends and the next begins.</span></span></span><span class="line"><span class="cl"><span class="s2"> fallback_positions : set</span></span></span><span class="line"><span class="cl"><span class="s2"> Option positions where no option data was found (need BS fallback).</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">option_positions</span><span class="o">=</span><span class="nb">sorted</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">_normalize_option_type</span><span class="p">(</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ALPHA_VANTAGE_KEY'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache_only</span><span class="o">=</span><span class="ow">not</span><span class="nb">bool</span><span class="p">(</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">"WARNING: ALPHA_VANTAGE_KEY not set; using cached option "</span></span></span><span class="line"><span class="cl"><span class="s2">"prices where available and BS repricing elsewhere."</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">OPTION_CACHE_DIR</span><span class="p">,</span><span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">=</span><span class="p">{}</span><span class="c1"># {q: {(ticker, type): {date_str: price}}}</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">=</span><span class="nb">set</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="ow">in</span><span class="n">option_positions</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">_load_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip quarters where this exact option position is absent.</span></span></span><span class="line"><span class="cl"><span class="n">has_opts</span><span class="o">=</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">has_opts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="p">(</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">trading_days</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">bdate_range</span><span class="p">(</span><span class="n">period_start</span><span class="p">,</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">trading_days</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">first_day</span><span class="o">=</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Select contract on first trading day --</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_cached_contract</span><span class="p">(</span><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">first_day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">from_cache</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">cache_only</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">contract</span><span class="o">=</span><span class="n">_select_best_contract</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">first_day</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">first_day</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">strike</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">expiry</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Collect prices for this period (fresh dict per period) --</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">from_cache</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Fast path: read all matching prices from cache (no API calls).</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&lt;=</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'option_type'</span><span class="p">]</span><span class="o">==</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]</span><span class="o">-</span><span class="n">strike</span><span class="p">)</span><span class="o">&lt;</span><span class="mf">0.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">(</span><span class="n">expiry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">_</span><span class="p">,</span><span class="n">row</span><span class="ow">in</span><span class="n">rows</span><span class="o">.</span><span class="n">iterrows</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="c1"># Slow path: fetch each trading day from API</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">contract</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'price'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">first_day</span><span class="p">]</span><span class="o">=</span><span class="n">contract</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day</span><span class="ow">in</span><span class="n">trading_days</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cached_price</span><span class="o">=</span><span class="n">_cached_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">cached_price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">cached_price</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">_AV_RATE_DELAY</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="o">=</span><span class="n">_fetch_option_chain</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">day_str</span><span class="p">,</span><span class="n">api_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">fetched</span><span class="o">+=</span><span class="mi">1</span></span></span><span class="line"><span class="cl"><span class="n">price</span><span class="o">=</span><span class="n">_extract_contract_price</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">chain</span><span class="p">,</span><span class="n">strike</span><span class="p">,</span><span class="n">expiry</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">price</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">period_prices</span><span class="p">[</span><span class="n">day_str</span><span class="p">]</span><span class="o">=</span><span class="n">price</span></span></span><span class="line"><span class="cl"><span class="n">new_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span></span></span><span class="line"><span class="cl"><span class="s1">'date'</span><span class="p">:</span><span class="n">day_str</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'option_type'</span><span class="p">:</span><span class="n">option_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="n">strike</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="n">expiry</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s1">'delta'</span><span class="p">:</span><span class="n">contract</span><span class="p">[</span><span class="s1">'delta'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="n">price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="p">})</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Accumulate per-period prices</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_prices</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">per_period</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})[</span><span class="n">opt_key</span><span class="p">]</span><span class="o">=</span><span class="n">period_prices</span></span></span><span class="line"><span class="cl"><span class="n">position_has_data</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Persist new data to cache</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">new_rows</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">new_df</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">new_rows</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">([</span><span class="n">cache</span><span class="p">,</span><span class="n">new_df</span><span class="p">],</span><span class="n">ignore_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">drop_duplicates</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="n">subset</span><span class="o">=</span><span class="p">[</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'option_type'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">],</span></span></span><span class="line"><span class="cl"><span class="n">keep</span><span class="o">=</span><span class="s1">'last'</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">.</span><span class="n">sort_values</span><span class="p">([</span><span class="s1">'date'</span><span class="p">,</span><span class="s1">'expiry'</span><span class="p">,</span><span class="s1">'strike'</span><span class="p">],</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">_save_option_cache</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">option_type</span><span class="p">,</span><span class="n">cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">position_has_data</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">fallback</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">opt_key</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">fetched</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">sys</span></span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[options] Fetched</span><span class="si">{</span><span class="n">fetched</span><span class="si">}</span><span class="s2"> chain snapshots from Alpha Vantage"</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">per_period</span><span class="p">,</span><span class="n">fallback</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Fallback: Black-Scholes repricing for tickers without option data -----</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="kn">from</span><span class="nn">scipy.stats</span><span class="kn">import</span><span class="n">norm</span><span class="k">as</span><span class="n">_norm</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">compute_realized_vol</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">download_daily_fn</span><span class="p">,</span><span class="n">today_str</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute annualized realized vol from trailing 1-year daily returns."""</span></span></span><span class="line"><span class="cl"><span class="n">vol_start</span><span class="o">=</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">today_str</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">400</span><span class="p">))</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">vol_df</span><span class="o">=</span><span class="n">download_daily_fn</span><span class="p">(</span><span class="n">tickers</span><span class="p">,</span><span class="n">vol_start</span><span class="p">,</span><span class="n">today_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">ticker</span><span class="ow">in</span><span class="n">tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">vol_df</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">series</span><span class="o">=</span><span class="n">vol_df</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="nb">len</span><span class="p">(</span><span class="n">series</span><span class="p">)</span><span class="o">&gt;</span><span class="mi">20</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">log_rets</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">series</span><span class="o">/</span><span class="n">series</span><span class="o">.</span><span class="n">shift</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span><span class="o">.</span><span class="n">tail</span><span class="p">(</span><span class="mi">252</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">log_rets</span><span class="o">.</span><span class="n">std</span><span class="p">()</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">252</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_price</span><span class="p">(</span><span class="n">S</span><span class="p">,</span><span class="n">K</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Black-Scholes option price (assumes zero risk-free rate and dividends)."""</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">T</span><span class="o">&lt;=</span><span class="mi">0</span><span class="ow">or</span><span class="n">sigma</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">S</span><span class="o">-</span><span class="n">K</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="nb">max</span><span class="p">(</span><span class="n">K</span><span class="o">-</span><span class="n">S</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">d1</span><span class="o">=</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">S</span><span class="o">/</span><span class="n">K</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">T</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="n">d2</span><span class="o">=</span><span class="n">d1</span><span class="o">-</span><span class="n">sigma</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">T</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">option_type</span><span class="o">==</span><span class="s1">'call'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d1</span><span class="p">)</span><span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="n">d2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">K</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d2</span><span class="p">)</span><span class="o">-</span><span class="n">S</span><span class="o">*</span><span class="n">_norm</span><span class="o">.</span><span class="n">cdf</span><span class="p">(</span><span class="o">-</span><span class="n">d1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">bs_option_return</span><span class="p">(</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">delta_t</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">option_type</span><span class="o">=</span><span class="s1">'call'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Compute option return from stock return using Black-Scholes repricing.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> Normalizes S_0 = 1, so S_1 = 1 + stock_return and K = K_over_S.</span></span></span><span class="line"><span class="cl"><span class="s2"> T is time to expiry at period start; delta_t is time elapsed.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">V0</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">T</span><span class="p">,</span><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">V1</span><span class="o">=</span><span class="n">bs_price</span><span class="p">(</span><span class="mf">1.0</span><span class="o">+</span><span class="n">stock_return</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="nb">max</span><span class="p">(</span><span class="n">T</span><span class="o">-</span><span class="n">delta_t</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">option_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">V0</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">stock_return</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">V1</span><span class="o">/</span><span class="n">V0</span><span class="o">-</span><span class="mi">1</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">OPTION_DELTA</span><span class="o">=</span><span class="mf">0.15</span></span></span><span class="line"><span class="cl"><span class="n">OPTION_T</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">build_option_params</span><span class="p">(</span><span class="n">option_tickers</span><span class="p">,</span><span class="n">ticker_vol</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build {ticker: (K_over_S_call, K_over_S_put, sigma)} for BS fallback."""</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">t</span><span class="ow">in</span><span class="n">option_tickers</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">t</span><span class="ow">not</span><span class="ow">in</span><span class="n">ticker_vol</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="o">=</span><span class="n">ticker_vol</span><span class="p">[</span><span class="n">t</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">srt</span><span class="o">=</span><span class="n">sigma</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">**</span><span class="mf">0.5</span></span></span><span class="line"><span class="cl"><span class="c1"># Call: delta = N(d1) = OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_call</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_call</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1"># Put: delta = N(d1) - 1 = -OPTION_DELTA, so N(d1) = 1 - OPTION_DELTA</span></span></span><span class="line"><span class="cl"><span class="n">d1_put</span><span class="o">=</span><span class="n">_norm</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">OPTION_DELTA</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">K_put</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">exp</span><span class="p">(</span><span class="o">-</span><span class="n">d1_put</span><span class="o">*</span><span class="n">srt</span><span class="o">+</span><span class="n">sigma</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">OPTION_T</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">result</span><span class="p">[</span><span class="n">t</span><span class="p">]</span><span class="o">=</span><span class="p">(</span><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">result</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">daily_cumulative</span><span class="p">(</span><span class="n">holdings</span><span class="p">,</span><span class="n">quarters</span><span class="p">,</span><span class="n">filing_dates</span><span class="p">,</span><span class="n">close</span><span class="p">,</span><span class="n">today</span><span class="p">,</span><span class="n">mode</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">per_period_opt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">option_params</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="s2">"""Build a daily series of cumulative growth factors for a given mode.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For each filing period the portfolio weights are fixed. Each trading</span></span></span><span class="line"><span class="cl"><span class="s2"> day's weighted return is computed relative to the period's starting</span></span></span><span class="line"><span class="cl"><span class="s2"> prices, then chained with the prior period's cumulative growth.</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> For option positions: uses per-period option prices from per_period_opt</span></span></span><span class="line"><span class="cl"><span class="s2"> when available; otherwise falls back to Black-Scholes repricing using</span></span></span><span class="line"><span class="cl"><span class="s2"> option_params.</span></span></span><span class="line"><span class="cl"><span class="s2"> """</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="mf">1.0</span></span></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">i</span><span class="p">,</span><span class="n">q</span><span class="ow">in</span><span class="nb">enumerate</span><span class="p">(</span><span class="n">quarters</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">period_start</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">period_end</span><span class="o">=</span><span class="n">filing_dates</span><span class="p">[</span><span class="n">quarters</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]]</span><span class="k">if</span><span class="n">i</span><span class="o">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="n">quarters</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="k">else</span><span class="n">today</span></span></span><span class="line"><span class="cl"><span class="n">ps</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">pe</span><span class="o">=</span><span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">period_end</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Trading days in this period</span></span></span><span class="line"><span class="cl"><span class="n">mask</span><span class="o">=</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">)</span><span class="o">&amp;</span><span class="p">(</span><span class="n">close</span><span class="o">.</span><span class="n">index</span><span class="o">&lt;=</span><span class="n">pe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">period_close</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">period_close</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Option prices for this period (keyed by (ticker, type) → prices)</span></span></span><span class="line"><span class="cl"><span class="n">quarter_opt</span><span class="o">=</span><span class="n">per_period_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">q</span><span class="p">,</span><span class="p">{})</span><span class="k">if</span><span class="n">per_period_opt</span><span class="k">else</span><span class="p">{}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Determine portfolio weights and starting prices</span></span></span><span class="line"><span class="cl"><span class="n">positions</span><span class="o">=</span><span class="n">holdings</span><span class="p">[</span><span class="n">q</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">weights</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="o">=</span><span class="p">{}</span><span class="c1"># track which positions use option prices</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">mode</span><span class="o">==</span><span class="s1">'equity_only'</span><span class="ow">and</span><span class="n">pos_type</span><span class="o">!=</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Select price source for this position</span></span></span><span class="line"><span class="cl"><span class="n">is_option</span><span class="o">=</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">has_opt</span><span class="o">=</span><span class="n">is_option</span><span class="ow">and</span><span class="n">opt_key</span><span class="ow">in</span><span class="n">quarter_opt</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">has_opt</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">ticker_opt</span><span class="o">=</span><span class="n">quarter_opt</span><span class="p">[</span><span class="n">opt_key</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">opt_dates</span><span class="o">=</span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="k">for</span><span class="n">d</span><span class="ow">in</span><span class="n">ticker_opt</span><span class="k">if</span><span class="n">d</span><span class="o">&gt;=</span><span class="n">period_start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">opt_dates</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">ticker_opt</span><span class="p">[</span><span class="n">opt_dates</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">src</span><span class="o">=</span><span class="n">close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="n">avail</span><span class="o">=</span><span class="n">src</span><span class="p">[</span><span class="n">src</span><span class="o">.</span><span class="n">index</span><span class="o">&gt;=</span><span class="n">ps</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">avail</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="n">avail</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">weights</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">value</span></span></span><span class="line"><span class="cl"><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">has_opt</span></span></span><span class="line"><span class="cl"><span class="n">total_value</span><span class="o">+=</span><span class="n">value</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">total_value</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Daily weighted return relative to period start</span></span></span><span class="line"><span class="cl"><span class="c1"># Skip first day of subsequent periods (already recorded as last day</span></span></span><span class="line"><span class="cl"><span class="c1"># of the prior period) to avoid duplicate boundary dates.</span></span></span><span class="line"><span class="cl"><span class="n">start_idx</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="n">i</span><span class="o">&gt;</span><span class="mi">0</span><span class="k">else</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="c1"># Forward-fill: track last known option price so that gaps in</span></span></span><span class="line"><span class="cl"><span class="c1"># option data don't cause positions to vanish mid-period.</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="o">=</span><span class="p">{</span><span class="n">k</span><span class="p">:</span><span class="n">v</span><span class="k">for</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="ow">in</span><span class="n">start_prices</span><span class="o">.</span><span class="n">items</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">k</span><span class="p">)}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">day_idx</span><span class="ow">in</span><span class="nb">range</span><span class="p">(</span><span class="n">start_idx</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">period_close</span><span class="p">)):</span></span></span><span class="line"><span class="cl"><span class="n">day</span><span class="o">=</span><span class="n">period_close</span><span class="o">.</span><span class="n">index</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">day_str</span><span class="o">=</span><span class="n">day</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">=</span><span class="mi">0</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="n">weights</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></span></span><span class="line"><span class="cl"><span class="n">p0</span><span class="o">=</span><span class="n">start_prices</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p0</span><span class="o">==</span><span class="mi">0</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]:</span></span></span><span class="line"><span class="cl"><span class="n">opt_key</span><span class="o">=</span><span class="n">_option_position_key</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">quarter_opt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">opt_key</span><span class="p">,</span><span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">day_str</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="ow">not</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">last_opt</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="o">=</span><span class="n">p1_val</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">last_opt</span><span class="o">.</span><span class="n">get</span><span class="p">((</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">p1_val</span><span class="ow">is</span><span class="kc">None</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">ticker</span><span class="ow">in</span><span class="n">period_close</span><span class="o">.</span><span class="n">columns</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">p1_val</span><span class="o">=</span><span class="n">period_close</span><span class="p">[</span><span class="n">ticker</span><span class="p">]</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">day_idx</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">isna</span><span class="p">(</span><span class="n">p1_val</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">p1_val</span><span class="p">)</span><span class="o">-</span><span class="n">p0</span><span class="p">)</span><span class="o">/</span><span class="n">p0</span></span></span><span class="line"><span class="cl"><span class="c1"># Fallback: BS repricing for option positions without option data</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">False</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="ow">and</span><span class="ow">not</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]):</span></span></span><span class="line"><span class="cl"><span class="n">params</span><span class="o">=</span><span class="n">option_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ticker</span><span class="p">)</span><span class="k">if</span><span class="n">option_params</span><span class="k">else</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">params</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">K_call</span><span class="p">,</span><span class="n">K_put</span><span class="p">,</span><span class="n">sigma</span><span class="o">=</span><span class="n">params</span></span></span><span class="line"><span class="cl"><span class="n">K_over_S</span><span class="o">=</span><span class="n">K_call</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'call'</span><span class="k">else</span><span class="n">K_put</span></span></span><span class="line"><span class="cl"><span class="n">dt</span><span class="o">=</span><span class="p">(</span><span class="n">day</span><span class="o">-</span><span class="n">ps</span><span class="p">)</span><span class="o">.</span><span class="n">days</span><span class="o">/</span><span class="mf">365.25</span></span></span><span class="line"><span class="cl"><span class="n">ret</span><span class="o">=</span><span class="n">bs_option_return</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span><span class="n">K_over_S</span><span class="p">,</span><span class="n">OPTION_T</span><span class="p">,</span><span class="n">dt</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="n">sigma</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">use_bs</span><span class="o">=</span><span class="kc">True</span></span></span><span class="line"><span class="cl"><span class="n">sign</span><span class="o">=</span><span class="mi">1</span><span class="k">if</span><span class="p">(</span><span class="n">use_opt_px</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)]</span><span class="ow">or</span><span class="n">use_bs</span><span class="p">)</span><span class="k">else</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="o">-</span><span class="mi">1</span><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'put'</span><span class="k">else</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">weighted_return</span><span class="o">+=</span><span class="p">(</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span><span class="p">)</span><span class="o">*</span><span class="n">sign</span><span class="o">*</span><span class="n">ret</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">dates_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">values_out</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cum_growth</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="n">weighted_return</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Chain: next period starts from the last day's growth factor</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">values_out</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">cum_growth</span><span class="o">=</span><span class="n">values_out</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">dates_out</span><span class="p">,</span><span class="n">values_out</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="nn">os</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">HUGO_BASE</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~/My Drive/repos/stafforini.com'</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Build position data for both modes --------------------------------</span></span></span><span class="line"><span class="cl"><span class="n">latest</span><span class="o">=</span><span class="n">parsed</span><span class="p">[</span><span class="s2">"filings"</span><span class="p">][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">pos</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">latest</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">],</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="n">pos</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="n">pos</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">h</span><span class="p">[</span><span class="s2">"value"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">eq_pos</span><span class="o">=</span><span class="p">{</span><span class="n">k</span><span class="p">:</span><span class="n">v</span><span class="k">for</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="ow">in</span><span class="n">pos</span><span class="o">.</span><span class="n">items</span><span class="p">()</span><span class="k">if</span><span class="n">k</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">==</span><span class="s1">'long'</span><span class="p">}</span></span></span><span class="line"><span class="cl"><span class="n">eq_total</span><span class="o">=</span><span class="nb">sum</span><span class="p">(</span><span class="n">eq_pos</span><span class="o">.</span><span class="n">values</span><span class="p">())</span></span></span><span class="line"><span class="cl"><span class="n">full_total</span><span class="o">=</span><span class="nb">sum</span><span class="p">(</span><span class="n">pos</span><span class="o">.</span><span class="n">values</span><span class="p">())</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Fetch current underlying prices for all rows</span></span></span><span class="line"><span class="cl"><span class="n">calc_tickers</span><span class="o">=</span><span class="nb">sorted</span><span class="p">({</span><span class="n">t</span><span class="k">for</span><span class="p">(</span><span class="n">t</span><span class="p">,</span><span class="n">_</span><span class="p">)</span><span class="ow">in</span><span class="n">pos</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">current</span><span class="o">=</span><span class="n">get_prices</span><span class="p">(</span><span class="n">calc_tickers</span><span class="p">,</span><span class="p">[</span><span class="n">today</span><span class="p">])</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Load option contract info for the latest quarter</span></span></span><span class="line"><span class="cl"><span class="n">latest_fd</span><span class="o">=</span><span class="n">latest</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="n">opt_contracts</span><span class="o">=</span><span class="p">{}</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="n">h</span><span class="ow">in</span><span class="n">latest</span><span class="p">[</span><span class="s2">"holdings"</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="p">(</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">],</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">key</span><span class="ow">in</span><span class="n">opt_contracts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="k">continue</span></span></span><span class="line"><span class="cl"><span class="n">cache</span><span class="o">=</span><span class="n">_load_option_cache</span><span class="p">(</span><span class="n">h</span><span class="p">[</span><span class="s2">"ticker"</span><span class="p">],</span><span class="n">h</span><span class="p">[</span><span class="s2">"type"</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="n">period_rows</span><span class="o">=</span><span class="n">cache</span><span class="p">[(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]</span><span class="o">&gt;=</span><span class="n">latest_fd</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">&amp;</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="s1">'price'</span><span class="p">])]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="ow">not</span><span class="n">period_rows</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">=</span><span class="n">period_rows</span><span class="o">.</span><span class="n">sort_values</span><span class="p">(</span><span class="s1">'date'</span><span class="p">)</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">])</span><span class="ow">and</span><span class="n">pd</span><span class="o">.</span><span class="n">notna</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]):</span></span></span><span class="line"><span class="cl"><span class="n">opt_contracts</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">=</span><span class="p">{</span></span></span><span class="line"><span class="cl"><span class="s1">'strike'</span><span class="p">:</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'strike'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'expiry'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'expiry'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="s1">'price'</span><span class="p">:</span><span class="nb">round</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'price'</span><span class="p">]),</span><span class="mi">2</span><span class="p">),</span></span></span><span class="line"><span class="cl"><span class="s1">'price_as_of'</span><span class="p">:</span><span class="nb">str</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">'date'</span><span class="p">]),</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Build JSON data for both modes</span></span></span><span class="line"><span class="cl"><span class="k">def</span><span class="nf">build_mode_data</span><span class="p">(</span><span class="n">positions</span><span class="p">,</span><span class="n">total_value</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">=</span><span class="p">[]</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">),</span><span class="n">value</span><span class="ow">in</span><span class="nb">sorted</span><span class="p">(</span><span class="n">positions</span><span class="o">.</span><span class="n">items</span><span class="p">(),</span></span></span><span class="line"><span class="cl"><span class="n">key</span><span class="o">=</span><span class="k">lambda</span><span class="n">x</span><span class="p">:</span><span class="o">-</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span></span></span><span class="line"><span class="cl"><span class="n">weight</span><span class="o">=</span><span class="n">value</span><span class="o">/</span><span class="n">total_value</span></span></span><span class="line"><span class="cl"><span class="n">underlying_price</span><span class="o">=</span><span class="kc">None</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">=</span><span class="p">{</span><span class="s2">"ticker"</span><span class="p">:</span><span class="n">ticker</span><span class="p">,</span><span class="s2">"type"</span><span class="p">:</span><span class="n">pos_type</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"weight"</span><span class="p">:</span><span class="nb">round</span><span class="p">(</span><span class="n">weight</span><span class="p">,</span><span class="mi">6</span><span class="p">)}</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">ticker</span><span class="ow">in</span><span class="n">current</span><span class="ow">and</span><span class="n">today</span><span class="ow">in</span><span class="n">current</span><span class="p">[</span><span class="n">ticker</span><span class="p">]:</span></span></span><span class="line"><span class="cl"><span class="n">underlying_price</span><span class="o">=</span><span class="nb">round</span><span class="p">(</span><span class="n">current</span><span class="p">[</span><span class="n">ticker</span><span class="p">][</span><span class="n">today</span><span class="p">],</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="n">pos_type</span><span class="o">==</span><span class="s1">'long'</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"instrument"</span><span class="p">:</span><span class="s2">"stock"</span><span class="p">,</span><span class="s2">"price"</span><span class="p">:</span><span class="n">underlying_price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"underlying_price"</span><span class="p">:</span><span class="n">underlying_price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"multiplier"</span><span class="p">:</span><span class="mi">1</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="n">pos_type</span><span class="ow">in</span><span class="p">(</span><span class="s1">'call'</span><span class="p">,</span><span class="s1">'put'</span><span class="p">):</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"instrument"</span><span class="p">:</span><span class="s2">"option"</span><span class="p">,</span><span class="s2">"price"</span><span class="p">:</span><span class="kc">None</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"underlying_price"</span><span class="p">:</span><span class="n">underlying_price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"multiplier"</span><span class="p">:</span><span class="mi">100</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)</span><span class="ow">in</span><span class="n">opt_contracts</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">opt_contracts</span><span class="p">[(</span><span class="n">ticker</span><span class="p">,</span><span class="n">pos_type</span><span class="p">)])</span></span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">row</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"instrument"</span><span class="p">:</span><span class="s2">"stock"</span><span class="p">,</span><span class="s2">"price"</span><span class="p">:</span><span class="n">underlying_price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"underlying_price"</span><span class="p">:</span><span class="n">underlying_price</span><span class="p">,</span></span></span><span class="line"><span class="cl"><span class="s2">"multiplier"</span><span class="p">:</span><span class="mi">1</span><span class="p">})</span></span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">row</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">return</span><span class="n">rows</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">eq_data</span><span class="o">=</span><span class="n">build_mode_data</span><span class="p">(</span><span class="n">eq_pos</span><span class="p">,</span><span class="n">eq_total</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">full_data</span><span class="o">=</span><span class="n">build_mode_data</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span><span class="n">full_total</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">quarter</span><span class="o">=</span><span class="n">latest</span><span class="p">[</span><span class="s2">"quarter"</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"_"</span><span class="p">,</span><span class="s2">" "</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="n">filing_date</span><span class="o">=</span><span class="n">latest</span><span class="p">[</span><span class="s2">"filing_date"</span><span class="p">]</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># -- Generate self-contained HTML --------------------------------------</span></span></span><span class="line"><span class="cl"><span class="n">CSS</span><span class="o">=</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'/* reset */ * { margin: 0; padding: 0; box-sizing: border-box; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' sans-serif; font-size: 14px; background: transparent;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' color: #333; padding: 16px 0; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.controls { display: flex; gap: 16px; align-items: center;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' flex-wrap: wrap; margin-bottom: 12px; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.controls label { font-weight: 600; font-size: 13px; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.controls input, .controls select {</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' padding: 6px 10px; border: 1px solid #ccc; border-radius: 4px;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' font-size: 14px; background: #fff; color: #333; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.controls input { width: 140px; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.meta { font-size: 12px; color: #888; margin-bottom: 12px; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.muted { color: #888; font-size: 11px; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'table { width: 100%; border-collapse: collapse; font-size: 13px;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' font-variant-numeric: tabular-nums; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'th { text-align: left; padding: 6px 10px; border-bottom: 2px solid #ddd;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' font-weight: 600; font-size: 12px; text-transform: uppercase;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' letter-spacing: 0.03em; color: #666; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'th.r, td.r { text-align: right; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'td { padding: 5px 10px; border-bottom: 1px solid #eee; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'tr:hover td { background: rgba(0,0,0,0.02); }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.tag { display: inline-block; padding: 1px 6px; border-radius: 3px;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' font-size: 11px; font-weight: 600; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.tag-long { background: #dcfce7; color: #166534; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.tag-call { background: #dbeafe; color: #1e40af; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.tag-put { background: #fee2e2; color: #991b1b; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.summary { margin-top: 12px; font-size: 13px; display: flex;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' gap: 24px; font-weight: 500; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'.summary span { color: #666; font-weight: 400; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'td.cb { width: 24px; text-align: center; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'td.cb input { margin: 0; cursor: pointer; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'tr.excluded td { opacity: 0.35; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'tr.excluded td.cb { opacity: 1; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark { color: #d4d4d4; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .controls input, body.dark .controls select {</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' background: #2a2a2a; color: #d4d4d4; border-color: #555; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark th { color: #999; border-bottom-color: #444; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark td { border-bottom-color: #333; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark tr:hover td { background: rgba(255,255,255,0.03); }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .tag-long { background: #14532d; color: #86efac; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .tag-call { background: #1e3a5f; color: #93c5fd; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .tag-put { background: #450a0a; color: #fca5a5; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .meta { color: #777; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark tr.excluded td { opacity: 0.3; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'body.dark .summary span { color: #888; }</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">JS</span><span class="o">=</span><span class="sa">r</span><span class="s2">"""</span></span></span><span class="line"><span class="cl"><span class="s2">var DATA = {</span></span></span><span class="line"><span class="cl"><span class="s2"> equity_only:</span><span class="si">%s</span><span class="s2">,</span></span></span><span class="line"><span class="cl"><span class="s2"> full:</span><span class="si">%s</span><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">};</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">var excluded =</span><span class="si">{}</span><span class="s2">;</span></span></span><span class="line"><span class="cl"><span class="s2">function posKey(r) { return r.ticker + '_' + r.type; }</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">function syncCutoff() {</span></span></span><span class="line"><span class="cl"><span class="s2"> var cutoff = (parseFloat(document.getElementById('cutoff').value) || 0) / 100;</span></span></span><span class="line"><span class="cl"><span class="s2"> var mode = document.getElementById('mode').value;</span></span></span><span class="line"><span class="cl"><span class="s2"> var rows = DATA[mode];</span></span></span><span class="line"><span class="cl"><span class="s2"> excluded =</span><span class="si">{}</span><span class="s2">;</span></span></span><span class="line"><span class="cl"><span class="s2"> rows.forEach(function(r) {</span></span></span><span class="line"><span class="cl"><span class="s2"> if (r.weight &lt; cutoff) excluded[posKey(r)] = true;</span></span></span><span class="line"><span class="cl"><span class="s2"> });</span></span></span><span class="line"><span class="cl"><span class="s2">}</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">function render() {</span></span></span><span class="line"><span class="cl"><span class="s2"> var bankroll = parseFloat(document.getElementById('bankroll').value) || 0;</span></span></span><span class="line"><span class="cl"><span class="s2"> var mode = document.getElementById('mode').value;</span></span></span><span class="line"><span class="cl"><span class="s2"> var rows = DATA[mode];</span></span></span><span class="line"><span class="cl"><span class="s2"> var showType = mode === 'full';</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> // Show mode description</span></span></span><span class="line"><span class="cl"><span class="s2"> var descEl = document.getElementById('mode-desc');</span></span></span><span class="line"><span class="cl"><span class="s2"> if (mode === 'equity_only') {</span></span></span><span class="line"><span class="cl"><span class="s2"> descEl.textContent = 'Long equity positions only. Options are excluded.';</span></span></span><span class="line"><span class="cl"><span class="s2"> } else {</span></span></span><span class="line"><span class="cl"><span class="s2"> descEl.textContent = 'Uses option rows as underlying notional exposure targets; exact contracts are inferred.';</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> // All rows shown; excluded rows are greyed out</span></span></span><span class="line"><span class="cl"><span class="s2"> var active = rows.filter(function(r) { return !excluded[posKey(r)]; });</span></span></span><span class="line"><span class="cl"><span class="s2"> var totalWeight = active.reduce(function(s, r) { return s + r.weight; }, 0);</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> var allocated = 0;</span></span></span><span class="line"><span class="cl"><span class="s2"> var unsizedTarget = 0;</span></span></span><span class="line"><span class="cl"><span class="s2"> var unknownCostTarget = 0;</span></span></span><span class="line"><span class="cl"><span class="s2"> var computed = rows.map(function(r) {</span></span></span><span class="line"><span class="cl"><span class="s2"> var key = posKey(r);</span></span></span><span class="line"><span class="cl"><span class="s2"> var isExcl = !!excluded[key];</span></span></span><span class="line"><span class="cl"><span class="s2"> var adjWeight = (!isExcl &amp;&amp; totalWeight &gt; 0) ? r.weight / totalWeight : 0;</span></span></span><span class="line"><span class="cl"><span class="s2"> var dollarAlloc = bankroll * adjWeight;</span></span></span><span class="line"><span class="cl"><span class="s2"> var multiplier = r.multiplier || 1;</span></span></span><span class="line"><span class="cl"><span class="s2"> var isOption = r.instrument === 'option';</span></span></span><span class="line"><span class="cl"><span class="s2"> var sizingPrice = isOption ? r.underlying_price : r.price;</span></span></span><span class="line"><span class="cl"><span class="s2"> if (!isExcl &amp;&amp; !sizingPrice) unsizedTarget += dollarAlloc;</span></span></span><span class="line"><span class="cl"><span class="s2"> if (!sizingPrice || isExcl) return { ticker: r.ticker, type: r.type, weight: r.weight,</span></span></span><span class="line"><span class="cl"><span class="s2"> adjWeight: adjWeight, target: dollarAlloc,</span></span></span><span class="line"><span class="cl"><span class="s2"> excluded: isExcl, key: key,</span></span></span><span class="line"><span class="cl"><span class="s2"> instrument: r.instrument || 'stock',</span></span></span><span class="line"><span class="cl"><span class="s2"> strike: r.strike || null, expiry: r.expiry || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> underlyingPrice: r.underlying_price || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> priceAsOf: r.price_as_of || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> price: r.price, units: null, cost: null };</span></span></span><span class="line"><span class="cl"><span class="s2"> var units = Math.floor(dollarAlloc / (sizingPrice * multiplier));</span></span></span><span class="line"><span class="cl"><span class="s2"> var cost = r.price ? units * r.price * multiplier : null;</span></span></span><span class="line"><span class="cl"><span class="s2"> if (cost != null) allocated += cost;</span></span></span><span class="line"><span class="cl"><span class="s2"> if (!isExcl &amp;&amp; isOption &amp;&amp; !r.price &amp;&amp; units &gt; 0) unknownCostTarget += dollarAlloc;</span></span></span><span class="line"><span class="cl"><span class="s2"> return { ticker: r.ticker, type: r.type, weight: r.weight,</span></span></span><span class="line"><span class="cl"><span class="s2"> adjWeight: adjWeight, target: dollarAlloc,</span></span></span><span class="line"><span class="cl"><span class="s2"> excluded: isExcl, key: key, instrument: r.instrument || 'stock',</span></span></span><span class="line"><span class="cl"><span class="s2"> strike: r.strike || null, expiry: r.expiry || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> underlyingPrice: r.underlying_price || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> priceAsOf: r.price_as_of || null,</span></span></span><span class="line"><span class="cl"><span class="s2"> price: r.price, units: units, cost: cost };</span></span></span><span class="line"><span class="cl"><span class="s2"> });</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> var html = '&lt;table&gt;&lt;thead&gt;&lt;tr&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;th&gt;&lt;/th&gt;&lt;th&gt;Ticker&lt;/th&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> if (showType) html += '&lt;th&gt;Type&lt;/th&gt;&lt;th class="r"&gt;Strike&lt;/th&gt;&lt;th class="r"&gt;Expiry&lt;/th&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;th class="r"&gt;Weight&lt;/th&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;th class="r"&gt;Target&lt;/th&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;th class="r"&gt;Price&lt;/th&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;th class="r"&gt;Units&lt;/th&gt;&lt;th class="r"&gt;Cost&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> computed.forEach(function(c) {</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;tr' + (c.excluded ? ' class="excluded"' : '') + '&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="cb"&gt;&lt;input type="checkbox" data-key="' + c.key + '"' + (c.excluded ? '' : ' checked') + '&gt;&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td&gt;&lt;strong&gt;' + c.ticker + '&lt;/strong&gt;&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> if (showType) {</span></span></span><span class="line"><span class="cl"><span class="s2"> var cls = c.type === 'put' ? 'tag-put' : c.type === 'call' ? 'tag-call' : 'tag-long';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td&gt;&lt;span class="tag ' + cls + '"&gt;' + c.type + '&lt;/span&gt;&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> if (c.strike) {</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;$' + c.strike.toFixed(0) + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + (c.expiry || '\u2014') + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> } else {</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;\u2014&lt;/td&gt;&lt;td class="r"&gt;\u2014&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + (c.excluded ? '0.0' : (c.adjWeight * 100).toFixed(1)) + '</span><span class="si">%%</span><span class="s2">&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + (c.excluded ? '$0.00' : '$' + c.target.toFixed(2)) + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> var priceText = c.price != null ? '$' + c.price.toFixed(2) : 'N/A';</span></span></span><span class="line"><span class="cl"><span class="s2"> if (c.instrument === 'option' &amp;&amp; c.priceAsOf) {</span></span></span><span class="line"><span class="cl"><span class="s2"> priceText += '&lt;br&gt;&lt;span class="muted"&gt;' + c.priceAsOf + '&lt;/span&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + priceText + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + (c.units != null ? c.units.toLocaleString() : 'N/A') + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;td class="r"&gt;' + (c.cost != null ? '$' + c.cost.toFixed(2) : 'N/A') + '&lt;/td&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;/tr&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> });</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;/tbody&gt;&lt;/table&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;div class="summary"&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;div&gt;&lt;span&gt;Allocated:&lt;/span&gt; $' + allocated.toFixed(2) + '&lt;/div&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;div&gt;&lt;span&gt;Unknown-cost target:&lt;/span&gt; $' + unknownCostTarget.toFixed(2) + '&lt;/div&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;div&gt;&lt;span&gt;Unsized target:&lt;/span&gt; $' + unsizedTarget.toFixed(2) + '&lt;/div&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;div&gt;&lt;span&gt;Known residual:&lt;/span&gt; $' + (bankroll - allocated - unsizedTarget).toFixed(2) + '&lt;/div&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"> html += '&lt;/div&gt;';</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"> document.getElementById('output').innerHTML = html;</span></span></span><span class="line"><span class="cl"><span class="s2"> // Auto-resize iframe to fit content</span></span></span><span class="line"><span class="cl"><span class="s2"> try {</span></span></span><span class="line"><span class="cl"><span class="s2"> var el = window.frameElement;</span></span></span><span class="line"><span class="cl"><span class="s2"> if (el) el.style.height = document.body.scrollHeight + 'px';</span></span></span><span class="line"><span class="cl"><span class="s2"> } catch(e)</span><span class="si">{}</span><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">}</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">document.getElementById('bankroll').addEventListener('input', render);</span></span></span><span class="line"><span class="cl"><span class="s2">document.getElementById('mode').addEventListener('change', function() { syncCutoff(); render(); });</span></span></span><span class="line"><span class="cl"><span class="s2">document.getElementById('cutoff').addEventListener('input', function() { syncCutoff(); render(); });</span></span></span><span class="line"><span class="cl"><span class="s2">document.getElementById('output').addEventListener('change', function(e) {</span></span></span><span class="line"><span class="cl"><span class="s2"> if (e.target.type === 'checkbox' &amp;&amp; e.target.dataset.key) {</span></span></span><span class="line"><span class="cl"><span class="s2"> if (e.target.checked) {</span></span></span><span class="line"><span class="cl"><span class="s2"> delete excluded[e.target.dataset.key];</span></span></span><span class="line"><span class="cl"><span class="s2"> } else {</span></span></span><span class="line"><span class="cl"><span class="s2"> excluded[e.target.dataset.key] = true;</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2"> render();</span></span></span><span class="line"><span class="cl"><span class="s2"> }</span></span></span><span class="line"><span class="cl"><span class="s2">});</span></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">// Dark mode</span></span></span><span class="line"><span class="cl"><span class="s2">function isDark() {</span></span></span><span class="line"><span class="cl"><span class="s2"> try { return parent.document.documentElement.getAttribute('data-theme') === 'dark'; }</span></span></span><span class="line"><span class="cl"><span class="s2"> catch(e) { return window.matchMedia('(prefers-color-scheme: dark)').matches; }</span></span></span><span class="line"><span class="cl"><span class="s2">}</span></span></span><span class="line"><span class="cl"><span class="s2">function applyTheme() {</span></span></span><span class="line"><span class="cl"><span class="s2"> document.body.classList.toggle('dark', isDark());</span></span></span><span class="line"><span class="cl"><span class="s2">}</span></span></span><span class="line"><span class="cl"><span class="s2">applyTheme();</span></span></span><span class="line"><span class="cl"><span class="s2">try {</span></span></span><span class="line"><span class="cl"><span class="s2"> new MutationObserver(applyTheme).observe(</span></span></span><span class="line"><span class="cl"><span class="s2"> parent.document.documentElement,</span></span></span><span class="line"><span class="cl"><span class="s2"> { attributes: true, attributeFilter: ['data-theme'] });</span></span></span><span class="line"><span class="cl"><span class="s2">} catch(e)</span><span class="si">{}</span><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2"/></span></span><span class="line"><span class="cl"><span class="s2">render();</span></span></span><span class="line"><span class="cl"><span class="s2">"""</span><span class="o">%</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">eq_data</span><span class="p">),</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">full_data</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">BODY</span><span class="o">=</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;div class="controls"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;label for="bankroll"&gt;Bankroll ($)&lt;/label&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;input type="number" id="bankroll" value="10000" min="0" step="100"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;label for="mode"&gt;Mode&lt;/label&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;select id="mode"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;option value="equity_only" selected&gt;Equity only&lt;/option&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;option value="full"&gt;Full exposure&lt;/option&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;/select&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;label for="cutoff"&gt;Cutoff (</span><span class="si">%%</span><span class="s1">)&lt;/label&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">' &lt;input type="number" id="cutoff" value="0" min="0" max="100"'</span></span></span><span class="line"><span class="cl"><span class="s1">' step="0.5" style="width:80px"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;/div&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;div id="mode-desc" class="meta" style="font-style:italic"&gt;&lt;/div&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;div class="meta"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'</span><span class="si">%s</span><span class="s1"> filing (filed</span><span class="si">%s</span><span class="s1">) &amp;middot; underlying prices as of</span><span class="si">%s</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;/div&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;div id="output"&gt;&lt;/div&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">%</span><span class="p">(</span><span class="n">quarter</span><span class="p">,</span><span class="n">filing_date</span><span class="p">,</span><span class="n">today</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">html</span><span class="o">=</span><span class="p">(</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;!DOCTYPE html&gt;</span><span class="se">\n</span><span class="s1">&lt;html&gt;</span><span class="se">\n</span><span class="s1">&lt;head&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;meta charset="utf-8"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;style&gt;</span><span class="se">\n</span><span class="s1">'</span><span class="o">+</span><span class="n">CSS</span><span class="o">+</span><span class="s1">'&lt;/style&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;/head&gt;</span><span class="se">\n</span><span class="s1">&lt;body&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="o">+</span><span class="n">BODY</span></span></span><span class="line"><span class="cl"><span class="o">+</span><span class="s1">'&lt;script&gt;</span><span class="se">\n</span><span class="s1">'</span><span class="o">+</span><span class="n">JS</span><span class="o">+</span><span class="s1">'</span><span class="se">\n</span><span class="s1">&lt;/script&gt;</span><span class="se">\n</span><span class="s1">'</span></span></span><span class="line"><span class="cl"><span class="s1">'&lt;/body&gt;</span><span class="se">\n</span><span class="s1">&lt;/html&gt;'</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="n">outpath</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">HUGO_BASE</span><span class="p">,</span><span class="s1">'static'</span><span class="p">,</span><span class="s1">'images'</span><span class="p">,</span><span class="s1">'sa-lp-calculator.html'</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="k">with</span><span class="nb">open</span><span class="p">(</span><span class="n">outpath</span><span class="p">,</span><span class="s1">'w'</span><span class="p">)</span><span class="k">as</span><span class="n">f</span><span class="p">:</span></span></span><span class="line"><span class="cl"><span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">html</span><span class="p">)</span></span></span></code></pre></div></div></details><iframe src="/images/sa-lp-calculator.html" width="100%" height="580" style="border:none;" scrolling="no"/><p>Based on the five filings to date, the fund files within 0–3 days of the 45-day deadline:</p><table><thead><tr><th>Quarter end</th><th>45-day deadline</th><th>Actual filing</th><th>Days early</th></tr></thead><tbody><tr><td>2024-12-31</td><td>Feb 14</td><td>Feb 12</td><td>2</td></tr><tr><td>2025-03-31</td><td>May 15</td><td>May 14</td><td>1</td></tr><tr><td>2025-06-30</td><td>Aug 14</td><td>Aug 14</td><td>0</td></tr><tr><td>2025-09-30</td><td>Nov 14</td><td>Nov 14</td><td>0</td></tr><tr><td>2025-12-31</td><td>Feb 14</td><td>Feb 11</td><td>3</td></tr></tbody></table><p>So expect new disclosures around<strong>February 14</strong>,<strong>May 15</strong>,<strong>August 14</strong>, and<strong>November 14</strong>. If you decide to implement the copycat strategy, consider setting a calendar reminder. I’ll try to keep this note updated, but please let me know if anything looks outdated.</p><p><em>With thanks to Bastian Stern and Jonas Vollmer for comments.</em></p><div class="footnotes" role="doc-endnotes"><hr><ol><li id="fn:1"><p>See<a href="/notes/situational-awareness-lp/">below</a> for an estimate of the cost of these delays.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li><li id="fn:2"><p>The code still contains utilities for caching representative option contracts, keyed by ticker and option type, because the calculator can use them to estimate contract counts and premium costs. Those estimates are separate from the return table, where the options book is modeled only as underlying directional exposure.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li><li id="fn:3"><p>The single-switch assumption is a simplification: the fund likely makes multiple trades throughout the quarter. But since we only observe quarter-end snapshots, the uniform single-switch model is the most we can extract from the data. There is also a one-time boundary cost—the return of the initial portfolio during the first ~45 days before the copycat sees the first filing—but this is a startup effect, not a recurring feature of the delay, so we omit it from the analysis.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li><li id="fn:4"><p>For the most recent transition, where \(Q_{i+1}\) is not yet available, the gap estimate falls back to the simple comparison of \(Q_i\) vs \(Q_{i-1}\). A more accurate way to model this is to compute the historical returns using this simple comparison and compare them to the returns calculated as we now do, and then adjust the returns from the simple comparison for the most recent transition accordingly. This adjustment will increase the cumulative delay costs a bit, but probably not too much to bother: it only affects ~45/135 ≈ 33% of the days in the last quarter.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li></ol></div>
]]></description></item><item><title>John McTaggart Ellis McTaggart: a bibliography</title><link>https://stafforini.com/notes/john-mctaggart-ellis-mctaggart-a-bibliography/</link><pubDate>Sat, 20 Dec 2014 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/john-mctaggart-ellis-mctaggart-a-bibliography/</guid><description>&lt;![CDATA[<figure><a href="/ox-hugo/john-mctaggart-portrait.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/john-mctaggart-portrait.jpg" alt="John McTaggart Ellis McTaggart"/></figure><blockquote><p>If we compare McTaggart with the other commentators on Hegel we must admit that he has at least produced an extremely lively and fascinating rabbit from the Hegelian hat, whilst they have produced nothing but consumptive and gibbering chimeras. And we shall admire his resource and dexterity all the more when we reflect that the rabbit was, in all probability, never inside the hat, whilst the chimeras perhaps were.</p></blockquote>
C. D. Broad,<a href="/works/broad-1930-dogmas-religion/">Introduction</a>,<em>Some dogmas of religion</em>, London, 1930, pp. xxv–lii, p. xxxi<h2 id="1892">1892</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1892-changes-method-hegel/">The changes of method in Hegel's Dialectic (I)</a>,<em>Mind</em>, vol. 1, no. 1, 1892, pp. 56–71</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1892-changes-method-hegela/">The changes of method in Hegel's Dialectic (II)</a>,<em>Mind</em>, vol. 1, no. 2, 1892, pp. 188–205</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1892-review-thomas-mackay/">Review of Thomas Mackay's<em>A Plea for Liberty</em></a>,<em>International journal of ethics</em>, vol. 2, no. 3, 1892, pp. 391–392</li></ul><h2 id="1893">1893</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1893-further-determination-absolute/"><em>The further determination of the absolute</em></a>, 1893</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1893-time-hegelian-dialectic/">Time and the Hegelian dialectic. (I.)</a>,<em>Mind</em>, vol. 2, no. 8, 1893, pp. 490–504</li></ul><h2 id="1894">1894</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1894-time-hegelian-dialectic/">Time and the hegelian dialectic. (II.)</a>,<em>Mind</em>, vol. 3, no. 10, 1894, pp. 190–207</li></ul><h2 id="1895">1895</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1895-necessity-dogma/">The necessity of dogma</a>,<em>International journal of ethics</em>, vol. 5, no. 2, 1895, pp. 147</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1895-review-wallace-hegel/">Review of W. Wallace, Hegel's philosophy of mind</a>,<em>International journal of ethics</em>, vol. 5, no. 3, 1895, pp. 393–395</li></ul><h2 id="1896">1896</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1896-studies-hegelian-dialectic/"><em>Studies in the Hegelian Dialectic</em></a>, Cambridge, 1896</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1896-hegel-theory-punishment/">Hegel's theory of punishment</a>,<em>The International Journal of Ethics</em>, vol. 6, no. 4, 1896, pp. 479–502</li></ul><h2 id="1897">1897</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1897-review-noel-logique/">Review of G. Noël,<em>La logique de Hegel</em></a>,<em>Mind</em>, vol. 6, no. 4, 1897, pp. 573–576</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1897-hegel-treatment-categories/">Hegel's treatment of the categories of the subjective notion. (I.)</a>,<em>Mind</em>, vol. 6, no. 2, 1897, pp. 164–181</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1897-hegel-treatment-categoriesa/">Hegel's treatment of the categories of the subjective notion. (II.)</a>,<em>Mind</em>, vol. 6, no. 3, 1897, pp. 342–358</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1897-conception-society-organism/">The conception of society as an organism</a>,<em>International Journal of Ethics</em>, vol. 7, no. 4, 1897, pp. 414–434</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1897-review-watson-christianity/">Review of J. Watson, Christianity and idealism</a>,<em>International journal of ethics</em>, vol. 8, no. 1, 1897, pp. 123–124</li></ul><h2 id="1899">1899</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1899-hegel-treatment-categories/">Hegel's treatment of the categories of the objective notion</a>,<em>Hegel's treatment of the categories of the objective notion</em>, vol. 8, no. 1, 1899, pp. 35–62</li></ul><h2 id="1900">1900</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1900-critical-notice-josiah/">Critical notice of Josiah Royce,<em>The World and the Individual</em>. First series</a>,<em>Mind</em>, vol. 9, no. 36, 1900, pp. 258–266</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1900-hegel-treatment-categories/">Hegel's treatment of the categories of the idea</a>,<em>Mind</em>, vol. 9, no. 36, 1900, pp. 145–183</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1900-review-inge-christian/">Review of W. R. Inge,<em>Christian mysticism</em></a>,<em>International journal of ethics</em>, vol. 10, no. 4, 1900, pp. 535–536</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1900-review-wilson-two/">Review of J. M. Wilson,<em>Two sermons on some of the mutual influences of theology and the natural sciences</em></a>,<em>International journal of ethics</em>, vol. 11, no. 1, 1900, pp. 130–132</li></ul><h2 id="1901">1901</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1901-studies-hegelian-cosmology/"><em>Studies in Hegelian Cosmology</em></a>, Cambridge, 1901</li></ul><h2 id="1902">1902</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1902-critical-notice-howison/">Critical notice of G. H. Howison,<em>The limits of evolution and other essays illustrating the metaphysical theory of personal idealism</em></a>,<em>Mind</em>, vol. 11, no. 1, 1902, pp. 383–389</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1902-review-joachim-study/">Review of H. H. Joachim,<em>A study of the ethics of Spinoza</em></a>,<em>International journal of ethics</em>, vol. 12, no. 4, 1902, pp. 517–520</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1902-hegel-treatment-categories/">Hegel's treatment of the categories of quality</a>,<em>Mind</em>, vol. 11, no. 44, 1902, pp. 503–526</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1902-review-josiah-roycea/">Review of Josiah Royce,<em>The World and the Individual</em>. Second series</a>,<em>Mind</em>, vol. 11, no. 1, 1902, pp. 557–563</li></ul><h2 id="1903">1903</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1903-considerations-relating-human/">Some considerations relating to human immortality</a>,<em>The international journal of ethics</em>, vol. 13, no. 2, 1903, pp. 152–171</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1903-review-john-grier/">Review of John Grier Hibben's,<em>Hegel's Logic: An Essay in Interpretation</em></a>,<em>Mind</em>, vol. 12, no. 4, 1903, pp. 550</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1903-review-tennant-origin/">Review of F. R. Tennant,<em>The Origin and Propagation of Sin</em></a>,<em>The International Journal of Ethics</em>, vol. 14, no. 1, 1903, pp. 128–131</li></ul><h2 id="1904">1904</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1904-hegel-treatment-categories/">Hegel's treatment of the categories of quantity</a>,<em>Mind</em>, vol. XIII, no. 1, 1904, pp. 180–203</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1904-review-robert-adamson/">Review of Robert Adamson,<em>The Development of Modern Philosophy</em></a>,<em>International Journal of Ethics</em>, vol. 14, no. 3, 1904, pp. 394–5</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1904-human-preexistence/">Human pre-existence</a>,<em>International journal of ethics</em>, vol. 15, no. 1, 1904, pp. 83–95</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1904-review-aspects-vedanta/">Review of aspects of the Vedanta</a>,<em>International journal of ethics</em>, vol. 15, no. 1, 1904, pp. 124–125</li></ul><h2 id="1906">1906</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1906-dogmas-religion/"><em>Some dogmas of religion</em></a>, London, 1906</li></ul><h2 id="1907">1907</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1907-critical-notice-ormond/">Critical notice of A. T. Ormond,<em>Concepts of philosophy</em></a>,<em>Mind</em>, vol. 16, no. 63, 1907, pp. 431–436</li></ul><h2 id="1908">1908</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1908-critical-notice-william/">Critical notice of William James,<em>Pragmatism, a New Name for Some Old Ways of Thinking: Popular Lectures on Philosophy</em></a>,<em>Mind</em>, vol. 17, no. 1, 1908, pp. 104–109</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1908-individualism-value/">The Individualism of value</a>,<em>International journal of ethics</em>, vol. 18, no. 4, 1908, pp. 433–445</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1908-unreality-time/">The unreality of time</a>,<em>Mind</em>, vol. 17, no. 4, 1908, pp. 457–474</li></ul><h2 id="1909">1909</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1909-relation-time-eternity/">The relation of time and eternity</a>,<em>Mind</em>, vol. 18, no. 3, 1909, pp. 343–362</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1909-review-edward-westermarck/">Review of Edward Westermarck,<em>The Origin and Development of the Moral Ideas</em></a>,<em>The International Journal of Ethics</em>, vol. 20, no. 1, 1909, pp. 94–99</li></ul><h2 id="1910">1910</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1910-commentary-hegel-logic/"><em>A Commentary on Hegel's Logic</em></a>, Cambridge, 1910</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1910-dare-be-wise/"><em>Dare to be wise</em></a>, London, 1910</li></ul><h2 id="1912">1912</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1912-review-bosanquet-principle/">Review of B. Bosanquet,<em>The Principle of Individuality and Value : the Oifford Lectures for 1911</em></a>,<em>Mind</em>, vol. 21, no. 83, 1912, pp. 416–427</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1912-review-georg-lasson/">Review of Georg Lasson (ed.),<em>Grundlinien der Philosophie des Rechts</em> by G. W. F. Hegel</a>,<em>International journal of ethics</em>, vol. 22, no. 4, 1912, pp. 480</li></ul><h2 id="1913">1913</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1913-review-adolf-phalen/">Review of Adolf Phalén,<em>Das Erkenntnis in Hegel's Philosophie</em></a>,<em>Mind</em>, vol. 22, no. 1, 1913, pp. 142–143</li></ul><h2 id="1915">1915</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1915-meaning-causality/">The meaning of causality</a>,<em>Mind</em>, vol. 24, no. 3, 1915, pp. 326–344</li></ul><h2 id="1916">1916</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1916-human-immortality-pre-existence/"><em>Human Immortality and Pre-Existence</em></a>, London, 1916</li></ul><h2 id="1921">1921</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1921-nature-existence/"><em>The nature of existence</em></a>, Cambridge, 1921</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1921-immortality-monadistic-idealism/">Immortality and monadistic idealism</a>,<em>The Monist</em>, vol. 31, no. 2, 1921, pp. 316–317</li></ul><h2 id="1923">1923</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1923-review-seth-pringle-pattison/">Review of A. Seth Pringle-Pattison,<em>The Idea of Immortality</em></a>,<em>Mind</em>, vol. 32, no. 126, 1923, pp. 220–224</li><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1923-propositions-applicable-themselves/">Propositions applicable to themselves</a>,<em>Mind</em>, vol. 32, no. 128, 1923, pp. 462–464</li></ul><h2 id="1925">1925</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1925-review-xavier-leon/">Review of Xavier Léon,<em>Fichte et son temps</em></a>,<em>Mind</em>, vol. 34, no. 133, 1925, pp. 119–120</li></ul><h2 id="1927">1927</h2><ul><li>J. Ellis McTaggart (ed.),<a href="/works/mc-taggart-1927-the-nature-existence/"><em>The nature of existence</em></a>, Cambridge, 1927</li></ul><h2 id="1934">1934</h2><ul><li>J. Ellis McTaggart,<a href="/works/mc-taggart-1934-philosophical-studies/"><em>Philosophical studies</em></a>, London, 1934</li></ul><h2 id="1938">1938</h2><ul><li>S. V. Keeling,<a href="/works/keeling-1938-mc-taggart-nature-existence/">McTaggart's<em>Nature of Existence</em>, vol. I., comments and amendments</a>,<em>Mind</em>, vol. XLVII, no. 188, 1938, pp. 547–550</li></ul>
]]></description></item><item><title>Why does the world exist? — A bibliography</title><link>https://stafforini.com/notes/why-does-the-world-exist-a-bibliography/</link><pubDate>Thu, 27 Feb 2014 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/why-does-the-world-exist-a-bibliography/</guid><description>&lt;![CDATA[<blockquote><p>That anything should exist at all does seem to me a matter for the deepest awe.</p></blockquote><p>J. J. C. Smart</p><blockquote><p>Nicht wie die Welt ist, ist das Mystische, sondern dass sie ist.</p></blockquote><p>Ludwig Wittgenstein</p><p>The most important question of all is also one of the most neglected. The list below includes what are, to the best of my knowledge, the only scholarly writings in the contemporary literature that directly address the question of why the universe exists. (That question includes two sub-questions, &lsquo;Why is there anything at all?&rsquo; and &lsquo;Why does this particular world exist, rather than some other&rsquo;, which we may call the &ldquo;general&rdquo; and the &ldquo;special&rdquo; ultimate questions of existence, respectively.) Note that this excludes non-scholarly writings (such as Jim Holt&rsquo;s<em>Why does the world exist?</em>); writings that address the question indirectly (such as those found in certain areas within physical cosmology and the philosophy of religion); and writings too removed from the present (published before, say, 1850, such as Leibniz&rsquo;s<em>De rerum originatione radicali</em>). My personal recommendations are<strong>boldfaced</strong>.</p><p>If you think I&rsquo;m missing something, please let me know.</p><ul><li>Leslie Armour,<a href="/works/armour-1987-values-god-problem/">Values, God, and the problem about why there is anything at all</a>,<em>Journal of speculative philosophy</em>, vol. 1, no. 2, 1987, pp. 147–162</li><li>Simon Blackburn,<a href="/works/blackburn-2009-philosophy/"><em>Philosophy</em></a>, London, 2009, pp. 132–141</li><li>David Brooks,<a href="/works/brooks-1992-why-this-world/">Why this world?</a>,<em>Philosophical Papers</em>, vol. 21, no. 3, 1992, pp. 259–273</li><li>Michael B. Burke,<a href="/works/burke-1984-hume-edwards-why/">Hume and Edwards on ‘why is there something rather than nothing?’</a>,<em>Australasian Journal of Philosophy</em>, vol. 62, no. 4, 1984, pp. 355–362</li><li>Erik Carlson and Erik J. Olsson,<a href="/works/carlson-2001-presumption-nothingness/">The presumption of nothingness</a>,<em>Ratio</em>, vol. 14, no. 3, 2001, pp. 203–221</li><li>Sean Carroll,<a href="/works/carroll-2018-why-there-something/">Why is there something, rather than nothing?</a>,<em>ArXiv</em>, February 6, 2018</li><li>Earl Conee and Theodore Sider,<a href="/works/conee-2005-riddles-existence/"><em>Riddles of Existence</em></a>, Oxford, 2005, ch. 5</li><li>Brian Davies,<a href="/works/davies-2003-why-there-anything/">Why is there anything at all?</a>,<em>Think</em>, vol. 2, no. 4, 2003, pp. 7–15</li><li>Paul Edwards,<a href="/works/edwards-1967-why/">Why?</a>, in Paul Edwards (ed.)<em>The Encyclopedia of Philosophy</em>, New York, 1967, pp. 296–302</li><li>Noel Fleming,<a href="/works/fleming-1988-why-there-something/">Why is there something rather than nothing?</a>,<em>Analysis</em>, vol. 48, no. 1, 1988, pp. 32–35</li><li>Tyron Goldschmidt (ed.),<a href="/works/goldschmidt-2013-puzzle-existence-why/"><em>The puzzle of existence: Why is there something rather than nothing?</em></a>, New York, 2013</li><li>D. Goldstick,<a href="/works/goldstick-1979-why-there-something/">Why is there something rather than nothing?</a>,<em>Philosophy and Phenomenological Research</em>, vol. 40, no. 2, 1979, pp. 265</li><li><strong>Stephen Grover,<a href="/works/grover-1998-cosmological-fecundity/">Cosmological fecundity</a>,<em>Inquiry</em>, vol. 41, no. 3, 1998, pp. 277–299</strong></li><li>Adolf Grünbaum,<a href="/works/grunbaum-1993-creation-cosmology/">Creation in cosmology</a>, in N. S. Hetherington (ed.)<em>Encyclopedia of cosmology: historical, philosophical, and scientific foundations of modern cosmology</em>, New York, 1993, pp. 126–136</li><li>Adolf Grünbaum,<a href="/works/grunbaum-2009-why-there-world/">Why is there a world at all rather than just nothing?</a>,<em>Ontology Studies</em>, vol. 9, 2009, pp. 7–19</li><li>Michał Heller,<a href="/works/heller-2009-ultimate-explanations-universe/"><em>Ultimate explanations of the universe</em></a>, Heidelberg, 2009</li><li>Jan Heylen,<a href="/works/heylen-2017-why-there-something/">Why is there something rather than nothing? A logical investigation</a>,<em>Erkenntnis</em>, vol. 82, no. 3, 2017, pp. 531–559</li><li>Thomas S. Knight,<a href="/works/knight-1956-why-not-nothing/">Why not nothing?</a>,<em>The Review of Metaphysics</em>, vol. 10, no. 1, 1956, pp. 158–164</li><li>Robert Lawrence Kuhn,<a href="/works/kuhn-2007-why-this-universe/">Why this universe? Toward a taxonomy of possible explanations</a>,<em>Skeptic</em>, vol. 13, no. 2, 2007, pp. 28–39</li><li>Robert Lawrence Kuhn,<a href="/works/kuhn-2007-closer-truth-science/"><em>Closer to truth: Science, meaning, and the future</em></a>, London, 2007, pp. 235–258</li><li>Robert Lawrence Kuhn,<a href="/works/kuhn-2013-why-not-nothing/">Why not nothing?</a>, in John Leslie and Robert Lawrence Kuhn (eds.)<em>The mystery of existence: why is there anything at all?</em>, Chichester, West Sussex, 2013, pp. 246–278</li><li>Martin Kusch,<a href="/works/kusch-1990-why-there-something/">On "Why is there something rather than nothing?"</a>,<em>American Philosophical Quarterly</em>, vol. 27, no. 3, 1990, pp. 253–257</li><li>William James,<a href="/works/james-1911-problem-being/">The problem of being</a>, in William James (ed.)<em>Some problems of philosophy</em>, London, 1911, pp. 38–46</li><li>John Leslie,<a href="/works/leslie-1978-efforts-explain-all/">Efforts to explain all existence</a>,<em>Mind</em>, vol. 87, no. 2, 1978, pp. 181–194</li><li>John Leslie,<a href="/works/leslie-1979-value-existence/"><em>Value and existence</em></a>, Totowa, 1979</li><li>John Leslie,<a href="/works/leslie-2005-review-bede-rundle/">Review of Bede Rundle, Why There Is Something Rather Than Nothing</a>,<em>Mind</em>, vol. 114, no. 453, 2005, pp. 197–200</li><li>John Leslie,<a href="/works/leslie-2009-why-there-something/">Why there is something</a>, in Jaegwon Kim, Ernest Sosa, and Gary S. Rosenkranz (eds.)<em>A companion to metaphysics</em>, Malden, MA, 2009, pp. 625</li><li>John Leslie,<a href="/works/leslie-2009-cosmos-existing-ethical/">A cosmos existing through ethical necessity</a>,<em>Philo</em>, vol. 12, no. 2, 2009, pp. 172–187</li><li>John Leslie and Robert Lawrence Kuhn (eds.),<a href="/works/leslie-2013-mystery-existence-why/"><em>The mystery of existence: why is there anything at all?</em></a>, Chichester, West Sussex, 2013</li><li>E. J. Lowe,<a href="/works/lowe-1996-why-there-anything/">Why is there anything at all?</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 70, no. 1, 1996, pp. 111–120</li><li>Stephen Maitzen,<a href="/works/maitzen-2012-stop-asking-why/">Stop asking why there’s anything</a>,<em>Erkenntnis</em>, vol. 77, no. 1, 2012, pp. 51–63</li><li>Robert B Mann,<a href="/works/mann-2009-puzzle-existence/">The puzzle of existence</a>,<em>Perspectives on Science and Christian Faith</em>, vol. 61, no. 3, 2009, pp. 139 – 151</li><li>Tim Mawson,<a href="/works/mawson-2009-why-there-anything/">Why is there anything at all?</a>, in Yujin Nagasawa and Erik J. Wielenberg (eds.)<em>New waves in philosophy of religion</em>, New York, 2009, pp. 36–54</li><li>Chris Mortensen,<a href="/works/mortensen-1986-explaining-existence/">Explaining existence</a>,<em>Canadian journal of philosophy</em>, vol. 16, no. 4, 1986, pp. 713–22</li><li>Milton K. Munitz,<a href="/works/munitz-1965-mystery-existence-essay/"><em>The mystery of existence: an essay in philosophical cosmology</em></a>, New York, 1965</li><li>Thomas Nagel,<a href="/works/nagel-2010-why-there-anything/">Why is there anything?</a>, in Thomas Nagel (ed.)<em>Secular Philosophy and the Religious Temperament: Essays 2002-2008</em>, New York, 2010, pp. 27–31</li><li>Yew-Kwang Ng,<a href="/works/ng-2019-evolved-god-creationism-view/"><em>Evolved-God creationism: a view of how God evolved in the wider universe</em></a>, 2019</li><li><strong>Robert Nozick,<a href="/works/nozick-1981-why-there-something/">Why is there something rather than nothing?</a>, in Robert Nozick (ed.)<em>Philosophical explanations</em>, Cambridge, MA, 1981, pp. 115–164</strong></li><li>Derek Parfit,<a href="/works/parfit-1991-why-does-universe/">Why does the universe exist?</a>,<em>Harvard review of philosophy</em>, vol. 1, no. 1, 1991, pp. 2–5</li><li>Derek Parfit,<a href="/works/parfit-1992-puzzle-reality-why/">The puzzle of reality: Why does the universe exist?</a>,<em>Times literary supplement</em>, 1992, pp. 3–5</li><li><strong>Derek Parfit,<a href="/works/parfit-1998-why-anything-why/">Why anything? Why this?</a>,<em>London Review of Books</em>, vol. 20, no. 2, 1998, pp. 24–27, Derek Parfit,<a href="/works/parfit-1998-why-anything-why-2/">Why anything? Why this?</a>,<em>London Review of Books</em>, vol. 20, no. 3, 1998, pp. 22–25</strong></li><li>John F. Post,<a href="/works/post-1991-why-does-anything/">Why does anything at all exist?</a>, in Richard Taylor (ed.)<em>Metaphysics : a contemporary introduction</em>, New York, 1991, pp. chap. 4</li><li>Nicholas Rescher,<a href="/works/rescher-1984-riddle-existence-essay/"><em>The riddle of existence: an essay in idealistic metaphysics</em></a>, Lanham, MD, 1984</li><li>Nicholas Rescher,<a href="/works/rescher-2000-optimalism-axiological-metaphysics/">Optimalism and axiological metaphysics</a>,<em>Review of metaphysics</em>, vol. 53, no. 4, 2000, pp. 807–835</li><li>Bede Rundle,<a href="/works/rundle-2004-why-there-something/"><em>Why there is something rather than nothing</em></a>, Oxford, 2004</li><li>Husain Sarkar and Southwestern Philosophical Society,<a href="/works/sarkar-1993-something-nothing-explanation/">Something, nothing and explanation</a>,<em>Southwest Philosophy Review</em>, vol. 9, no. 1, 1993, pp. 151–161</li><li>George Schlesinger,<a href="/works/schlesinger-1998-enigma-existence/">The enigma of existence</a>,<em>Ratio</em>, vol. 11, no. 1, 1998, pp. 66–77</li><li>Daniel Schuppe, Jens Lemanski, and Rico Hauswald (eds.),<a href="/works/schuppe-2013-warum-uberhaupt-etwas/"><em>Warum ist überhaupt etwas und nicht vielmehr nichts?: Wandel und Variationen einer Frage</em></a>, Hamburg, 2013</li><li>Quentin Smith,<a href="/works/smith-1997-simplicity-why-universe/">Simplicity and why the universe exists</a>,<em>Philosophy</em>, vol. 72, no. 279, 1997, pp. 125–132</li><li>Quentin Smith,<a href="/works/smith-1999-reason-universe-exists/">The reason the universe exists is that it caused itself to exist</a>,<em>Philosophy</em>, vol. 74, no. 4, 1999, pp. 579–586</li><li>Peter Unger,<a href="/works/unger-1984-minimizing-arbitrariness-metaphysics/">Minimizing arbitrariness: Toward a metaphysics of infinitely many isolated concrete worlds</a>,<em>Midwest Studies in Philosophy</em>, vol. 9, no. 1, 1984, pp. 29–51</li><li>Peter van Inwagen,<a href="/works/van-inwagen-1996-why-there-anything/">Why is there anything at all?</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 70, no. 1, 1996, pp. 95–110</li><li>John F. Wippel (ed.),<a href="/works/wippel-2011-ultimate-why-question/"><em>The ultimate why question: Why is there anything at all rather than nothing whatsoever?</em></a>, Washington, 2011</li><li>Arthur Witherall,<a href="/works/witherall-2001-fundamental-question/">The fundamental question</a>,<em>Journal of Philosophical Research</em>, vol. 26, 2001, pp. 53–87</li><li>Arthur Witherall,<a href="/works/witherall-2002-problem-existence/"><em>The problem of existence</em></a>, Aldershot, 2002</li></ul><p><em>In memoriam, Quentin Smith (1952-2020)</em></p><figure><a href="/ox-hugo/quentin-smith-portrait.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/quentin-smith-portrait.jpg" alt="Quentin Smith"/></figure>
]]></description></item><item><title>My 1996 Winnebago Rialta is for sale</title><link>https://stafforini.com/notes/my-1996-winnebago-rialta-is-for-sale/</link><pubDate>Wed, 14 Mar 2018 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/my-1996-winnebago-rialta-is-for-sale/</guid><description>&lt;![CDATA[<figure><a href="/ox-hugo/rialta-featured.jpeg" target="_blank" rel="noopener"><img src="/ox-hugo/rialta-featured.jpeg" alt="1996 Winnebago Rialta parked on a residential street"/></figure><p><strong><em>Note: The Rialta is now sold.</em></strong></p><p>My 1996 Winnebago Rialta is for sale. This is the famous RV that, until last year, belonged to Tynan, author of the classic <em>The Tiniest Mansion: How To Live In Luxury on the Side of the Road in an RV</em>. Although I would love to keep it, I currently live in the UK and transporting the vehicle to Europe is a major logistical, financial, and bureaucratic hassle.</p><p>I only drove the Rialta 500 miles since buying it from the previous owner, and nothing has changed relative to the state it was when I purchased it, except that the following improvements worth $4,000 have been made: new tires, including the spare, getting new spark plugs, tuning it up, and changing the fluids. I&rsquo;m selling it for the same price I bought it for, which is a good deal given that it now has these mechanical things fixed up.</p><p>What follows is Tynan&rsquo;s<a href="http://tynan.com/rialta">original announcement</a>, which provides a comprehensive description of all the tweaks Tynan made to the vehicle over the years. If you have any questions, feel free to<a href="/notes/contact/">get in touch</a>.</p><p><a href="//www.youtube.com/embed/BjiQFCunJqk?rel=0;vq=hd720;rel=0;showinfo=0;modestbranding=1;autohide=1&amp;controls=0">Youtube video</a></p><p>If you&rsquo;ve been thinking about the RV lifestyle and want to live in the RV that started the Rialta craze, here&rsquo;s your chance. Or if you just want a cool RV or a pied-a-terre in San Francisco, this could be for you.</p><p>Also included is a parking spot in San Francisco, if you want it. It&rsquo;s probably the only good RV spot in San Francisco and includes water and electricity. I also have a waste-dumping system that allows you to dump your waste without moving the RV from the parking spot. You&rsquo;ll have to negotiate the rate with the owner of the spot (a friend of mine), but he offered that if someone pays my asking price they can have the spot at an artificially low rate of $550/mo. He&rsquo;s a really nice guy. Location is in a prime area of the Castro with easy subway connection to downtown in 5 minutes. Nearby studios rent for $3500+, so the RV pays for itself in less than a year.</p><p>The RV itself is a 1996 Rialta Winnebago. This is the best RV to live in because it&rsquo;s much wider than Sprinter vans and similar. Mine has the rare floorplan that has a full-sized bed, which makes it very comfortable.</p><p>The RV itself has around 85k miles. I&rsquo;m not in San Francisco so I can&rsquo;t check currently. I replaced the top half of the engine as well as the transmission, which cost me around $12k total.</p><p>I&rsquo;ve done a tremendous amount of work to the RV, all without regard to price or effort to install. Below is a nearly-complete list of the features, though I&rsquo;m sure I&rsquo;ve forgotten some stuff.</p><h2 id="design">Design</h2><p>I installed maple floors in the main area, and black and white marble mosaic in the entryway. The ceiling is a real metal tin ceiling in gold tone. The curved transition area between the wall and ceiling is real 20k gold leaf, which is lit by LEDs hidden in the molding. Custom curtains were made from antique kimono fabric from Japan. Some of the windows are covered in mulberry shoji paper, but some have small tears now. Easy to remove or fix.</p><p>Windows on the driver&rsquo;s side of the RV are day-night shades custom made to size, with magnets to keep them in place.</p><p>I bought tatami mats and sized them to fit the bed platform so that I can roll it up and have a tea room. I now build tea rooms everywhere (Vegas, building island this summer), and you can own the first one I built.</p><p>The countertops were custom fabricated from high end Brazilian granite. A deep sink with new faucet was put in. The cabinet handles were replaced with brass and all cabinets were painted.</p><p>The desk is a custom made tigerwood desk with a low-profile drawer. Under it is a 100 year old persian rug which I will include if you want it, but would like to keep if you don&rsquo;t really care.</p><p>The closet was converted into a cedar closet, as was one of the drawers.</p><h2 id="lighting">Lighting</h2><p>You get a fully automated light system that I coded, which also controls stereo and fan. The interface is basic, but it has powerful capabilities which you could expand). It runs off of a raspberry pi and GC100 IR/relay controller. I&rsquo;ve installed LED strips just about everywhere in two different zones that can be independently controlled. I made two little art lights to shine an LED spot on the wall where I hung art. The desk lamp is also controllable. My software allows you to white balance lights, create scenes, fade over time, etc.</p><p>There&rsquo;s also a backup set of lights that you can control just by pushing buttons.</p><h2 id="av-equipment">AV Equipment</h2><p>The head unit for the stereo is a Clarion with a flip out screen. It has full navigation with lane changing, is satellite ready, has an installed backup camera, etc. It&rsquo;s paired with an Alpine amplifier and upgraded speakers. I also built a custom subwoofer enclosure into the bed which has a JL 12" subwoofer. This system sounds amazing.</p><p>Mounted overhead is a small projector which projects onto an easy-to-deploy screen in the middle of the RV. You can turn the captains chairs around and watch like it&rsquo;s a movie theater, or you can flip the image and watch from bed. The power switch is mounted in the wall.</p><p>Over the desk is a 27" TV that I use as a second monitor. An HDMI switch allows you to output your laptop to either the TV or the projector. The 27" TV is on an extendable arm mounted to the metal frame of the RV so that it can be fully extended.</p><h2 id="kitchen">Kitchen</h2><p>The fridge is a Dometic DC fridge which runs off batteries and uses an average of 10W throughout the day. It even has a freezer that&rsquo;s cold enough to make ice. The range is a household two-burner gas range. I forget the brand, but it&rsquo;s a high-end unit meant for real cooking and has far higher output than most RV stoves.</p><p>Above the range are a bunch of magnetic spice boxes that adhere to the curved tin ceiling that comes down to the wall.</p><p>The sink is deep and includes a pullout faucet. It also has a cutting board that fits into it. Beside the regular sink is a second tap for filtered water which goes through a large three stage filter.</p><h2 id="power">Power</h2><p>On the roof are two 200W solar panels with low profile mounts. The solar controller is a Blue Sky 3024i MPPT controller with a monitoring panel and a shunt for measuring the power. The inverter and battery charger is a Xantrex Prosine 2.0. I custom wired everything so that you can use all of the outlets on either the inverter or shore power. This system is ridiculous overkill that would be more appropriate for a cabin than an RV.</p><p>The batteries are both dead and should be replaced. You could go really cheap if you don&rsquo;t plan on being off-grid, or you could get lithium ion batteries that would last a week without sun.</p><p>There&rsquo;s also a SeeLevel monitor which shows battery charge, LP gas levels, and fresh water levels down to the exact percentage.</p><h2 id="climate-control">Climate Control</h2><p>The RV comes with an Olympian Wave 6 propane heater with auto shutoff. This feels like a fireplace and gets really hot if you put it on high. It has a flexible house and a quick-detach mount point in the kitchen.</p><p>Also installed is a 400W ceramic panel. Unless you get lithium ion batteries, you should run this only when you&rsquo;re plugged in. It&rsquo;s silent and located under the desk so you can be toasty while you work.</p><p>In the ceiling is a MaxxAir vent fan with variable speed control and reversible direction. It can be controlled by remote with thermostat or by my system. For some reason it&rsquo;s very hard to close now, so I just leave it open all the time.</p><p>I think that the AC in the car part of the RV might not work. I haven&rsquo;t used it in a long time so I don&rsquo;t remember.</p><h2 id="bathroom">Bathroom</h2><p>I replaced the old plastic toilet with a porcelain RV toilet with wooden seat and cover. It was virtually impossible to find one that would fit. The shower was modified to eject water outside (it used to go into the gray tank which would fill very quickly). The showerhead was replaced with a high-pressure low-flow oxygenics head.</p><p>Also included is a propane water heater that I never installed. The built in one uses electricity.</p><h2 id="miscellaneous">Miscellaneous</h2><p>The skylight was recently replaced with a brand new one, but it doesn&rsquo;t have trim around it.</p><p>There&rsquo;s a viper alarm with window break sensors and extra remotes. A friend tried to test it for me and said it didn&rsquo;t do anything, which I believe is because the remote batteries are dead.</p><p>I replaced the RV door with a brand new one with deadbolt and extra key.</p><p>Installed is a wireless router that can pull in other wifi signals and rebroadcast them within the RV.</p><p>I&rsquo;m sure I&rsquo;ve forgotten a lot of things about the RV as well as things that I&rsquo;m throwing in because I bought them for the RV. Maybe there will be some cool surprises for you.</p><h2 id="registration-smog">Registration + Smog</h2><p>The RV is owned by a Wyoming Corporation and registered in South Dakota. I am actually selling you the Wyoming Corporation, not the RV. The practical implication of this is that you don&rsquo;t have to pay transfer tax since the owner of the RV is staying the same. South Dakota is the most common place to register RVs because you never have to get them smogged or inspected, and annual registration is low.</p><h2 id="the-issues">The Issues</h2><p><em>Please note that most of these issues have been fixed since Tynan wrote the original post. As mentioned above, the following improvements have been made: &ldquo;new tires, including the spare, getting new spark plugs, tuning it up, and changing the fluids."—Pablo</em></p><p>I basically never drive the RV anymore because I have such a good parking space. I move it around a bit to dump the tanks and it always runs just fine. A year or so ago I drove across San Francisco to fill up the propane. But even though I don&rsquo;t know about any issues, it hasn&rsquo;t been seriously driven in years so I&rsquo;d personally get it tuned up before any long trips.</p><p>The drawers are a little busted. I have a repair kit but haven&rsquo;t gotten around to installing it. The driver&rsquo;s side door doesn&rsquo;t open from the outside for some reason.</p><p>The RV is pretty dirty on the outside, but clean on the inside.</p><p>I did a lot of the work myself and while I&rsquo;m competent, I&rsquo;m not a finish carpenter. So maybe just decrease expectations for fit and finish by 10% and be pleasantly surprised in some cases.</p><div class="gallery"><a href="/images/rialta/1.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/1.jpeg" alt="1.jpeg" loading="lazy"/><a href="/images/rialta/11.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/11.jpeg" alt="11.jpeg" loading="lazy"/><a href="/images/rialta/12.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/12.jpeg" alt="12.jpeg" loading="lazy"/><a href="/images/rialta/13.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/13.jpeg" alt="13.jpeg" loading="lazy"/><a href="/images/rialta/14.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/14.jpeg" alt="14.jpeg" loading="lazy"/><a href="/images/rialta/16.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/16.jpeg" alt="16.jpeg" loading="lazy"/><a href="/images/rialta/17.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/17.jpeg" alt="17.jpeg" loading="lazy"/><a href="/images/rialta/2.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/2.jpeg" alt="2.jpeg" loading="lazy"/><a href="/images/rialta/20180909_125132.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/20180909_125132.jpg" alt="20180909_125132.jpg" loading="lazy"/><a href="/images/rialta/20180909_125156.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/20180909_125156.jpg" alt="20180909_125156.jpg" loading="lazy"/><a href="/images/rialta/20180909_125210.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/20180909_125210.jpg" alt="20180909_125210.jpg" loading="lazy"/><a href="/images/rialta/20180909_125222.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/20180909_125222.jpg" alt="20180909_125222.jpg" loading="lazy"/><a href="/images/rialta/20180909_125243.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/20180909_125243.jpg" alt="20180909_125243.jpg" loading="lazy"/><a href="/images/rialta/3.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/3.jpeg" alt="3.jpeg" loading="lazy"/><a href="/images/rialta/4.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/4.jpeg" alt="4.jpeg" loading="lazy"/><a href="/images/rialta/6.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/6.jpeg" alt="6.jpeg" loading="lazy"/><a href="/images/rialta/7.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/7.jpeg" alt="7.jpeg" loading="lazy"/><a href="/images/rialta/8.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/8.jpeg" alt="8.jpeg" loading="lazy"/><a href="/images/rialta/9.jpeg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/9.jpeg" alt="9.jpeg" loading="lazy"/><a href="/images/rialta/Tynan-Ceiling-and-Gold-Leaf.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/Tynan-Ceiling-and-Gold-Leaf.jpg" alt="Tynan-Ceiling-and-Gold-Leaf.jpg" loading="lazy"/><a href="/images/rialta/Tynan-Galley.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/Tynan-Galley.jpg" alt="Tynan-Galley.jpg" loading="lazy"/><a href="/images/rialta/Tynan-Office.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/Tynan-Office.jpg" alt="Tynan-Office.jpg" loading="lazy"/><a href="/images/rialta/Tynan-hardwood-floor.jpg" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/Tynan-hardwood-floor.jpg" alt="Tynan-hardwood-floor.jpg" loading="lazy"/><a href="/images/rialta/floor_plan_22fd_double.gif" class="gallery-item" target="_blank" rel="noopener"><img src="/images/rialta/floor_plan_22fd_double.gif" alt="floor_plan_22fd_double.gif" loading="lazy"/></div><h2 id="more-info">More info</h2><ul><li><a href="/ox-hugo/1996_rialta_specs.pdf">Specs</a></li><li><a href="/ox-hugo/1996Rialta.pdf">Brochure</a></li><li><a href="/ox-hugo/floor_plan_22fd_double.gif">Floor plan</a></li></ul><h2 id="sources">Sources</h2><ul><li><a href="https://www.sfgate.com/bayarea/article/These-young-SF-professionals-choose-to-live-in-RVs-4778625.php">These young SF professionals choose to live in RVs</a>, <em>SFGate</em></li><li><a href="https://winnebagolife.com/2014/05/the-gambler-pick-up-artist-blogger-and-rialta">The gambler, pick-up artist, blogger and Rialta</a>,<em>WinnebagoLife</em></li></ul>
]]></description></item><item><title>Minimizing jet lag</title><link>https://stafforini.com/notes/minimizing-jet-lag/</link><pubDate>Sun, 25 Mar 2018 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/minimizing-jet-lag/</guid><description>&lt;![CDATA[<p>This post lists what I believe are the most effective strategies to reduce the impact of jet lag. It evolved out of a document I wrote for a friend who sought my advice. A few of these tips are copied from Wiseman (2014); most of the other ones are based on a couple of hours of research using Google and Google Scholar.</p><h2 id="booking-your-flight">Booking your flight</h2><ul><li><em>Timing.</em> Choose the time of the flight by following the simple adage,<em>Fly east, fly early. Fly west, fly late.</em></li><li><em>Seating.</em> If you need to sleep during the trip, (1) pick a window seat to avoid being disturbed by other passengers and (2) do not pick a a seat on the sunny side of the plane.<ul><li>For flights in the northern hemisphere, the sun will tend to be on the left side of the plane when you fly west, and on the right side when you go east. Check<a href="https://www.seatguru.com">SeatGuru</a> for more info.</li></ul></li><li><em>Airline.</em> Ideally, book your flight with<a href="http://www.flightstats.com/company/monthly-performance-reports/airlines/">an airline that is rarely delayed</a>.<ul><li>The most important consideration is the frequency of<em>long</em> delays (+2 hours) and cancellations, since these are the most disruptive. I couldn&rsquo;t find statistics for these outside the US, but Silver (2015) notes that overall delay times generally correlate well with both long delay and cancellation frequency, so we can rely on this measure as an adequate proxy.</li></ul></li><li><em>Aircraft.</em> Ideally, book your flight on a Dreamliner.</li></ul><h2 id="before-you-fly">Before you fly</h2><ul><li>Insofar as you can, gradually shift your body clock to match your destination&rsquo;s, by going to bed one hour earlier or later each day, and shifting your wakeup time correspondingly.<ul><li>Calculate the time you should go to bed on each of the relevant days preceding your flight. For example, if the time at your destination is five hours later, you should go to bed one hour earlier five days before your departure, two hours earlier four days before, and so on.</li><li>For each of these days, set an alarm on your phone to ring ~2 hours prior to bedtime. When the alarm rings, start wearing<a href="https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&amp;field-keywords=orange+tinted+glasses&amp;x=0&amp;y=0">orange-tinted glasses</a>, take melatonin, and resolve to go to bed ~2 hours later. (If you have a bedtime routine, shift this routine accordingly.)</li><li>Expose yourself to lots of light soon after waking up, by either going outdoors or using a<a href="https://www.amazon.com/gp/bestsellers/hpc/13053141/ref=zg_b_bs_13053141_1">blue-light lamp</a>.</li></ul></li><li>The site<a href="http://www.jetlagrooster.com/">Jet Lag Rooster</a> can help implement this advice.</li></ul><h2 id="during-your-flight">During your flight</h2><ul><li>As soon as you board the plane, adjust your watch to show the time at your destination, and try to fit into this new time schedule as soon as possible. If it is time to sleep, get your head down. If it is dinner time, eat something. Etc.</li><li>Drink plenty of water, and drink often.</li><li>When it&rsquo;s time to sleep, wear an<a href="https://www.amazon.com/OOSilk-19mm-Mulberry-Sleep-Black/dp/B010UCY3S2/ref=lp_12025177011_1_1?srs=12025177011&amp;ie=UTF8&amp;qid=1483885819&amp;sr=8-1">eye mask</a> and<a href="https://www.amazon.com/gp/product/B0007XJOLG">earplugs</a>, and take melatonin.</li><li>If you still have trouble sleeping, consider taking<a href="https://en.wikipedia.org/wiki/Zolpidem">zolpidem</a>,<a href="https://en.wikipedia.org/wiki/Zaleplon">zaleplon</a> or<a href="https://en.wikipedia.org/wiki/Temazepam">temazepam</a> (the three main sleep aids used in military aviation).</li></ul><h2 id="after-you-fly">After you fly</h2><ul><li>When you arrive at your destination, continue exposing yourself to light in the morning, and limiting exposure to (blue) light in the evening.</li><li>Above all,<em>don&rsquo;t nap</em>. If you have trouble staying awake during the day, consider taking modafinil or<a href="https://en.wikipedia.org/wiki/Dextroamphetamine">dextroamphetamine</a> (the two main stimulants used in military aviation).</li></ul><p>Note that, unless you are permanently moving to a new location, you should follow some of the steps above<em>twice</em>: first when visiting your destination, and a second time when returning home.</p><h2 id="bibliography">Bibliography</h2><ul><li>Rocky Jedick,<a href="/works/jedick-2020-stimulants-sleep-aids/">Stimulants & Sleep Aids in Military Aviation</a>,<em>Go Flight Med</em>, November 12, 2020</li><li>Nate Silver,<a href="/works/silver-2015-better-way-to/">A Better Way To Find The Best Flights And Avoid The Worst Airports</a>,<em>FiveThirtyEight</em>, March 11, 2015</li><li>Richard Wiseman,<a href="/works/wiseman-2014-night-school-hidden/"><em>Night School: The Hidden Science of Sleep and Dreams</em></a>, 2014</li></ul>
]]></description></item><item><title>My Emacs config</title><link>https://stafforini.com/notes/my-emacs-config/</link><pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/my-emacs-config/</guid><description>&lt;![CDATA[<p>I am not a programmer, let alone an Elisp hacker. My background is in the humanities. It is only a slight exaggeration to say that, before I started using Emacs in 2020, I didn&rsquo;t know the difference between a function and a variable. You have been forewarned.</p><p>This configuration is an Org document that tangles to an Emacs Lisp init file. It is organized into thematic sections—package management, version control, display, text manipulation, and so on—each of which groups related package declarations together. In addition to built-in features and external packages, it loads dozens of “extras” files: personal Elisp libraries stored in the<code>emacs/extras/</code> directory and named after the package they extend (e.g.,<code>org-extras</code>,<code>elfeed-extras</code>,<code>gptel-extras</code>). These files are loaded via the<code>use-personal-package</code> macro, a thin wrapper around<code>use-package</code> that fetches the corresponding file from this dotfiles repository. Such a setup allows me to extend the functionality of various packages and features without cluttering the main configuration section. For example, instead of piling dozens of custom<code>org-mode</code> functions into the<code>org</code> section of this file, I place them in<code>emacs/extras/org-extras.el</code> and load that file with a single<code>(use-personal-package org-extras)</code> declaration here. This structure also allows anyone to try out my configuration selectively and straightforwardly. Thus, if you’d like to install my<code>org</code> extensions, you can just add one of the following recipes to your own config (depending on which package manager or Emacs version you use):</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="c1">;; with elpaca</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"benthamite/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/extras/org-extras.el"</span></span></span><span class="line"><span class="cl"><span class="s">"emacs/extras/doc/org-extras.texi"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; with straight</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:straight</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"benthamite/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/extras/org-extras.el"</span></span></span><span class="line"><span class="cl"><span class="s">"emacs/extras/doc/org-extras.texi"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; with vc (requires Emacs 30.1 or higher; no Info manual)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:vc</span><span class="p">(</span><span class="nb">:url</span><span class="s">"https://github.com/benthamite/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:lisp-dir</span><span class="s">"emacs/extras"</span></span></span><span class="line"><span class="cl"><span class="nb">:rev</span><span class="nb">:newest</span><span class="p">))</span></span></span></code></pre></div><p>The extras come with their own manuals and user options: everything is documented and customizable. When installed via elpaca or straight, each package&rsquo;s Info manual is built and registered automatically. To read a manual, type<code>M-x info-display-manual RET</code> (or<code>C-h R</code>) and enter the package name (e.g.<code>org-extras</code>). You can also browse all available manuals with<code>M-x info RET</code> (<code>C-h i</code>). (The<code>:vc</code> recipe does not currently build Info manuals due to a limitation in<code>package-vc</code>.)</p><h2 id="early-init">early-init</h2><p>The contents of this code block are tangled to the<code>early-init.el</code> file.</p><p>First, I check the system appearance and blacken the screen if it&rsquo;s set to `dark`. This is done to prevent a flash of white during startup on macOS when using a dark theme. I use frame parameters to set the background and foreground colors instead of<code>set-face-attribute</code> to avoid interfering with<code>face-spec-recalc</code> during theme switches.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">macos-get-system-appearance</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Return the current macOS system appearance."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">intern</span><span class="p">(</span><span class="nf">downcase</span><span class="p">(</span><span class="nv">string-trim</span><span class="p">(</span><span class="nv">shell-command-to-string</span></span></span><span class="line"><span class="cl"><span class="s">"defaults read -g AppleInterfaceStyle 2&gt;/dev/null || echo 'Light'"</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">early-init-blacken-screen</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Blacken screen as soon as Emacs starts, if the system theme is</span><span class="ss">`dark'</span><span class="s">.</span></span></span><span class="line"><span class="cl"><span class="s">Use frame parameters instead of</span><span class="ss">`set-face-attribute'</span><span class="s"> to avoid</span></span></span><span class="line"><span class="cl"><span class="s">interfering with</span><span class="ss">`face-spec-recalc'</span><span class="s"> during theme switches."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">eq</span><span class="p">(</span><span class="nv">macos-get-system-appearance</span><span class="p">)</span><span class="ss">'dark</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">mode-line-format</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="nv">background-color</span><span class="o">.</span><span class="s">"#000000"</span><span class="p">)</span><span class="nv">default-frame-alist</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="nv">foreground-color</span><span class="o">.</span><span class="s">"#ffffff"</span><span class="p">)</span><span class="nv">default-frame-alist</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">early-init-blacken-screen</span><span class="p">)</span></span></span></code></pre></div><p>I also disable package initialization at startup (recommended for elpaca) and set<code>load-prefer-newer</code> to<code>t</code> to ensure that Emacs always loads the latest version of a package (useful during development when packages are frequently updated).</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">package-enable-at-startup</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">load-prefer-newer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><p>Then, I set some frame parameters to remove the title bar and maximize the frame on startup.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'default-frame-alist</span><span class="o">'</span><span class="p">(</span><span class="nv">undecorated-round</span><span class="o">.</span><span class="no">t</span><span class="p">))</span><span class="c1">; remove title bar</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'initial-frame-alist</span><span class="o">'</span><span class="p">(</span><span class="nv">fullscreen</span><span class="o">.</span><span class="nv">maximized</span><span class="p">))</span><span class="c1">; maximize frame on startup</span></span></span></code></pre></div><p>Finally, I redirect the native compilation cache to a directory within my Emacs profile and define a function for debugging feature loading.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="c1">;; github.com/emacscollective/no-littering#native-compilation-cache</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">fboundp</span><span class="ss">'startup-redirect-eln-cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">startup-redirect-eln-cache</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"HOME"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">".config/emacs-profiles/var/eln-cache/"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; for debugging</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">early-init-trace-feature-load</span><span class="p">(</span><span class="nv">feature</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Print a backtrace immediately after FEATURE is loaded."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-after-load</span><span class="nv">feature</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">(</span><span class="nf">message</span><span class="s">"Feature '%s' loaded by:\n%s"</span></span></span><span class="line"><span class="cl"><span class="ss">',feature</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-output-to-string</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">backtrace</span><span class="p">)))))</span></span></span></code></pre></div><h2 id="package-management">package management</h2><h3 id="elpaca"><code>elpaca</code></h3><p><em><a href="https://github.com/progfolio/elpaca">elpaca</a> is a package manager that supports asynchronous installation of packages.</em></p><p>When experiencing issues,<a href="https://github.com/progfolio/elpaca/wiki/Troubleshooting">follow these steps</a>.</p><ul><li>By default,<code>elpaca</code> makes shallow copies of all the repos it clones. You can specify the repo depth with the<a href="https://github.com/progfolio/elpaca/blob/master/doc/manual.md#recipe-keyword-depth">:depth</a> keyword. What if, however, you want to turn a shallow repo into a full repo<em>after</em> it has been cloned? There is a relatively obscure command in Magit that lets you do this:<code>magit-remote-unshallow</code>. (Note that this not only passes the<code>--unshallow</code> flag but also restores access to all branches in addition to the main one.)</li></ul><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="c1">;;; init.el --- Init File -*- lexical-binding: t -*-</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">elpaca-installer-version</span><span class="mf">0.12</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">elpaca-directory</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"elpaca/"</span><span class="nv">user-emacs-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">elpaca-builds-directory</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"builds/"</span><span class="nv">elpaca-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">elpaca-sources-directory</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"sources/"</span><span class="nv">elpaca-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Using benthamite fork until progfolio/elpaca#513 is merged (mono-repo deadlock fix).</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">elpaca-order</span><span class="o">'</span><span class="p">(</span><span class="nv">elpaca</span><span class="nb">:repo</span><span class="s">"https://github.com/benthamite/elpaca.git"</span></span></span><span class="line"><span class="cl"><span class="nb">:ref</span><span class="s">"6503e6c19931dc42bf16e9af980d2e69921f7b6a"</span><span class="nb">:depth</span><span class="mi">1</span><span class="nb">:inherit</span><span class="nv">ignore</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="nb">:defaults</span><span class="s">"elpaca-test.el"</span><span class="p">(</span><span class="nb">:exclude</span><span class="s">"extensions"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-activate</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">repo</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"elpaca/"</span><span class="nv">elpaca-sources-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">build</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"elpaca/"</span><span class="nv">elpaca-builds-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">order</span><span class="p">(</span><span class="nf">cdr</span><span class="nv">elpaca-order</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">default-directory</span><span class="nv">repo</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'load-path</span><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">file-exists-p</span><span class="nv">build</span><span class="p">)</span><span class="nv">build</span><span class="nv">repo</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nf">file-exists-p</span><span class="nv">repo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">make-directory</span><span class="nv">repo</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">&lt;=</span><span class="nv">emacs-major-version</span><span class="mi">28</span><span class="p">)</span><span class="p">(</span><span class="nb">require</span><span class="ss">'subr-x</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">condition-case-unless-debug</span><span class="nv">err</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">if-let*</span><span class="p">((</span><span class="nv">buffer</span><span class="p">(</span><span class="nv">pop-to-buffer-same-window</span><span class="s">"*elpaca-bootstrap*"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">zerop</span><span class="p">(</span><span class="nf">apply</span><span class="nf">#'call-process</span><span class="o">`</span><span class="p">(</span><span class="s">"git"</span><span class="no">nil</span><span class="o">,</span><span class="nv">buffer</span><span class="no">t</span><span class="s">"clone"</span></span></span><span class="line"><span class="cl"><span class="o">,@</span><span class="p">(</span><span class="nv">when-let*</span><span class="p">((</span><span class="nv">depth</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">order</span><span class="nb">:depth</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nf">format</span><span class="s">"--depth=%d"</span><span class="nv">depth</span><span class="p">)</span><span class="s">"--no-single-branch"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">order</span><span class="nb">:repo</span><span class="p">)</span><span class="o">,</span><span class="nv">repo</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">zerop</span><span class="p">(</span><span class="nf">call-process</span><span class="s">"git"</span><span class="no">nil</span><span class="nv">buffer</span><span class="no">t</span><span class="s">"checkout"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">or</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">order</span><span class="nb">:ref</span><span class="p">)</span><span class="s">"--"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emacs</span><span class="p">(</span><span class="nf">concat</span><span class="nf">invocation-directory</span><span class="nf">invocation-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">zerop</span><span class="p">(</span><span class="nf">call-process</span><span class="nv">emacs</span><span class="no">nil</span><span class="nv">buffer</span><span class="no">nil</span><span class="s">"-Q"</span><span class="s">"-L"</span><span class="s">"."</span><span class="s">"--batch"</span></span></span><span class="line"><span class="cl"><span class="s">"--eval"</span><span class="s">"(byte-recompile-directory \".\" 0 'force)"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nb">require</span><span class="ss">'elpaca</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">elpaca-generate-autoloads</span><span class="s">"elpaca"</span><span class="nv">repo</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span><span class="p">(</span><span class="nf">message</span><span class="s">"%s"</span><span class="p">(</span><span class="nf">buffer-string</span><span class="p">))</span><span class="p">(</span><span class="nf">kill-buffer</span><span class="nv">buffer</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ne">error</span><span class="s">"%s"</span><span class="p">(</span><span class="nb">with-current-buffer</span><span class="nv">buffer</span><span class="p">(</span><span class="nf">buffer-string</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="ne">error</span><span class="p">)</span><span class="p">(</span><span class="ne">warn</span><span class="s">"%s"</span><span class="nv">err</span><span class="p">)</span><span class="p">(</span><span class="nv">delete-directory</span><span class="nv">repo</span><span class="ss">'recursive</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nb">require</span><span class="ss">'elpaca-autoloads</span><span class="no">nil</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'elpaca</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-generate-autoloads</span><span class="s">"elpaca"</span><span class="nv">repo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">load-source-file-function</span><span class="no">nil</span><span class="p">))</span><span class="p">(</span><span class="nf">load</span><span class="s">"./elpaca-autoloads"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'after-init-hook</span><span class="nf">#'</span><span class="nv">elpaca-process-queues</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca</span><span class="o">`</span><span class="p">(</span><span class="o">,@</span><span class="nv">elpaca-order</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-wait</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; NOTE: Do not set elpaca-queue-limit. It counts *all* queued packages (not just</span></span></span><span class="line"><span class="cl"><span class="c1">;; actively cloning ones) as "active", causing a false deadlock on fresh installs</span></span></span><span class="line"><span class="cl"><span class="c1">;; where hundreds of packages are enqueued simultaneously. See elpaca--continue-build.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'elpaca-menu-elpa</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'packages-url</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'gnu</span><span class="nv">elpaca-menu-elpas</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">"https://raw.githubusercontent.com/emacsmirror/gnu_elpa/refs/heads/main/elpa-packages"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'remote</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'gnu</span><span class="nv">elpaca-menu-elpas</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">"https://github.com/emacsmirror/gnu_elpa"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'packages-url</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'nongnu</span><span class="nv">elpaca-menu-elpas</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">"https://raw.githubusercontent.com/emacsmirror/nongnu_elpa/refs/heads/main/elpa-packages"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'remote</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'nongnu</span><span class="nv">elpaca-menu-elpas</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">"https://github.com/emacsmirror/nongnu_elpa"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">toggle-debug-on-error</span><span class="p">)</span><span class="c1">; uncomment when debugging</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">elpaca-lock-file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="p">(</span><span class="nf">file-name-directory</span><span class="p">(</span><span class="nf">directory-file-name</span><span class="nv">elpaca-directory</span><span class="p">))</span><span class="s">"lockfile.el"</span><span class="p">))</span></span></span></code></pre></div><h3 id="use-package"><code>use-package</code></h3><p><em><a href="https://github.com/jwiegley/use-package">use-package</a> is a package organizer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca</span><span class="nv">elpaca-use-package</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-use-package-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nb">use-package</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package-always-ensure</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package-verbose</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package-compute-statistics</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package-hook-name-suffix</span><span class="no">nil</span><span class="p">)</span><span class="c1">; use real name for hooks, i.e. do not omit the `-hook' bit</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-package-minimum-reported-time</span><span class="mf">0.1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defmacro</span><span class="nv">use-personal-package</span><span class="p">(</span><span class="nv">name</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Like</span><span class="ss">`use-package'</span><span class="s"> but to load personal packages.</span></span></span><span class="line"><span class="cl"><span class="s">NAME and ARGS as in</span><span class="ss">`use-package'</span><span class="s">."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">declare</span><span class="p">(</span><span class="nv">indent</span><span class="nb">defun</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">name-str</span><span class="p">(</span><span class="nf">symbol-name</span><span class="p">(</span><span class="nf">eval</span><span class="o">`</span><span class="p">(</span><span class="nb">quote</span><span class="o">,</span><span class="nv">name</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">(</span><span class="nb">use-package</span><span class="o">,</span><span class="nv">name</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="o">,</span><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nv">file-name-concat</span></span></span><span class="line"><span class="cl"><span class="s">"emacs/extras"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-with-extension</span><span class="nv">name-str</span><span class="s">"el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span></span></span><span class="line"><span class="cl"><span class="s">"emacs/extras/doc"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-with-extension</span><span class="nv">name-str</span><span class="s">"texi"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">,@</span><span class="nv">args</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-wait</span><span class="p">)</span></span></span></code></pre></div><p>Because<code>use-personal-package</code> declares each extras file with an<code>:ensure</code> recipe pointing at this GitHub repository,<code>elpaca</code> treats them like any other package: it clones the repo into its own<code>elpaca/repos/dotfiles/</code> directory and builds the relevant files from there. This means the dotfiles end up in two separate local clones—the primary one in my main dotfiles location (where all edits are made) and the elpaca-managed one under<code>elpaca/repos/dotfiles/</code> (which Emacs loads from). To keep them in sync, three git hooks in the primary clone&rsquo;s gitdir automatically propagate changes to the elpaca clone. The<code>post-commit</code> hook handles normal commits, the<code>post-rewrite</code> hook handles rebases and amends, and both delegate to a shared<code>sync-elpaca-clone.sh</code> script. All three files live in the gitdir&rsquo;s<code>hooks/</code> directory and must be executable. The script reads the active profile name from a cache file (<code>~/.config/emacs-profiles/.current-profile</code>) that Emacs writes at startup, rather than calling<code>emacsclient</code>, to avoid deadlocking when the hook is triggered by a synchronous git process inside Emacs (e.g.,<code>magit-commit-squash</code>).</p><p><code>hooks/sync-elpaca-clone.sh</code>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="cp">#!/bin/sh</span></span></span><span class="line"><span class="cl"><span class="c1"># Propagate the current state of master to the elpaca dotfiles clone.</span></span></span><span class="line"><span class="cl"><span class="c1"># Reads the active profile from a cache file written by Emacs at startup,</span></span></span><span class="line"><span class="cl"><span class="c1"># avoiding emacsclient calls that deadlock when git is spawned synchronously</span></span></span><span class="line"><span class="cl"><span class="c1"># by Emacs.</span></span></span><span class="line"><span class="cl"><span class="c1"># Called by post-commit and post-rewrite hooks.</span></span></span><span class="line"><span class="cl"><span class="nv">PROFILE</span><span class="o">=</span><span class="k">$(</span>cat<span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/.config/emacs-profiles/.current-profile"</span> 2&gt;/dev/null<span class="k">)</span></span></span><span class="line"><span class="cl"><span class="nv">ELPACA_BASE</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/.config/emacs-profiles/</span><span class="nv">$PROFILE</span><span class="s2">/elpaca"</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1"># Newer elpaca versions use sources/ instead of repos/</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="o">[</span> -d<span class="s2">"</span><span class="nv">$ELPACA_BASE</span><span class="s2">/sources/dotfiles/.git"</span><span class="o">]</span><span class="p">;</span><span class="k">then</span></span></span><span class="line"><span class="cl"><span class="nv">ELPACA_DOTFILES</span><span class="o">=</span><span class="s2">"</span><span class="nv">$ELPACA_BASE</span><span class="s2">/sources/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="k">elif</span><span class="o">[</span> -d<span class="s2">"</span><span class="nv">$ELPACA_BASE</span><span class="s2">/repos/dotfiles/.git"</span><span class="o">]</span><span class="p">;</span><span class="k">then</span></span></span><span class="line"><span class="cl"><span class="nv">ELPACA_DOTFILES</span><span class="o">=</span><span class="s2">"</span><span class="nv">$ELPACA_BASE</span><span class="s2">/repos/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="k">fi</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="k">if</span><span class="o">[</span> -n<span class="s2">"</span><span class="nv">$ELPACA_DOTFILES</span><span class="s2">"</span><span class="o">]</span><span class="p">;</span><span class="k">then</span></span></span><span class="line"><span class="cl"><span class="nv">GITDIR</span><span class="o">=</span><span class="s2">"</span><span class="nv">$GIT_DIR</span><span class="s2">"</span></span></span><span class="line"><span class="cl"><span class="c1"># The parent git process sets GIT_DIR, GIT_INDEX_FILE, and</span></span></span><span class="line"><span class="cl"><span class="c1"># GIT_WORK_TREE pointing at the Google Drive clone. Unsetting them</span></span></span><span class="line"><span class="cl"><span class="c1"># is essential so that git commands target the elpaca clone.</span></span></span><span class="line"><span class="cl"><span class="nb">unset</span> GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE</span></span><span class="line"><span class="cl"> git -C<span class="s2">"</span><span class="nv">$ELPACA_DOTFILES</span><span class="s2">"</span> fetch<span class="s2">"</span><span class="nv">$GITDIR</span><span class="s2">"</span> master 2&gt;<span class="p">&amp;</span><span class="m">1</span><span class="o">&amp;&amp;</span></span></span><span class="line"><span class="cl"> git -C<span class="s2">"</span><span class="nv">$ELPACA_DOTFILES</span><span class="s2">"</span> reset --hard FETCH_HEAD 2&gt;<span class="p">&amp;</span><span class="m">1</span></span></span><span class="line"><span class="cl"><span class="k">fi</span></span></span></code></pre></div><p><code>hooks/post-commit</code>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="cp">#!/bin/sh</span></span></span><span class="line"><span class="cl"><span class="nb">exec</span><span class="s2">"</span><span class="k">$(</span>dirname<span class="s2">"</span><span class="nv">$0</span><span class="s2">"</span><span class="k">)</span><span class="s2">/sync-elpaca-clone.sh"</span></span></span></code></pre></div><p><code>hooks/post-rewrite</code>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="cp">#!/bin/sh</span></span></span><span class="line"><span class="cl"><span class="nb">exec</span><span class="s2">"</span><span class="k">$(</span>dirname<span class="s2">"</span><span class="nv">$0</span><span class="s2">"</span><span class="k">)</span><span class="s2">/sync-elpaca-clone.sh"</span></span></span></code></pre></div><h3 id="use-package-extras"><code>use-package-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/use-package-extras.el">use-package-extras</a> collects my extensions for<code>use-package</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">use-package-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span><span class="o">.</span><span class="nv">use-package-extras-display-startup-time</span><span class="p">))</span></span></span></code></pre></div><h3 id="elpaca-extras"><code>elpaca-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/elpaca-extras.el">elpaca-extras</a> collects my extensions for<code>elpaca</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">elpaca-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:wait</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">use-package-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-extras-write-lock-file-excluded</span><span class="o">'</span><span class="p">(</span><span class="nv">tlon</span><span class="p">)))</span></span></span></code></pre></div><h2 id="foundational">foundational</h2><h3 id="gcmh"><code>gcmh</code></h3><p><em><a href="https://github.com/emacsmirror/gcmh">GCMH</a> enforces a sneaky Garbage Collection strategy to minimize GC interference with user activity.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">gcmh</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gcmh-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="seq"><code>seq</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/seq.el">seq</a> provides sequence-manipulation functions that complement basic functions provided by<code>subr.el</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="c1">;; https://github.com/progfolio/elpaca/issues/216#issuecomment-1868747372</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">elpaca-unload-seq</span><span class="p">(</span><span class="nv">e</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nb">featurep</span><span class="ss">'seq</span><span class="p">)</span><span class="p">(</span><span class="nv">unload-feature</span><span class="ss">'seq</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca--continue-build</span><span class="nv">e</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">seq</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="o">`</span><span class="p">(</span><span class="nv">seq</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:before</span><span class="nv">elpaca-activate</span><span class="nv">elpaca-unload-seq</span><span class="p">)))</span></span></span></code></pre></div><h3 id="paths"><code>paths</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/paths.el">paths</a> defines various paths used in this configuration.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">paths</span><span class="p">)</span></span></span></code></pre></div><h3 id="transient"><code>transient</code></h3><p><em>transient is a library for creating keyboard-driven menus.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">transient</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"magit/transient"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"main"</span><span class="c1">; github.com/progfolio/elpaca/issues/342</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">seq</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">transient-default-level</span><span class="mi">7</span><span class="p">)</span><span class="c1">; magit.vc/manual/transient/Enabling-and-Disabling-Suffixes.html</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">transient-save-history</span><span class="no">nil</span><span class="p">)</span><span class="c1">; the history file was throwing an error on startup</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">transient-base-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-q"</span><span class="o">.</span><span class="nv">transient-quit-one</span><span class="p">)))</span></span></span></code></pre></div><h3 id="init"><code>init</code></h3><p><em><a href="https://github.com/benthamite/init">init</a> is a private package that I use to manage my config files and profiles.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">init</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/init"</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="c1">; clone entire repo, not just last commit</span></span></span><span class="line"><span class="cl"><span class="nb">:wait</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">paths</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-startup</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Cache the profile name to a file so that git hooks can read it</span></span></span><span class="line"><span class="cl"><span class="c1">;; without calling emacsclient (which deadlocks when the hook is</span></span></span><span class="line"><span class="cl"><span class="c1">;; spawned by a synchronous git process inside Emacs).</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-temp-file</span><span class="p">(</span><span class="nv">file-name-concat</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">file-name-directory</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">directory-file-name</span><span class="nv">user-emacs-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">".current-profile"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="nv">init-current-profile</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-n"</span><span class="o">.</span><span class="nv">init-menu</span><span class="p">))</span></span></span></code></pre></div><h3 id="no-littering"><code>no-littering</code></h3><p><em><a href="https://github.com/emacscollective/no-littering">no-littering</a> keeps<code>.emacs.d</code> clean.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">no-littering</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:wait</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="c1">;; these directories should be shared across profiles, so there should</span></span></span><span class="line"><span class="cl"><span class="c1">;; be only one `var' and one `etc' directory in `emacs-profiles'</span></span></span><span class="line"><span class="cl"><span class="c1">;; rather than a pair of such directories for each profile</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">no-littering-etc-directory</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-emacs-profiles</span><span class="s">"etc/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">no-littering-var-directory</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-emacs-profiles</span><span class="s">"var/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; github.com/emacscollective/no-littering#auto-save-settings</span></span></span><span class="line"><span class="cl"><span class="c1">;; should not be set via :custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">auto-save-file-name-transforms</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="s">".*"</span><span class="o">,</span><span class="p">(</span><span class="nv">no-littering-expand-var-file-name</span><span class="s">"auto-save/"</span><span class="p">)</span><span class="no">t</span><span class="p">))))</span></span></span></code></pre></div><h3 id="ns-win"><code>ns-win</code></h3><p><em>ns-win provides various Nexstep convenience functions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ns-win</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-option-modifier</span><span class="ss">'meta</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-control-modifier</span><span class="ss">'control</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-command-modifier</span><span class="ss">'hyper</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-function-modifier</span><span class="ss">'none</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-right-option-modifier</span><span class="ss">'none</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-right-control-modifier</span><span class="ss">'super</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mac-right-command-modifier</span><span class="ss">'alt</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; ns-use-proxy-icon set to t causes Emacs to freeze</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ns-use-proxy-icon</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="iso-transl"><code>iso-transl</code></h3><p><em>iso-transl defines ways of entering the non-ASCII printable characters with codes above 127.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">iso-transl</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">iso-transl-char-map</span><span class="no">nil</span><span class="p">)</span><span class="c1">; emacs.stackexchange.com/questions/17508/</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; unset all `Super' key bindings</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">char</span><span class="p">(</span><span class="nv">number-sequence</span><span class="sc">?a</span><span class="sc">?z</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">keymap-global-unset</span><span class="p">(</span><span class="nf">concat</span><span class="s">"s-"</span><span class="p">(</span><span class="nf">char-to-string</span><span class="nv">char</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; unset some `Alt' key bindings in `key-translation-map'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">char</span><span class="o">'</span><span class="p">(</span><span class="s">"SPC"</span><span class="s">"!"</span><span class="s">"$"</span><span class="s">"+"</span><span class="s">"-"</span><span class="s">"&lt;"</span><span class="s">"&gt;"</span><span class="s">"?"</span><span class="s">"a"</span><span class="s">"c"</span><span class="s">"m"</span><span class="s">"o"</span><span class="s">"u"</span></span></span><span class="line"><span class="cl"><span class="s">"x"</span><span class="s">"C"</span><span class="s">"L"</span><span class="s">"P"</span><span class="s">"R"</span><span class="s">"S"</span><span class="s">"T"</span><span class="s">"Y"</span><span class="s">"["</span><span class="s">"]"</span><span class="s">"{"</span><span class="s">"|"</span><span class="s">"}"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">keymap-unset</span><span class="nv">key-translation-map</span><span class="p">(</span><span class="nf">concat</span><span class="s">"A-"</span><span class="nv">char</span><span class="p">))))</span></span></span></code></pre></div><h3 id="el-patch"><code>el-patch</code></h3><p><em><a href="https://github.com/raxod502/el-patch">el-patch</a> customizes the behavior of Emacs Lisp functions and notifies the user when a function so customized changes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">el-patch</span><span class="p">)</span></span></span></code></pre></div><h3 id="casual"><code>casual</code></h3><p><em><a href="https://github.com/kickingvegas/casual">casual</a> is a collection of Transient menus for various Emacs modes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">casual</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'calc-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">calc-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-o"</span><span class="o">.</span><span class="nv">casual-calc-tmenu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">calc-alg-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-o"</span><span class="o">.</span><span class="nv">casual-calc-tmenu</span><span class="p">))))</span></span></span></code></pre></div><h3 id="warnings"><code>warnings</code></h3><p><em>warnings provides support for logging and displaying warnings.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">warnings</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">warning-suppress-types</span><span class="o">'</span><span class="p">((</span><span class="nv">copilot</span><span class="nv">copilot-exceeds-max-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck</span><span class="nv">syntax-checker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tramp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">aidermacs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-element-cache</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">yasnippet</span><span class="nv">backquote-change</span><span class="p">))))</span></span></span></code></pre></div><h3 id="comp"><code>comp</code></h3><p><em>comp compiles Lisp code into native code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">comp</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">native-comp-async-report-warnings-errors</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="bytecomp"><code>bytecomp</code></h3><p><em>bytecomp compiles Lisp code into byte code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">bytecomp</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">byte-compile-warnings</span><span class="o">'</span><span class="p">(</span><span class="nv">cl-functions</span><span class="p">)))</span></span></span></code></pre></div><h3 id="startup"><code>startup</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/startup.el">startup</a> processes Emacs shell arguments and controls startup behavior.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">user-full-name</span><span class="s">"Pablo Stafforini"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">user-mail-address</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_GMAIL"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">initial-scratch-message</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">inhibit-startup-screen</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">inhibit-startup-echo-area-message</span><span class="nf">user-login-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">inhibit-startup-buffer-menu</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">frame-resize-pixelwise</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="server"><code>server</code></h3><p><em>server starts a server for external clients to connect to.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">server</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nv">server-running-p</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">server-start</span><span class="p">)))</span></span></span></code></pre></div><h3 id="async"><code>async</code></h3><p><em><a href="https://github.com/jwiegley/emacs-async">async</a> is a simple library for asynchronous processing in Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">async</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="prot-common"><code>prot-common</code></h3><p><em>[[<a href="https://github.com/protesilaos/dotfiles/blob/master/emacs">https://github.com/protesilaos/dotfiles/blob/master/emacs</a></em>.emacs.d/prot-lisp/prot-common.el][prot-common]] is a set of functions used by Protesilaos Stavrou&rsquo;s unreleased &ldquo;packages&rdquo;._</p><p>Note Prot&rsquo;s clarification:</p><blockquote><p>Remember that every piece of Elisp that I write is for my own educational and recreational purposes. I am not a programmer and I do not recommend that you copy any of this if you are not certain of what it does.</p></blockquote><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">prot-common</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:local-repo</span><span class="s">"prot-common"</span></span></span><span class="line"><span class="cl"><span class="nb">:main</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-common.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-common.el"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="prot-simple"><code>prot-simple</code></h3><p><em>[[<a href="https://github.com/protesilaos/dotfiles/blob/master/emacs">https://github.com/protesilaos/dotfiles/blob/master/emacs</a></em>.emacs.d/prot-lisp/prot-simple.el][prot-simple]] is a set of common commands used by Protesilaos Stavrou&rsquo;s unreleased &ldquo;packages&rdquo;._</p><p>Note Prot&rsquo;s clarification:</p><blockquote><p>Remember that every piece of Elisp that I write is for my own educational and recreational purposes. I am not a programmer and I do not recommend that you copy any of this if you are not certain of what it does.</p></blockquote><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">prot-simple</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:local-repo</span><span class="s">"prot-simple"</span></span></span><span class="line"><span class="cl"><span class="nb">:main</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-simple.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-simple.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">prot-common</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prot-simple-date-specifier</span><span class="s">"%F"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prot-simple-time-specifier</span><span class="s">"%R %z"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-s-="</span><span class="o">.</span><span class="nv">prot-simple-insert-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-j"</span><span class="o">.</span><span class="nv">prot-simple-mark-sexp</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bug-hunter"><code>bug-hunter</code></h3><p><em><a href="https://elpa.gnu.org/packages/bug-hunter.html">bug-hunter</a> interactively bisects and debugs your init file.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">bug-hunter</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="inheritenv"><code>inheritenv</code></h3><p><em><a href="https://github.com/purcell/inheritenv">inheritenv</a> allows temp buffers to inherit buffer-local environment variables.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">inheritenv</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"purcell/inheritenv"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="misc"><code>misc</code></h3><p><em>Miscellaneous settings: default directory, short answers, message log, bell, cursor width, and UTF-8 encoding.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">default-directory</span><span class="nv">paths-dir-dropbox</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-short-answers</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-log-max</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ring-bell-function</span><span class="ss">'ignore</span><span class="p">)</span><span class="c1">; silence bell when mistake is made</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">x-stretch-cursor</span><span class="no">t</span><span class="p">)</span><span class="c1">; make curor the width of the character under it</span></span></span><span class="line"><span class="cl"><span class="c1">;; emacs.stackexchange.com/questions/14509/kill-process-buffer-without-confirmation</span></span></span><span class="line"><span class="cl"><span class="c1">;; UTF8 stuff.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prefer-coding-system</span><span class="ss">'utf-8</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-default-coding-systems</span><span class="ss">'utf-8</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-terminal-coding-system</span><span class="ss">'utf-8</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-keyboard-coding-system</span><span class="ss">'utf-8</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">input-decode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-8"</span><span class="o">.</span><span class="s">"•"</span><span class="p">)))</span></span></span></code></pre></div><h2 id="performance">performance</h2><h3 id="profiler"><code>profiler</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/profiler.el">profiler</a> provides UI and helper functions for the Emacs profiler.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">profiler</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="profiler-extras"><code>profiler-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/profiler-extras.el">profiler-extras</a> collects my extensions for<code>profiler</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">profiler-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-p"</span><span class="o">.</span><span class="nv">profiler-extras-profiler-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">profiler-report-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">profiler-extras-profiler-report-toggle-entry-global</span><span class="p">)))</span></span></span></code></pre></div><h3 id="so-long"><code>so-long</code></h3><p><em><a href="https://savannah.nongnu.org/projects/so-long">so-long</a> optimizes performance with minified code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">so-long</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">so-long-threshold</span><span class="mi">500000</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">find-file-hook</span><span class="o">.</span><span class="nv">global-so-long-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="misc-dot"><code>misc.</code></h3><p><em>Performance-related settings: bidirectional display, font caches, fontification skipping, and process output buffer size.</em></p><p>Partly borrowed from<a href="https://gitlab.com/protesilaos/dotfiles/-/blob/350ca3144c5ee868056619b9d6351fca0d6b131e/emacs/.emacs.d/emacs-init.org">Prot</a>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bidi-display-reordering</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bidi-inhibit-bpa</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">inhibit-compacting-font-caches</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">redisplay-skip-fontification-on-input</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; emacs-lsp.github.io/lsp-mode/page/performance/</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">read-process-output-max</span><span class="p">(</span><span class="nf">expt</span><span class="mi">1024</span><span class="mi">2</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bidi-paragraph-direction</span><span class="ss">'left-to-right</span><span class="p">))</span></span></span></code></pre></div><h2 id="secrets">secrets</h2><h3 id="plstore"><code>plstore</code></h3><p><em>plstore is a plist based data store providing search and partial encryption.</em></p><p>This feature is required by<code>org-gcal</code>. We create a new GPG key to use with<code>org-gcal</code> and add its public ID to<code>plstore-encrypt-to</code> , following<a href="https://github.com/kidd/org-gcal.el#note">these instructions</a>. (This method is superior to using symmetric encryption because it does not prompt the user for authentication with every new Emacs session.)</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">plstore</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pass</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'plstore-encrypt-to</span><span class="s">"A7C6A908CD1254A8B4051D3DCDBBB523C9627A26"</span><span class="p">))</span></span></span></code></pre></div><h3 id="epg-config"><code>epg-config</code></h3><p><em>epg-config provides configuration for the Easy Privacy Guard library.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">epg-config</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">epg-pinentry-mode</span><span class="ss">'loopback</span><span class="p">)</span><span class="c1">; use minibuffer for password entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">epg-gpg-program</span><span class="s">"/opt/homebrew/bin/gpg"</span><span class="p">))</span></span></span></code></pre></div><h3 id="auth-source"><code>auth-source</code></h3><p><em>auth-source supports authentication sources for Gnus and Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">auth-source</span></span></span><span class="line"><span class="cl"><span class="nb">:preface</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">eval-when-compile</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defvar</span><span class="nv">auth-sources</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-debug</span><span class="no">nil</span><span class="p">)</span><span class="c1">; set to t for debugging</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-do-cache</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-sources</span><span class="o">'</span><span class="p">(</span><span class="nv">macos-keychain-internet</span><span class="nv">macos-keychain-generic</span><span class="p">)))</span></span></span></code></pre></div><h3 id="oauth2-auto"><code>oauth2-auto</code></h3><p><em><a href="https://github.com/telotortium/emacs-oauth2-auto">emacs-oauth2-auto</a> supports authentication to an OAuth2 provider from within Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">oauth2-auto</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"telotortium/emacs-oauth2-auto"</span></span></span><span class="line"><span class="cl"><span class="nb">:protocol</span><span class="nv">ssh</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-gcal</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">oauth2-auto-plstore</span><span class="p">(</span><span class="nv">no-littering-expand-var-file-name</span><span class="s">"oauth2-auto.plist"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pass"><code>pass</code></h3><p><em><a href="https://github.com/NicolasPetton/pass">pass</a> is a major mode for<a href="https://en.wikipedia.org/wiki/Pass_%28software%29">pass</a>, the standard Unix password manager</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pass</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pass-suppress-confirmations</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pass-show-keybindings</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">5</span><span class="mi">60</span><span class="p">)</span><span class="no">t</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">magit-extras-warn-if-repo-is-dirty</span><span class="nv">paths-dir-dropbox-tlon-pass</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-o"</span><span class="o">.</span><span class="nv">pass</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">pass-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"RET"</span><span class="o">.</span><span class="nv">pass-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">pass-copy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">pass-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">pass-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">pass-view-toggle-password</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">pass-quit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">server-edit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pass-extras"><code>pass-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/pass-extras.el">pass-extras</a> collects my extensions for<code>pass</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">pass-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">pass-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"SPC"</span><span class="o">.</span><span class="nv">pass-extras-open-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pass-extras-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"G"</span><span class="o">.</span><span class="nv">pass-extras-generate-password</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">pass-extras-insert-generated-no-symbols</span><span class="p">)))</span></span></span></code></pre></div><h3 id="password-store-otp"><code>password-store-otp</code></h3><p><em><a href="https://github.com/volrath/password-store-otp.el">password-store-otp</a> provides integration with the pass-otp extension for pass.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">password-store-otp</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:version</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">_</span><span class="p">)</span><span class="s">"0.1.5"</span><span class="p">))</span><span class="c1">; github.com/progfolio/elpaca/issues/229</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pass</span><span class="p">)</span></span></span></code></pre></div><h3 id="auth-source-pass"><code>auth-source-pass</code></h3><p><em>auth-source-pass integrates auth-source with password-store.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">auth-source-pass</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">auth-source</span><span class="nv">pass</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-pass-enable</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-before-github-fetch-notification-hook</span><span class="o">.</span><span class="nv">auth-source-pass-enable</span><span class="p">))</span></span></span></code></pre></div><h3 id="password-generator"><code>password-generator</code></h3><p><em><a href="https://github.com/vandrlexay/emacs-password-genarator">password-generator</a> [sic] generates various types of passwords.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">password-generator</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"vandrlexay/emacs-password-genarator"</span><span class="p">)</span><span class="c1">; sic</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h2 id="version-control">version control</h2><h3 id="vc"><code>vc</code></h3><p><em>vc provides support for various version control systems.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">vc</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-handled-backends</span><span class="o">'</span><span class="p">(</span><span class="nv">Git</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-follow-symlinks</span><span class="no">t</span><span class="p">)</span><span class="c1">; don't ask for confirmation when opening symlinked file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-make-backup-files</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not backup version controlled files</span></span></span><span class="line"><span class="cl"><span class="c1">;; Disable VC in Dropbox cloud storage directories. `vc-git' runs</span></span></span><span class="line"><span class="cl"><span class="c1">;; synchronous `git' subprocesses via `call-process', which can hang</span></span></span><span class="line"><span class="cl"><span class="c1">;; indefinitely when Dropbox's virtual filesystem stalls on I/O</span></span></span><span class="line"><span class="cl"><span class="c1">;; (e.g. smart sync resolving a cloud-only file). This blocks the</span></span></span><span class="line"><span class="cl"><span class="c1">;; main thread since there is no timeout on the read.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-ignore-dir-regexp</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">format</span><span class="s">"%s\\|%s\\|%s"</span></span></span><span class="line"><span class="cl"><span class="nv">vc-ignore-dir-regexp</span></span></span><span class="line"><span class="cl"><span class="s">"Library/CloudStorage/Dropbox/"</span></span></span><span class="line"><span class="cl"><span class="s">"My Drive/"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="vc-extras"><code>vc-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/vc-extras.el">vc-extras</a> collects my extensions for<code>vc</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">vc-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">vc</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-extras-split-repo</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-v"</span><span class="o">.</span><span class="nv">vc-extras-menu</span><span class="p">))</span></span></span></code></pre></div><h3 id="log-edit"><code>log-edit</code></h3><p><em>log-edit is a major mode for editing CVS commit messages.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">log-edit</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'log-edit-comment-ring</span><span class="p">)))</span></span></span></code></pre></div><h3 id="diff-mode"><code>diff-mode</code></h3><p><em>diff-mode is a mode for viewing and editing context diffs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">diff-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">diff-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-o"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ediff"><code>ediff</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/vc/ediff.el">ediff</a> is a comprehensive visual interface to diff and patch.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ediff</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ediff-window-setup-function</span><span class="ss">'ediff-setup-windows-plain</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ediff-split-window-function</span><span class="ss">'split-window-horizontally</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">ediff-toggle-word-mode</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Toggle between linewise and wordwise comparisons."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">ediff-word-mode</span><span class="p">(</span><span class="nv">not</span><span class="nv">ediff-word-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"Word mode %s"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="nv">ediff-word-mode</span><span class="s">"disabled"</span><span class="s">"enabled"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ediff-update-diffs</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-d"</span><span class="o">.</span><span class="nv">ediff</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ediff-extras"><code>ediff-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/ediff-extras.el">ediff-extras</a> collects my extensions for<code>ediff</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">ediff-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ediff</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="smerge"><code>smerge</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/vc/smerge-mode.el">smerge-mode</a> is a minor mode for resolving diff3 conflicts.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">smerge-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">smerge-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-n"</span><span class="o">.</span><span class="nv">smerge-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-SPC"</span><span class="o">.</span><span class="nv">smerge-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">smerge-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">smerge-keep-lower</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">smerge-keep-upper</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">smerge-keep-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">smerge-keep-base</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">smerge-keep-current</span><span class="p">)))</span></span></span></code></pre></div><h3 id="gh"><code>gh</code></h3><p><em><a href="https://github.com/sigma/gh.el">gh</a> is a GitHub API library for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">gh</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:version</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">_</span><span class="p">)</span><span class="s">"2.29"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span><span class="c1">; github.com/progfolio/elpaca/issues/229</span></span></span></code></pre></div><h3 id="closql"><code>closql</code></h3><p><em><a href="https://github.com/magit/closql">closql</a> stores EIEIO objects using EmacSQL.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">closql</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"magit/closql"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="magit"><code>magit</code></h3><p><em><a href="https://github.com/magit/magit">magit</a> is a complete text-based user interface to Git.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">magit</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"magit/magit"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"main"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">magit-commit-ask-to-stage</span><span class="ss">'stage</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">magit-clone-set-remote.pushDefault</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">magit-diff-refine-hunk</span><span class="ss">'all</span><span class="p">)</span><span class="c1">; show word-granularity differences in all diff hunks</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'magit-read-rev-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'magit-no-confirm</span><span class="ss">'stage-all-changes</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">magit-status-mode-hook</span><span class="nv">magit-diff-mode-hook</span><span class="p">)</span><span class="o">.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable line truncation in Magit buffers."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">truncate-lines</span><span class="no">nil</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-g"</span><span class="o">.</span><span class="nv">magit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-g"</span><span class="o">.</span><span class="nv">magit-clone</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-log-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">magit-section-backward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">magit-section-forward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="o">.</span><span class="nv">magit-pull</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">magit-push</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-diff-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">magit-section-backward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">magit-section-forward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-hunk-section-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">magit-smerge-keep-lower</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">magit-smerge-keep-upper</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">magit-smerge-keep-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">magit-smerge-keep-base</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">magit-smerge-keep-current</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-hunk-section-smerge-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">magit-smerge-keep-lower</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">magit-smerge-keep-upper</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">magit-smerge-keep-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">magit-smerge-keep-base</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">magit-smerge-keep-current</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-status-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">magit-smerge-keep-lower</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">magit-smerge-keep-upper</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">magit-smerge-keep-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">magit-smerge-keep-base</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">magit-smerge-keep-current</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">tlon-commit-when-slug-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">magit-remote-unshallow</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">magit-section-backward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">magit-section-forward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">magit-revision-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">magit-section-backward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">magit-section-forward-sibling</span><span class="p">)))</span></span></span></code></pre></div><ul><li><a href="https://emacspeak.blogspot.com/2020/05/github-standard-fork-and-pull-request.html">EMACSPEAK The Complete Audio Desktop: GitHub Standard Fork And Pull-Request Workflow From Emacs</a></li><li>To read:<a href="https://emacsredux.com/blog/2020/12/11/super-keybindings-for-magit/">Super Keybindings for Magit | Emacs Redux</a></li></ul><h3 id="magit-extra"><code>magit-extra</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/magit-extra.el">magit-extra</a> collects my extensions for<code>magit</code>.</em></p><p>Note that this is called<code>magit-extra</code> (with no ‘s’ at the end) because Magit already provides a feature called<code>magit-extras</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">magit-extra</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">magit</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">git-commit-setup-hook</span><span class="o">.</span><span class="nv">magit-extras-move-point-to-start</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">magit-extras-with-editor-finish-and-push</span><span class="p">))</span></span></span></code></pre></div><h3 id="magit-todos"><code>magit-todos</code></h3><p><em><a href="https://github.com/alphapapa/magit-todos">magit-todos</a> displays TODOs present in project files in the Magit status buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">magit-todos</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"alphapapa/magit-todos"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">magit</span><span class="nv">hl-todo</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">magit-todos-branch-list</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">magit-todos-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="with-editor"><code>with-editor</code></h3><p><em><a href="https://github.com/magit/with-editor">with-editor</a> allows the use of Emacsclient as the $EDITOR for external programs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">with-editor</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">((</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">with-editor-finish</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">with-editor-cancel</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-c C-c"</span><span class="o">.</span><span class="nv">with-editor-finish</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ghub"><code>ghub</code></h3><p><em><a href="https://github.com/magit/ghub">ghub</a> provides basic support for using the APIs of various Git forges from Emacs packages.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ghub</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"magit/ghub"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"main"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'pass</span><span class="p">))</span></span></span></code></pre></div><h3 id="forge"><code>forge</code></h3><p><em><a href="https://github.com/magit/forge">forge</a> let&rsquo;s one work with git forges directly from Magit.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">forge</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"magit/forge"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"main"</span><span class="c1">; github.com/progfolio/elpaca/issues/342</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">magit</span><span class="nv">ghub</span><span class="nv">emacsql</span><span class="nv">auth-source-pass</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'magit-status</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'magit-status-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">forge-topic-set-assignees</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">forge-delete-comment</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">forge-edit-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">forge-browse-issue</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-I"</span><span class="o">.</span><span class="nv">forge-browse-issues</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">forge-topic-set-labels</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">forge-topic-status-set-done</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">forge-topic-set-title</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'magit</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'magit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="o">.</span><span class="nv">forge-dispatch</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-owned-accounts</span><span class="o">'</span><span class="p">((</span><span class="s">"benthamite"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-topic-list-limit</span><span class="o">'</span><span class="p">(</span><span class="mi">500</span><span class="o">.</span><span class="mi">-500</span><span class="p">))</span><span class="c1">; show closed topics only via `forge-toggle-closed-visibility'</span></span></span><span class="line"><span class="cl"><span class="c1">;; do not show inactive topics by default; keep other settings unchanged</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-status-buffer-default-topic-filters</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge--topics-spec</span><span class="nb">:type</span><span class="ss">'topic</span><span class="nb">:active</span><span class="no">nil</span><span class="nb">:state</span><span class="ss">'open</span><span class="nb">:order</span><span class="ss">'newest</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; why is this turned on by default!?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'forge-post-mode-hook</span><span class="ss">'turn-on-flyspell</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; temporarily overwrite function until idiotic error message is removed</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">forge--ghub-massage-notification</span><span class="p">(</span><span class="nv">data</span><span class="nv">githost</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">let-alist</span><span class="nv">data</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">type</span><span class="p">(</span><span class="nf">intern</span><span class="p">(</span><span class="nf">downcase</span><span class="o">.</span><span class="nv">subject.type</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">type</span><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">eq</span><span class="nv">type</span><span class="ss">'pullrequest</span><span class="p">)</span><span class="ss">'pullreq</span><span class="nv">type</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">_</span><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nf">memq</span><span class="nv">type</span><span class="o">'</span><span class="p">(</span><span class="nv">discussion</span><span class="nv">issue</span><span class="nv">pullreq</span></span></span><span class="line"><span class="cl"><span class="nv">commit</span><span class="nv">release</span><span class="nv">checksuite</span><span class="p">))</span><span class="c1">; Added checksuite</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"Forge: Ignoring unknown notification type: %s"</span><span class="nv">type</span><span class="p">)))</span><span class="c1">; Changed error to message</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">number-or-commit</span><span class="p">(</span><span class="nb">and</span><span class="o">.</span><span class="nv">subject.url</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">string-match</span><span class="s">"[^/]*\\'"</span><span class="o">.</span><span class="nv">subject.url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">match-string</span><span class="mi">0</span><span class="o">.</span><span class="nv">subject.url</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">number</span><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nf">memq</span><span class="nv">type</span><span class="o">'</span><span class="p">(</span><span class="nv">discussion</span><span class="nv">issue</span><span class="nv">pullreq</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">string-to-number</span><span class="nv">number-or-commit</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">repo</span><span class="p">(</span><span class="nv">forge-get-repository</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="nv">githost</span></span></span><span class="line"><span class="cl"><span class="o">.</span><span class="nv">repository.owner.login</span></span></span><span class="line"><span class="cl"><span class="o">.</span><span class="nv">repository.name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="no">nil</span><span class="nb">:insert!</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">repoid</span><span class="p">(</span><span class="nb">oref</span><span class="nv">repo</span><span class="nv">id</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">owner</span><span class="p">(</span><span class="nb">oref</span><span class="nv">repo</span><span class="nv">owner</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">name</span><span class="p">(</span><span class="nb">oref</span><span class="nv">repo</span><span class="nv">name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="p">(</span><span class="nv">forge--object-id</span><span class="nv">repoid</span><span class="p">(</span><span class="nf">string-to-number</span><span class="o">.</span><span class="nv">id</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alias</span><span class="p">(</span><span class="nf">intern</span><span class="p">(</span><span class="nf">concat</span><span class="s">"_"</span><span class="p">(</span><span class="nv">string-replace</span><span class="s">"="</span><span class="s">"_"</span><span class="nv">id</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">and</span><span class="nv">number</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="nv">alias</span><span class="nv">id</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="o">,</span><span class="nv">alias</span><span class="nv">repository</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">[(</span><span class="nv">name</span><span class="o">,</span><span class="nv">name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">owner</span><span class="o">,</span><span class="nv">owner</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="o">,@</span><span class="p">(</span><span class="nv">cddr</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">caddr</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ghub--graphql-prepare-query</span></span></span><span class="line"><span class="cl"><span class="nv">ghub-fetch-repository</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">pcase</span><span class="nv">type</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ss">'discussion</span><span class="o">`</span><span class="p">(</span><span class="nv">repository</span></span></span><span class="line"><span class="cl"><span class="nv">discussions</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">discussion</span><span class="o">.</span><span class="o">,</span><span class="nv">number</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ss">'issue</span><span class="o">`</span><span class="p">(</span><span class="nv">repository</span></span></span><span class="line"><span class="cl"><span class="nv">issues</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">issue</span><span class="o">.</span><span class="o">,</span><span class="nv">number</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ss">'pullreq</span><span class="o">`</span><span class="p">(</span><span class="nv">repository</span></span></span><span class="line"><span class="cl"><span class="nv">pullRequest</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pullRequest</span><span class="o">.</span><span class="o">,</span><span class="nv">number</span><span class="p">))))))))</span></span></span><span class="line"><span class="cl"><span class="nv">repo</span><span class="nv">type</span><span class="nv">data</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-issue-mode-hook</span><span class="o">.</span><span class="nv">simple-extras-visual-line-mode-enhanced</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">forge-post-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">forge-post-submit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">forge-issue-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">forge-topic-set-assignees</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">forge-delete-comment</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">forge-edit-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">forge-browse-issue</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-I"</span><span class="o">.</span><span class="nv">forge-browse-issues</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">forge-topic-set-labels</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">forge-topic-status-set-done</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">forge-topic-set-title</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">forge-notifications-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">forge-topic-set-assignees</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">forge-delete-comment</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">forge-edit-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">forge-browse-issue</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-I"</span><span class="o">.</span><span class="nv">forge-browse-issues</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">forge-topic-set-labels</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">forge-topic-status-set-done</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">forge-topic-set-title</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">forge-topic-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">forge-topic-set-assignees</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">forge-delete-comment</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">forge-edit-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">forge-browse-issue</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-I"</span><span class="o">.</span><span class="nv">forge-browse-issues</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">forge-topic-set-labels</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">forge-topic-status-set-done</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">forge-create-post</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">forge-topic-set-title</span><span class="p">)))</span></span></span></code></pre></div><h3 id="orgit"><code>orgit</code></h3><p><em><a href="https://github.com/magit/orgit">orgit</a> provides support for Org links to Magit buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">orgit</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="orgit-forge"><code>orgit-forge</code></h3><p><em><a href="https://github.com/magit/orgit-forge">orgit-forge</a> supports<code>org-mode</code> links to<code>forge</code> buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">orgit-forge</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">forge</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)))</span></span></span></code></pre></div><h3 id="forge-search"><code>forge-search</code></h3><p><em><a href="https://github.com/eatse21/forge-search.el/blob/master/forge-search.el">forge-search</a> supports searching through issues and pull requests within<code>forge</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">forge-search</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/forge-search.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"fix/forge-get-repository"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">forge</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">forge-search-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">magit-section-backward-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">magit-section-forward-sibling</span><span class="p">)))</span></span></span></code></pre></div><h3 id="forge-extras"><code>forge-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/forge-extras.el">forge-extras</a> collects my extensions for<code>forge</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">forge-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">forge</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'magit-status</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'magit-status-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">forge-extras-state-set-dwim</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-project-owner</span><span class="s">"tlon-team"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-project-number</span><span class="mi">9</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-project-node-id</span><span class="s">"PVT_kwDOBtGWf84A5jZf"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-status-field-node-id</span><span class="s">"PVTSSF_lADOBtGWf84A5jZfzguVNY8"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-estimate-field-node-id</span><span class="s">"PVTF_lADOBtGWf84A5jZfzguVNc0"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">forge-extras-status-option-ids-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"Doing"</span><span class="o">.</span><span class="s">"47fc9ee4"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Next"</span><span class="o">.</span><span class="s">"8607328f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Later"</span><span class="o">.</span><span class="s">"13e22f63"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Someday"</span><span class="o">.</span><span class="s">"4bf0f00e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Waiting"</span><span class="o">.</span><span class="s">"28097d1b"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Done"</span><span class="o">.</span><span class="s">"98236657"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'orgit-store-link</span><span class="nb">:override</span><span class="nf">#'</span><span class="nv">forge-extras-orgit-store-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'forge-visit-this-topic</span><span class="nb">:before</span><span class="nf">#'</span><span class="nv">forge-extras-sync-read-status</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="mi">30</span><span class="no">t</span><span class="nf">#'</span><span class="nv">forge-extras-pull-notifications</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">forge-issue-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-d"</span><span class="o">.</span><span class="nv">forge-previous-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">forge-next-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">forge-extras-set-project-status</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">forge-extras-copy-message-at-point-as-kill</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">forge-notifications-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">forge-extras-browse-github-inbox</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">forge-extras-state-set-dwim</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">forge-topic-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">forge-extras-state-set-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="emacs-pr-review"><code>emacs-pr-review</code></h3><p><em><a href="https://github.com/blahgeek/emacs-pr-review">emacs-pr-review</a> provides support for reviewing pull requests in Emacs.</em></p><p>See<a href="https://gitlab.com/magus/mes/-/blob/8615353ec007bd66209ee1ae3badddd26d3a3dc9/lisp/mes-dev-basics.el#L76">this config</a> for ideas.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pr-review</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">forge</span><span class="p">)</span></span></span></code></pre></div><h3 id="git-auto-commit-mode"><code>git-auto-commit-mode</code></h3><p><em><a href="https://github.com/ryuslash/git-auto-commit-mode">git-auto-commit-mode</a> allows for committing and pushing automatically after each save.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">git-auto-commit-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">recentf</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">gac-automatically-push-p</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">gac-debounce-interval</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">gac-silent-message-p</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">gac-automatically-add-new-files-p</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h2 id="display">display</h2><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">line-spacing</span><span class="mi">2</span><span class="p">)</span></span></span></code></pre></div><h3 id="fringe"><code>fringe</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/fringe.el">fringe</a> controls the thin strips at the edges of windows used for indicators.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">fringe</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">fringe-indicator-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">truncation</span><span class="no">nil</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">continuation</span><span class="no">nil</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">overlay-arrow</span><span class="o">.</span><span class="nv">right-triangle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">up</span><span class="o">.</span><span class="nv">up-arrow</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">down</span><span class="o">.</span><span class="nv">down-arrow</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">top</span><span class="nv">top-left-angle</span><span class="nv">top-right-angle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bottom</span><span class="nv">bottom-left-angle</span><span class="nv">bottom-right-angle</span><span class="nv">top-right-angle</span><span class="nv">top-left-angle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">top-bottom</span><span class="nv">left-bracket</span><span class="nv">right-bracket</span><span class="nv">top-right-angle</span><span class="nv">top-left-angle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">empty-line</span><span class="o">.</span><span class="nv">empty-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">unknown</span><span class="o">.</span><span class="nv">question-mark</span><span class="p">))))</span></span></span></code></pre></div><h3 id="faces"><code>faces</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/faces.el">faces</a> provides face definition and manipulation.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">faces</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">ns-use-thin-smoothing</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; to prevent misalignment in vtable</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">set-face-attribute</span><span class="ss">'header-line</span><span class="no">nil</span><span class="nb">:box</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><ul><li><a href="https://out-of-cheese-error.netlify.app/spacemacs-config">An Annotated Spacemacs - For an org-mode workflow ·</a></li><li><a href="https://zzamboni.org/post/beautifying-org-mode-in-emacs/">- zzamboni.org | Beautifying Org Mode in Emacs</a></li></ul><h3 id="faces-extras"><code>faces-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/faces-extras.el">faces-extras</a> collects my extensions for<code>faces</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">default</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">fixed-pitch</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">variable-pitch</span><span class="nb">:family</span><span class="nv">faces-extras-variable-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-variable-pitch-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">window-divider</span><span class="nb">:foreground</span><span class="p">(</span><span class="nv">face-attribute</span><span class="ss">'mode-line-inactive</span><span class="nb">:background</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span><span class="o">.</span><span class="nv">faces-extras-set-custom-face-attributes</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h C-f"</span><span class="o">.</span><span class="nv">faces-extras-describe-face</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-modern"><code>org-modern</code></h3><p><em><a href="https://github.com/minad/org-modern">org-modern</a> prettifies org mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-modern</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-table</span><span class="no">nil</span><span class="p">)</span><span class="c1">; doesn’t work well with variable-pitch: github.com/minad/org-modern/issues/99</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-statistics</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-star</span><span class="ss">'fold</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-fold-stars</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"▸"</span><span class="o">.</span><span class="s">"▾"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"▸"</span><span class="o">.</span><span class="s">"▾"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"▸"</span><span class="o">.</span><span class="s">"▾"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"▸"</span><span class="o">.</span><span class="s">"▾"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"▸"</span><span class="o">.</span><span class="s">"▾"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-replace-stars</span><span class="o">'</span><span class="p">(</span><span class="s">"◉"</span><span class="s">"◉"</span><span class="s">"◉"</span><span class="s">"◉"</span><span class="s">"◉"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-list</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="mi">42</span><span class="o">.</span><span class="s">"○"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="mi">43</span><span class="o">.</span><span class="s">"○"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="mi">45</span><span class="o">.</span><span class="s">"○"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">org-modern-date-active</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-date-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-date-inactive</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-date-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-tag</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-tag-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-modern-label</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-tag-height</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-org-modern-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-modern-indent"><code>org-modern-indent</code></h3><p><em><a href="https://github.com/jdtsmith/org-modern-indent">org-modern-indent</a> extends org-modern stylistic improvements to contexts involving indentation.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-modern-indent</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"jdtsmith/org-modern-indent"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-modern</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">org-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Remove the ╭│╰ bracket decoration; it renders with gaps in</span></span></span><span class="line"><span class="cl"><span class="c1">;; variable-pitch buffers because the line height exceeds the glyph height.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-modern-indent-begin</span><span class="s">" "</span></span></span><span class="line"><span class="cl"><span class="nv">org-modern-indent-guide</span><span class="s">" "</span></span></span><span class="line"><span class="cl"><span class="nv">org-modern-indent-end</span><span class="s">" "</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-indent-pixel"><code>org-indent-pixel</code></h3><p><em><a href="https://github.com/benthamite/org-indent-pixel">org-indent-pixel</a> fixes misaligned wrapped lines in<code>variable-pitch-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-indent-pixel</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"benthamite/org-indent-pixel"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-indent</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-indent-pixel-setup</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-tidy"><code>org-tidy</code></h3><p><em><a href="https://github.com/jxq0/org-tidy">org-tidy</a> hides org-mode property drawers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-tidy</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-tidy-properties-inline-symbol</span><span class="s">""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-tidy-protect-overlay</span><span class="no">nil</span><span class="p">)</span><span class="c1">; github.com/jxq0/org-tidy/issues/11</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">org-mode-hook</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-appear"><code>org-appear</code></h3><p><em><a href="https://github.com/awth13/org-appear">org-appear</a> toggles the visibility of hidden org mode element parts upon entering and leaving those elements.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-appear</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">org-mode-hook</span><span class="p">)</span></span></span></code></pre></div><h3 id="face-remap"><code>face-remap</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/face-remap.el">face-remap</a> defines simple operations for face remapping.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">face-remap</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">eww</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">elfeed-show-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">telega-webpage-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">eww-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">mu4e-view-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">outline-mode-hook</span><span class="p">)</span><span class="o">.</span><span class="nv">variable-pitch-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"+"</span><span class="o">.</span><span class="nv">text-scale-increase</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"-"</span><span class="o">.</span><span class="nv">text-scale-decrease</span><span class="p">)))</span></span></span></code></pre></div><h3 id="modus-themes"><code>modus-themes</code></h3><p><em><a href="https://protesilaos.com/emacs/modus-themes">modus-themes</a> are a pair of accessible white/dark themes for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">modus-themes</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/modus-themes"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces</span><span class="nv">faces-extras</span><span class="nv">simple-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-mixed-fonts</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">modus-themes-common-palette-overrides</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="nv">fringe</span><span class="nv">unspecified</span><span class="p">)</span><span class="c1">; hide the fringe</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bg-prose-block-delimiter</span><span class="nv">bg-inactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">fg-prose-block-delimiter</span><span class="nv">gray</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; for the rest, use the predefined intense values</span></span></span><span class="line"><span class="cl"><span class="o">,@</span><span class="nv">modus-themes-preset-overrides-intense</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-after-load-theme-hook</span><span class="o">.</span><span class="nv">faces-extras-set-custom-face-attributes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-after-load-theme-hook</span><span class="o">.</span><span class="nv">frame-extras-restore-window-divider</span><span class="p">))</span></span></span></code></pre></div><h3 id="modus-themes-extras"><code>modus-themes-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/modus-themes-extras.el">modus-themes-extras</a> collects my extensions for<code>modus-themes</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">modus-themes-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">modus-themes</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-extras-light-theme</span><span class="ss">'modus-operandi-tinted</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-extras-dark-theme</span><span class="ss">'modus-vivendi-tinted</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-override-code</span></span></span><span class="line"><span class="cl"><span class="nb">:modus-themes-load</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">modus-themes-extras-load-theme-conditionally</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-after-load-theme-hook</span><span class="o">.</span><span class="nv">modus-themes-extras-highlight-parentheses</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">modus-themes-after-load-theme-hook</span><span class="o">.</span><span class="nv">modus-themes-extras-set-faces</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-u"</span><span class="o">.</span><span class="nv">modus-themes-extras-toggle</span><span class="p">))</span></span></span></code></pre></div><h3 id="highlight-parentheses"><code>highlight-parentheses</code></h3><p><em><a href="https://sr.ht/~tsdh/highlight-parentheses.el/">highlight-parentheses</a> dynamically highlights the parentheses surrounding point based on nesting-level using configurable lists of colors, background colors, and other properties.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">highlight-parentheses</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">highlight-parentheses-delay</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-highlight-parentheses-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-setup-hook</span><span class="o">.</span><span class="nv">highlight-parentheses-minibuffer-setup</span><span class="p">))</span></span></span></code></pre></div><h3 id="spacious-padding"><code>spacious-padding</code></h3><p><em><a href="https://git.sr.ht/~protesilaos/spacious-padding">spacious-padding</a> increases the spacing of frames and windows.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">spacious-padding</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:tag</span><span class="s">"0.3.0"</span><span class="p">)</span><span class="c1">; using tagged version to avoid error on 2024-02-21</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spacious-padding-widths</span><span class="o">'</span><span class="p">())</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spacious-padding-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="emoji"><code>emoji</code></h3><p><em>emoji provides commands for emoji insertion.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emoji</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-:"</span><span class="o">.</span><span class="nv">emoji-search</span><span class="p">))</span></span></span></code></pre></div><h3 id="color"><code>color</code></h3><p><em>color is a color manipulation library.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">color</span><span class="p">)</span></span></span></code></pre></div><h3 id="color-extras"><code>color-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/color-extras.el">color-extras</a> collects my extensions for<code>color</code>.</em></p><p>Note that the loading of<code>color</code> cannot be deferred, since it is required by<code>pulse</code>. So we defer-load this package.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">color-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">color</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span><span class="p">)</span></span></span></code></pre></div><h3 id="rainbow-mode"><code>rainbow-mode</code></h3><p><em><a href="https://elpa.gnu.org/packages/rainbow-mode.html">rainbow-mode</a> colorizes strings that match color names.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">rainbow-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">color-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">rainbow-ansi-colors</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">rainbow-x-colors</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="ct"><code>ct</code></h3><p><em><a href="https://github.com/neeasade/ct.el">ct</a> is color library meant for making changes to individual colors in various color spaces.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ct</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">color-extras</span><span class="p">)</span></span></span></code></pre></div><h3 id="hsluv"><code>hsluv</code></h3><p><em><a href="https://github.com/hsluv/hsluv-emacs">hsluv</a> is a HSLuv implementation for Emacs Lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">hsluv</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">color-extras</span><span class="p">)</span></span></span></code></pre></div><h3 id="image"><code>image</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/image.el">image</a> provides image-manipulation functions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">image</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">image-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="c1">;; Use imagemagick, if available.</span></span></span><span class="line"><span class="cl"><span class="c1">;; djcbsoftware.nl/code/mu/mu4e/Viewing-images-inline.html</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">fboundp</span><span class="ss">'imagemagick-register-types</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">imagemagick-register-types</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">image-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"+"</span><span class="o">.</span><span class="nv">image-increase-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"-"</span><span class="o">.</span><span class="nv">image-decrease-size</span><span class="p">)))</span></span></span></code></pre></div><h3 id="image-mode"><code>image-mode</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/image-mode.el">image-mode</a> is a major mode for viewing images.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">image-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">image-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">dired-extras-copy-image</span><span class="p">)))</span></span></span></code></pre></div><h3 id="paren"><code>paren</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e7260d4eb3ed1bebcaa9e2b934f162d4bb42e413/lisp/paren.el#L4">paren</a> highlights matching parens.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">paren</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">show-paren-delay</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">show-paren-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="doom-modeline"><code>doom-modeline</code></h3><p><em><a href="https://github.com/seagle0128/doom-modeline/">doom-modeline</a> is a tidier and more aesthetically pleasing modeline.</em></p><p>I combine the modeline with the tab bar to display various types of information. Specifically, I use the modeline to display buffer-local information (such as the buffer major mode, line number, or word count), and the tab bar to display global information (such as the time and date, the weather, the computer’s battery status, and various notifications). This functionality is provided by a combination of the<code>=doom-modeline</code> package, the<code>tab-bar</code> feature, and my corresponding extensions (<code>doom-modeline-extras</code> and<code>tab-bar-extras</code>). In short, I move to the tab bar some of the elements that would normally be displayed in the modeline by (1)<em>enabling</em> those elements via the relevant<code>doom-modeline</code> user options, (2)<em>hiding</em> those elements via the<code>doom-modeline-def-modeline</code> macro, and (3)<em>adding</em> equivalent elements to the tab bar via the<code>tab-bar-format</code> user option.</p><p>Here’s a screenshot illustrating the modeline and tab bar in action (click to enlarge):</p><figure><a href="/ox-hugo/screenshot-config.png" target="_blank" rel="noopener"><img src="/ox-hugo/screenshot-config.png" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">doom-modeline</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-time</span><span class="no">nil</span><span class="p">)</span><span class="c1">; we display time (and date) in the tab bar</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-buffer-name</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; we display the full path in the header line via `breadcrumb'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-buffer-file-name-style</span><span class="ss">'file-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-check-simple-format</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-total-line-number</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-position-column-line-format</span><span class="o">'</span><span class="p">(</span><span class="s">" %c %l"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-enable-word-count</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-indent-info</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-github</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-github-interval</span><span class="mi">60</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-irc</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nf">cons</span><span class="o">'</span><span class="p">((</span><span class="nv">display-time-mode-hook</span><span class="o">.</span><span class="nv">doom-modeline-override-time</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-mode-hook</span><span class="o">.</span><span class="nv">doom-modeline-override-time</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="p">(</span><span class="nf">car</span><span class="nf">cons</span><span class="p">)</span><span class="p">(</span><span class="nf">cdr</span><span class="nf">cons</span><span class="p">))))</span></span></span></code></pre></div><h3 id="doom-modeline-extras"><code>doom-modeline-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/doom-modeline-extras.el">doom-modeline-extras</a> collects my extensions for<code>doom-modeline</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">doom-modeline-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">doom-modeline</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-def-modeline</span><span class="ss">'main</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">bar</span><span class="nv">workspace-name</span><span class="nv">parrot</span><span class="nv">buffer-info</span><span class="nv">modals</span><span class="nv">matches</span><span class="nv">follow</span><span class="nv">remote-host</span><span class="nv">buffer-position</span><span class="nv">tlon-paragraph</span><span class="nv">word-count</span><span class="nv">selection-info</span><span class="nv">org-roam-backlinks</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">tlon-split</span><span class="nv">compilation</span><span class="nv">objed-state</span><span class="nv">misc-info</span><span class="nv">persp-name</span><span class="nv">grip</span><span class="nv">irc</span><span class="nv">mu4e</span><span class="nv">gnus</span><span class="nv">lsp</span><span class="nv">minor-modes</span><span class="nv">input-method</span><span class="nv">indent-info</span><span class="nv">buffer-encoding</span><span class="nv">major-mode</span><span class="nv">process</span><span class="nv">vcs</span><span class="nv">check</span><span class="nv">time</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-def-modeline</span><span class="ss">'vcs</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">bar</span><span class="nv">window-number</span><span class="nv">modals</span><span class="nv">matches</span><span class="nv">buffer-info</span><span class="nv">remote-host</span><span class="nv">buffer-position</span><span class="nv">parrot</span><span class="nv">selection-info</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">compilation</span><span class="nv">misc-info</span><span class="nv">irc</span><span class="nv">mu4e</span><span class="nv">gnus</span><span class="nv">minor-modes</span><span class="nv">buffer-encoding</span><span class="nv">major-mode</span><span class="nv">process</span><span class="nv">time</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-def-modeline</span><span class="ss">'dashboard</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">bar</span><span class="nv">window-number</span><span class="nv">modals</span><span class="nv">buffer-default-directory-simple</span><span class="nv">remote-host</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">compilation</span><span class="nv">misc-info</span><span class="nv">irc</span><span class="nv">mu4e</span><span class="nv">gnus</span><span class="nv">minor-modes</span><span class="nv">input-method</span><span class="nv">major-mode</span><span class="nv">process</span><span class="nv">time</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-def-modeline</span><span class="ss">'project</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">bar</span><span class="nv">window-number</span><span class="nv">modals</span><span class="nv">buffer-default-directory</span><span class="nv">remote-host</span><span class="nv">buffer-position</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">compilation</span><span class="nv">misc-info</span><span class="nv">irc</span><span class="nv">mu4e</span><span class="nv">gnus</span><span class="nv">github</span><span class="nv">minor-modes</span><span class="nv">input-method</span><span class="nv">major-mode</span><span class="nv">process</span><span class="nv">time</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">doom-modeline-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="tab-bar"><code>tab-bar</code></h3><p><em>tab-bar displays a tab bar at the top of the frame, just below the tool bar.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">tab-bar</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-resize-tab-bars</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tab-bar-format</span><span class="o">'</span><span class="p">(</span><span class="nv">tab-bar-format-global</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="nv">mode-line-misc-info</span></span></span><span class="line"><span class="cl"><span class="c1">;; When the tab-bar is active, don't show `global-mode-string'</span></span></span><span class="line"><span class="cl"><span class="c1">;; in `mode-line-misc-info', because we now show that in the</span></span></span><span class="line"><span class="cl"><span class="c1">;; tab-bar using `tab-bar-format-global'.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove</span><span class="o">'</span><span class="p">(</span><span class="nv">global-mode-string</span><span class="p">(</span><span class="s">""</span><span class="nv">global-mode-string</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nv">mode-line-misc-info</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span></span></span><span class="line"><span class="cl"><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Set and store the tab bar attributes, then activate the tab bar."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">tab-bar</span><span class="nb">:background</span><span class="p">(</span><span class="nv">face-background</span><span class="ss">'mode-line-active</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:box</span><span class="o">`</span><span class="p">(</span><span class="nb">:line-width</span><span class="mi">6</span><span class="nb">:color</span><span class="o">,</span><span class="p">(</span><span class="nv">face-attribute</span><span class="ss">'mode-line-active</span><span class="nb">:background</span><span class="p">)</span><span class="nb">:style</span><span class="no">nil</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tab-bar-mode</span><span class="p">))))</span></span></span></code></pre></div><h3 id="tab-bar-extras"><code>tab-bar-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/tab-bar-extras.el">tab-bar-extras</a> collects my extensions for<code>tab-bar</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">tab-bar-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">tab-bar-extras-global-mode-string</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">tab-bar-extras-prefix-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-notification-status-element</span></span></span><span class="line"><span class="cl"><span class="c1">;; ,tab-bar-extras-time-element</span></span></span><span class="line"><span class="cl"><span class="c1">;; ,tab-bar-extras-separator-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-emacs-profile-element</span></span></span><span class="line"><span class="cl"><span class="c1">;; ,tab-bar-extras-separator-element</span></span></span><span class="line"><span class="cl"><span class="c1">;; ,tab-bar-extras-battery-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-telega-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-github-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-pomodoro-element</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-debug-element</span></span></span><span class="line"><span class="cl"><span class="c1">;; we add a separator at the end because `wttr' appends itself after it</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="nv">tab-bar-extras-separator-element</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span></span></span><span class="line"><span class="cl"><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Reset the tab shortly after startup to show all its elements correctly."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-timer</span><span class="mi">1</span><span class="no">nil</span><span class="nf">#'</span><span class="nv">tab-bar-extras-quick-reset</span><span class="p">))))</span></span></span></code></pre></div><h3 id="breadcrumb"><code>breadcrumb</code></h3><p><em><a href="https://github.com/joaotavora/breadcrumb/">breadcrumb</a> displays project information in the header line.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">breadcrumb</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">breadcrumb-project-max-length</span><span class="mf">0.5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">breadcrumb-project-crumb-separator</span><span class="s">"/"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">breadcrumb-imenu-max-length</span><span class="mf">1.0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">breadcrumb-imenu-crumb-separator</span><span class="s">" &gt; "</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">breadcrumb-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="battery"><code>battery</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/battery.el">battery</a> displays battery status information.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">battery</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-battery-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="nerd-icons"><code>nerd-icons</code></h3><p><em><a href="https://github.com/rainstormstudio/nerd-icons.el">nerd-icons</a> is a library for<a href="https://github.com/ryanoasis/nerd-fonts">Nerd Font</a> icons inside Emacs.</em></p><p>Note that the icons need to be installed via<code>nerd-icons-install-fonts</code>. If you want to install the icons with<code>brew</code> on macOS, run<code>brew tap homebrew/cask-fonts &amp;&amp; brew install --cask font-symbols-only-nerd-font</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">nerd-icons</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="menu-bar"><code>menu-bar</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/menu-bar.el">menu-bar</a> defines the menu bar.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">menu-bar</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span><span class="mi">-1</span><span class="p">))</span></span></span></code></pre></div><h3 id="tool-bar"><code>tool-bar</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/tool-bar.el">tool-bar</a> provides the tool bar.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">tool-bar</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span><span class="mi">-1</span><span class="p">))</span></span></span></code></pre></div><h3 id="scroll-bar"><code>scroll-bar</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/scroll-bar.el">scroll-bar</a> handles window scroll bars.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">scroll-bar</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span><span class="mi">-1</span><span class="p">))</span></span></span></code></pre></div><h3 id="pixel-scroll"><code>pixel-scroll</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/pixel-scroll.el">pixel-scroll</a> supports smooth scrolling.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">pixel-scroll</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pixel-scroll-precision-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="delsel"><code>delsel</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/delsel.el">delsel</a> deletes the selection when the user start typing.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">delsel</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">delete-selection-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="hl-line"><code>hl-line</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/hl-line.el">hl-line</a> highlights the current line.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">hl-line</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="nv">hl-line-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-reconcile-mode-hook</span><span class="o">.</span><span class="nv">hl-line-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="lin"><code>lin</code></h3><p><em><a href="https://protesilaos.com/codelog/2022-09-08-lin-1-0-0/">lin</a> is a stylistic enhancement for Emacs’ built-in<code>hl-line-mode</code>. It remaps the<code>hl-line</code> face (or equivalent) buffer-locally to a style optimal for major modes where line selection is the primary mode of interaction.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">lin</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lin-face</span><span class="ss">'lin-blue</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lin-mode-hooks</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">dired-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">elfeed-search-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">git-rebase-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">grep-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">ibuffer-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">ilist-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">ledger-report-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">log-view-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">magit-log-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">mu4e-headers-mode</span></span></span><span class="line"><span class="cl"><span class="nv">occur-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">org-agenda-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">pdf-outline-buffer-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">proced-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">tabulated-list-mode-hook</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span><span class="o">.</span><span class="nv">lin-global-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="jit-lock"><code>jit-lock</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/jit-lock.el">jit-lock</a> provides just-in-time fontification.</em></p><p>I have<a href="https://emacs.stackexchange.com/questions/72417/face-properties-fail-to-apply-to-parts-of-org-mode-buffer/72439#72439">noticed</a> that Emacs will sometimes fail to fontify parts of a buffer. This problem is solved, in my experience, by increasing the value of the user option<code>jit-lock-chunk-size</code>. Its docstring says that “The optimum value is a little over the typical number of buffer characters which fit in a typical window”, so we set its value dynamically by multiplying the number of lines per window by the number of characters per line, doubling that for safety.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">jit-lock</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">jit-lock-chunk-size</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">*</span><span class="p">(</span><span class="nv">window-max-chars-per-line</span><span class="p">)</span><span class="p">(</span><span class="nf">window-body-height</span><span class="p">)</span><span class="mi">2</span><span class="p">)))</span></span></span></code></pre></div><h2 id="text-movement">text movement</h2><h3 id="words">words</h3><p><em>Keybindings for word-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-p"</span><span class="o">.</span><span class="nf">forward-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-u"</span><span class="o">.</span><span class="nv">backward-word</span><span class="p">)))</span></span></span></code></pre></div><h3 id="lines">lines</h3><p><em>Keybindings for line-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:commands</span><span class="nv">next-line</span><span class="nv">previous-line</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'em-hist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">eshell-hist-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;up&gt;"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;down&gt;"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'cus-edit</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">custom-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ebib</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'elfeed</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'elisp-refs</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">elisp-refs-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'eww</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'forge-notify</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">forge-notifications-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'help</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">help-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'helpful</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">helpful-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'info</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">Info-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'johnson</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'johnson-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ledger-reconcile</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ledger-reconcile-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'Man</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">Man-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'mu4e</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">mu4e-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'org-lint</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">org-lint--report-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'osa-chrome</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">osa-chrome-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pass</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pass-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'simple</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">special-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'slack</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">slack-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'slack</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">slack-activity-feed-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'wasabi</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">wasabi-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-m"</span><span class="o">.</span><span class="nv">move-beginning-of-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-/"</span><span class="o">.</span><span class="nv">move-end-of-line</span><span class="p">)))</span></span></span></code></pre></div><h3 id="sentences">sentences</h3><p><em>Keybindings for sentence-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-i"</span><span class="o">.</span><span class="nv">backward-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-o"</span><span class="o">.</span><span class="nv">forward-sentence</span><span class="p">)))</span></span></span></code></pre></div><h3 id="paragraphs">paragraphs</h3><p><em>Keybindings for paragraph-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-,"</span><span class="o">.</span><span class="nv">backward-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-."</span><span class="o">.</span><span class="nv">forward-paragraph</span><span class="p">)))</span></span></span></code></pre></div><h3 id="sexps">sexps</h3><p><em>Keybindings for sexp-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-e"</span><span class="o">.</span><span class="nv">backward-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-s-d"</span><span class="o">.</span><span class="nv">forward-sexp</span><span class="p">)</span><span class="c1">; nonstandard binding because otherwise intercepted by OSX</span></span></span><span class="line"><span class="cl"><span class="p">))</span></span></span></code></pre></div><h3 id="defuns">defuns</h3><p><em>Keybindings for defun-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-w"</span><span class="o">.</span><span class="nv">beginning-of-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-s"</span><span class="o">.</span><span class="nv">end-of-defun</span><span class="p">)))</span></span></span></code></pre></div><h3 id="buffers">buffers</h3><p><em>Keybindings for buffer-level movement.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-s-SPC"</span><span class="o">.</span><span class="nv">beginning-of-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-&lt;tab&gt;"</span><span class="o">.</span><span class="nv">end-of-buffer</span><span class="p">)))</span></span></span></code></pre></div><h2 id="text-manipulation">text manipulation</h2><h3 id="simple"><code>simple</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/simple.el">simple</a> configures the kill ring, transposing, and text manipulation commands.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">kill-ring-max</span><span class="mi">99999</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">save-interprogram-paste-before-kill</span><span class="no">t</span><span class="p">)</span><span class="c1">; add system clipboard to kill ring</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-save-interval</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-M-d"</span><span class="o">.</span><span class="nv">transpose-chars</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-e"</span><span class="o">.</span><span class="nv">transpose-sentences</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-f"</span><span class="o">.</span><span class="nv">transpose-sexps</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-r"</span><span class="o">.</span><span class="nv">transpose-words</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-v"</span><span class="o">.</span><span class="nv">transpose-lines</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-&lt;delete&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-="</span><span class="o">.</span><span class="nv">overwrite-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-a"</span><span class="o">.</span><span class="nv">backward-kill-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-d"</span><span class="o">.</span><span class="nv">delete-forward-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-e"</span><span class="o">.</span><span class="nv">kill-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-f"</span><span class="o">.</span><span class="nv">kill-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-f"</span><span class="o">.</span><span class="nv">zap-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-g"</span><span class="o">.</span><span class="nv">append-next-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-q"</span><span class="o">.</span><span class="nv">backward-kill-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-r"</span><span class="o">.</span><span class="nv">kill-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s"</span><span class="o">.</span><span class="nv">delete-backward-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-SPC"</span><span class="o">.</span><span class="nv">cycle-spacing</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-v"</span><span class="o">.</span><span class="nv">kill-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-w"</span><span class="o">.</span><span class="nv">backward-kill-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-z"</span><span class="o">.</span><span class="nv">crux-kill-line-backwards</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-M-&lt;backspace&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-M-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-v"</span><span class="o">.</span><span class="nv">yank</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-DEL"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-C"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="simple-extras"><code>simple-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/simple-extras.el">simple-extras</a> collects my extensions for<code>simple</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">simple-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-H-a"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-f"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-a"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-a"</span><span class="o">.</span><span class="nv">simple-extras-backward-zap-delete-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-e"</span><span class="o">.</span><span class="nv">simple-extras-delete-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-f"</span><span class="o">.</span><span class="nv">simple-extras-delete-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-f"</span><span class="o">.</span><span class="nv">simple-extras-zap-delete-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-q"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-r"</span><span class="o">.</span><span class="nv">simple-extras-delete-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-v"</span><span class="o">.</span><span class="nv">simple-extras-delete-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-w"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-z"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-c"</span><span class="o">.</span><span class="nv">simple-extras-count-words-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-e"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-i"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-m"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-r"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-u"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-v"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-w"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-z"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-a"</span><span class="o">.</span><span class="nv">simple-extras-transpose-sexps-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-q"</span><span class="o">.</span><span class="nv">simple-extras-transpose-words-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-s"</span><span class="o">.</span><span class="nv">simple-extras-transpose-chars-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-s-9"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-word</span><span class="p">)</span><span class="c1">; `.-q'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-w"</span><span class="o">.</span><span class="nv">simple-extras-transpose-sentences-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-z"</span><span class="o">.</span><span class="nv">simple-extras-transpose-lines-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-f"</span><span class="o">.</span><span class="nv">simple-extras-fill-or-unfill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-g"</span><span class="o">.</span><span class="nv">simple-extras-keyboard-quit-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-a"</span><span class="o">.</span><span class="nv">simple-extras-backward-zap-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-b"</span><span class="o">.</span><span class="nv">simple-extras-strip-thing-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-a"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-a"</span><span class="o">.</span><span class="nv">simple-extras-backward-zap-copy-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-e"</span><span class="o">.</span><span class="nv">simple-extras-copy-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-f"</span><span class="o">.</span><span class="nv">simple-extras-copy-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-f"</span><span class="o">.</span><span class="nv">simple-extras-zap-copy-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-q"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-r"</span><span class="o">.</span><span class="nv">simple-extras-copy-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-v"</span><span class="o">.</span><span class="nv">simple-extras-copy-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-w"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-z"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-v"</span><span class="o">.</span><span class="nv">simple-extras-paste-no-properties</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-w"</span><span class="o">.</span><span class="nv">simple-extras-narrow-or-widen-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-A-v"</span><span class="o">.</span><span class="nv">simple-extras-yank-and-pop</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">simple-extras-smart-copy-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-M"</span><span class="o">.</span><span class="nv">simple-extras-exchange-point-and-mark</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-X"</span><span class="o">.</span><span class="nv">simple-extras-smart-delete-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-x"</span><span class="o">.</span><span class="nv">simple-extras-smart-kill-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-A-i"</span><span class="o">.</span><span class="nv">simple-extras-visual-line-mode-enhanced</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-i"</span><span class="o">.</span><span class="nv">simple-extras-indent-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-q"</span><span class="o">.</span><span class="nv">simple-extras-keyboard-quit-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-v"</span><span class="o">.</span><span class="nv">simple-extras-visible-mode-enhanced</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">isearch-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-w"</span><span class="o">.</span><span class="nv">simple-extras-narrow-or-widen-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="paragraphs"><code>paragraphs</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/textmodes/paragraphs.el">paragraphs</a> configures paragraph manipulation, including sentence-end and paragraph keybindings.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">emacs</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:commands</span><span class="nv">kill-paragraph</span><span class="nv">transpose-paragraphs</span><span class="nv">backward-kill-paragraph</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">sentence-end-double-space</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'text-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">text-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-c"</span><span class="o">.</span><span class="nv">kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-x"</span><span class="o">.</span><span class="nv">backward-kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-c"</span><span class="o">.</span><span class="nv">simple-extras-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-x"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-,"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-c"</span><span class="o">.</span><span class="nv">transpose-paragraphs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-x"</span><span class="o">.</span><span class="nv">simple-extras-transpose-paragraphs-backward</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'org</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-c"</span><span class="o">.</span><span class="nv">kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-x"</span><span class="o">.</span><span class="nv">backward-kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-c"</span><span class="o">.</span><span class="nv">simple-extras-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-x"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-,"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-c"</span><span class="o">.</span><span class="nv">transpose-paragraphs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-x"</span><span class="o">.</span><span class="nv">simple-extras-transpose-paragraphs-backward</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'outline</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">outline-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-c"</span><span class="o">.</span><span class="nv">kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-x"</span><span class="o">.</span><span class="nv">backward-kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-c"</span><span class="o">.</span><span class="nv">simple-extras-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-x"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-,"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-c"</span><span class="o">.</span><span class="nv">transpose-paragraphs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-x"</span><span class="o">.</span><span class="nv">simple-extras-transpose-paragraphs-backward</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'telega</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">telega-chat-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-c"</span><span class="o">.</span><span class="nv">kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-x"</span><span class="o">.</span><span class="nv">backward-kill-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-M-S-s-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-delete-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-c"</span><span class="o">.</span><span class="nv">simple-extras-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-A-x"</span><span class="o">.</span><span class="nv">simple-extras-backward-copy-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-c"</span><span class="o">.</span><span class="nv">simple-extras-delete-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-x"</span><span class="o">.</span><span class="nv">simple-extras-copy-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-,"</span><span class="o">.</span><span class="nv">simple-extras-kill-whole-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-c"</span><span class="o">.</span><span class="nv">transpose-paragraphs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-x"</span><span class="o">.</span><span class="nv">simple-extras-transpose-paragraphs-backward</span><span class="p">))))</span></span></span></code></pre></div><h2 id="editing">editing</h2><h3 id="simple"><code>simple</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/simple.el">simple</a> configures general editing behavior, including selection, indentation, and case conversion.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shift-select-mode</span><span class="no">nil</span><span class="p">)</span><span class="c1">; Shift keys do not activate the mark momentarily.</span></span></span><span class="line"><span class="cl"><span class="c1">;; hide commands in M-x which do not apply to the current mode.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">read-extended-command-predicate</span><span class="nf">#'</span><span class="nv">command-completion-default-include-p</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-expression-print-level</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-expression-print-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">print-level</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">print-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">truncate-partial-width-windows</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tab-always-indent</span><span class="ss">'complete</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">fill-column</span><span class="mi">80</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">column-number-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-e"</span><span class="o">.</span><span class="nv">eval-last-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-C"</span><span class="o">.</span><span class="nv">kill-ring-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-m"</span><span class="o">.</span><span class="nv">set-mark-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-Z"</span><span class="o">.</span><span class="nv">undo-redo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-o"</span><span class="o">.</span><span class="nv">downcase-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-u"</span><span class="o">.</span><span class="nv">capitalize-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-u"</span><span class="o">.</span><span class="nv">upcase-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-w"</span><span class="o">.</span><span class="nv">count-words-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-z"</span><span class="o">.</span><span class="nv">undo-only</span><span class="p">)))</span></span></span></code></pre></div><h3 id="rect"><code>rect</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/rect.el">rect</a> provides commands for operating on rectangular regions of text.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">rect</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="s">"C-x r w"</span><span class="o">.</span><span class="nv">copy-rectangle-as-kill</span><span class="p">))</span></span></span></code></pre></div><h3 id="repeat"><code>repeat</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/repeat.el">repeat</a> provides commands for repeating the previous command.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">repeat</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-r"</span><span class="o">.</span><span class="nv">repeat</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-r"</span><span class="o">.</span><span class="nv">repeat-complex-command</span><span class="p">)))</span></span></span></code></pre></div><h3 id="view"><code>view</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/view.el">view</a> provides a minor mode for viewing files without editing them.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">view</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-A-v"</span><span class="o">.</span><span class="nv">view-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="sort"><code>sort</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/sort.el">sort</a> provides commands for sorting text in a buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nf">sort</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">sort-fold-case</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-t"</span><span class="o">.</span><span class="nv">sort-lines</span><span class="p">))</span></span></span></code></pre></div><h3 id="vundo"><code>vundo</code></h3><p><em><a href="https://github.com/casouri/vundo">vundo</a> displays the undo history as a tree.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">vundo</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">undo-limit</span><span class="p">(</span><span class="nf">*</span><span class="mi">100</span><span class="mi">1000</span><span class="mi">1000</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">undo-strong-limit</span><span class="nv">undo-limit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">undo-outer-limit</span><span class="nv">undo-limit</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-z"</span><span class="o">.</span><span class="nv">vundo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">vundo-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">vundo-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">vundo-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">vundo-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">vundo-next</span><span class="p">)))</span></span></span></code></pre></div><h3 id="outline"><code>outline</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/outline.el">outline</a> provides selective display of portions of a buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">outline</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prog-mode-hook</span><span class="o">.</span><span class="nv">outline-minor-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">outline-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="nv">outline-cycle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">outline-cycle-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">outline-previous-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">outline-next-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-a"</span><span class="o">.</span><span class="nv">outline-extras-promote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-s"</span><span class="o">.</span><span class="nv">outline-move-subtree-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-d"</span><span class="o">.</span><span class="nv">outline-move-subtree-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-f"</span><span class="o">.</span><span class="nv">outline-extras-demote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-q"</span><span class="o">.</span><span class="nv">outline-promote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-r"</span><span class="o">.</span><span class="nv">outline-demote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">outline-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="nv">outline-cycle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">outline-cycle-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">outline-previous-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">outline-next-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-a"</span><span class="o">.</span><span class="nv">outline-extras-promote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-s"</span><span class="o">.</span><span class="nv">outline-move-subtree-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-d"</span><span class="o">.</span><span class="nv">outline-move-subtree-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-f"</span><span class="o">.</span><span class="nv">outline-extras-demote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-q"</span><span class="o">.</span><span class="nv">outline-promote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-r"</span><span class="o">.</span><span class="nv">outline-demote</span><span class="p">)))</span></span></span></code></pre></div><h3 id="outline-extras"><code>outline-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/outline-extras.el">outline-extras</a> collects my extensions for<code>outline</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">outline-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">outline</span><span class="p">)</span></span></span></code></pre></div><h3 id="outli"><code>outli</code></h3><p><em><a href="https://github.com/jdtsmith/outli">outli</a> is a simple comment-based outliner for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">outli</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"jdtsmith/outli"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">outline</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">outli-speed-commands</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"Outline navigation"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">outline-previous-visible-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">outline-forward-same-level</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">outline-backward-same-level</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">outline-next-visible-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">outline-up-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">consult-imenu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Outline structure editing"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">outline-promote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">outline-extras-promote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">outline-move-subtree-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">outline-move-subtree-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">outline-extras-demote-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">outline-demote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Outline visibility"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="nv">outline-cycle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">outline-cycle-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">outli-toggle-narrow-to-subtree</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Regular editing"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">undo-only</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="nv">yank</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Other"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"?"</span><span class="o">.</span><span class="nv">outli-speed-command-help</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">emacs-lisp-mode-hook</span><span class="p">)</span></span></span></code></pre></div><h3 id="thingatpt"><code>thingatpt</code></h3><p><em>thingatpt gets the “thing” at point.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">thingatpt</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="c1">;; we redefine `thing-at-point-url-path-regexp' to support Japanese URLs</span></span></span><span class="line"><span class="cl"><span class="c1">;; *after* `goto-addr' is loaded, so that `goto-address-url-regexp', which is</span></span></span><span class="line"><span class="cl"><span class="c1">;; defined in reference to that user option, inherits the redefinition</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'goto-addr</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">thing-at-point-url-path-regexp</span><span class="s">"[^]\t\n \"'&lt;&gt;[^`{}、。！？]*[^]\t\n \"'&lt;&gt;[^`{}.,;、。！？]+"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="abbrev"><code>abbrev</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/abbrev.el">abbrev</a> provides automatic expansion of abbreviations as you type.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">abbrev</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">save-abbrevs</span><span class="ss">'silently</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">abbrev-file-name</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-abbrev</span><span class="s">"abbrev_defs"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">abbrev-mode</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; do not look up abbrevs with case folding; e.g. `EA' will not expand an `ea' abbrev</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">abbrev-table-put</span><span class="nv">global-abbrev-table</span><span class="nb">:case-fixed</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">abbrev-table-put</span><span class="nv">text-mode-abbrev-table</span><span class="nb">:case-fixed</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="abbrev-extras"><code>abbrev-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/abbrev-extras.el">abbrev-extras</a> collects my extensions for<code>abbrev</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">abbrev-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">abbrev</span><span class="p">)</span></span></span></code></pre></div><h3 id="yasnippet"><code>yasnippet</code></h3><p><em><a href="https://github.com/joaotavora/yasnippet">yasnippet</a> is a template system for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">yasnippet</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">yas-snippet-dirs</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-dir-yasnippets</span></span></span><span class="line"><span class="cl"><span class="nv">paths-dir-yasnippets-private</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">elpaca-builds-directory</span><span class="s">"yasnippet-snippets/snippets/"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">yas-triggers-in-field</span><span class="no">t</span><span class="p">)</span><span class="c1">; allow stacked expansions</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">yas-new-snippet-default</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">format</span><span class="s">"# -*- mode: snippet -*-\n# name: $1\n# key: $2\n# contributor: %s\n# --\n$0"</span><span class="nf">user-full-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Dropbox's file provider can leave snippet files as online-only</span></span></span><span class="line"><span class="cl"><span class="c1">;; placeholders, causing `file-error' "Operation canceled" when</span></span></span><span class="line"><span class="cl"><span class="c1">;; yasnippet tries to read them. Catch the error so that loading</span></span></span><span class="line"><span class="cl"><span class="c1">;; one unavailable file does not prevent the mode from activating.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'yas--load-directory-2</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">fn</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">condition-case</span><span class="nv">err</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">fn</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-error</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"yasnippet: skipping unreadable directory %s: %s"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">car</span><span class="nv">args</span><span class="p">)</span><span class="p">(</span><span class="nf">error-message-string</span><span class="nv">err</span><span class="p">))))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">yas-global-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-setup-hook</span><span class="o">.</span><span class="nv">yas-minor-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-y"</span><span class="o">.</span><span class="nv">yas-new-snippet</span><span class="p">))</span></span></span></code></pre></div><h3 id="yasnippet-snippets"><code>yasnippet-snippets</code></h3><p><em><a href="https://github.com/AndreaCrotti/yasnippet-snippets">yasnippet-snippets</a> is a public repository of yasnippet snippets.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">yasnippet-snippets</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">yasnippet</span><span class="p">)</span></span></span></code></pre></div><h3 id="expand-region"><code>expand-region</code></h3><p><em><a href="https://github.com/magnars/expand-region.el">expand-region</a> incrementally selects regions by semantic units.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">expand-region</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-s-n"</span><span class="o">.</span><span class="nv">er/expand-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-h"</span><span class="o">.</span><span class="nv">er/contract-region</span><span class="p">)))</span></span></span></code></pre></div><h3 id="newcomment"><code>newcomment</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/newcomment.el">newcomment</a> provides commands for commenting and uncommenting code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">newcomment</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-/"</span><span class="o">.</span><span class="nv">comment-line</span><span class="p">))</span></span></span></code></pre></div><h3 id="skeleton"><code>skeleton</code></h3><p><em>skeleton provides a concise language extension for writing structured statement skeleton insertion commands for programming modes.</em></p><p>The code block below specifies how certain characters should be paired either globally or in specific modes.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">skeleton</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">skeleton-pair</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'telega</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">telega-chat-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"~"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"="</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'markdown-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"*"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"`"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'forge</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">forge-post-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"*"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"`"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">markdown-mode-hook</span><span class="nv">forge-post-mode-hook</span><span class="p">)</span><span class="o">.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Use two backticks, rather than ` and ', in selected modes."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-local</span><span class="nv">skeleton-pair-alist</span><span class="o">'</span><span class="p">((</span><span class="sc">?`</span><span class="nv">_</span><span class="sc">?`</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"["</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"{"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"("</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"\""</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"«"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"~"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"="</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">emacs-lisp-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"`"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">lisp-interaction-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"`"</span><span class="o">.</span><span class="nv">skeleton-pair-insert-maybe</span><span class="p">)))</span></span></span></code></pre></div><h3 id="crux"><code>crux</code></h3><p><em><a href="https://github.com/bbatsov/crux">crux</a> is a “collection of ridiculously useful extensions”.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">crux</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">crux-smart-open-line-before</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Insert an empty line before the current line."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">crux-smart-open-line</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">crux-smart-open-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-A-l"</span><span class="o">.</span><span class="nv">crux-smart-open-line-before</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-l"</span><span class="o">.</span><span class="nv">crux-duplicate-current-line-or-region</span><span class="p">)))</span></span></span></code></pre></div><h3 id="button"><code>button</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/button.el">button</a> defines functions for inserting and manipulating clickable buttons in Emacs buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">button</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">telega</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-C-M-s-j"</span><span class="o">.</span><span class="nv">backward-button</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-M-s-;"</span><span class="o">.</span><span class="nv">forward-button</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-chat-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-RET"</span><span class="o">.</span><span class="nv">push-button</span><span class="p">)))</span></span></span></code></pre></div><h3 id="back-button"><code>back-button</code></h3><p><em><a href="https://github.com/rolandwalker/back-button">back-button</a> supports navigating the mark ring forward and backward.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">back-button</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">back-button-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-,"</span><span class="o">.</span><span class="nv">back-button-local-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-."</span><span class="o">.</span><span class="nv">back-button-local-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-&lt;"</span><span class="o">.</span><span class="nv">back-button-global-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-&gt;"</span><span class="o">.</span><span class="nv">back-button-global-forward</span><span class="p">)))</span></span></span></code></pre></div><h3 id="goto-last-change"><code>goto-last-change</code></h3><p><em><a href="https://github.com/camdez/goto-last-change.el">goto-last-change</a> moves point through buffer-undo-list positions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">goto-last-change</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-z"</span><span class="o">.</span><span class="nv">goto-last-change</span><span class="p">))</span></span></span></code></pre></div><h3 id="goto-addr"><code>goto-addr</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/net/goto-addr.el">goto-addr</a> activates URLs and e-mail addresses in buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">goto-addr</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-goto-address-mode</span><span class="p">))</span></span></span></code></pre></div><h2 id="registers-and-bookmarks">registers &amp; bookmarks</h2><h3 id="register"><code>register</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/register.el">register</a> saves text, rectangles, positions, and other things for later use.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">register</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">savehist</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'register-alist</span><span class="p">)))</span></span></span></code></pre></div><h3 id="register-extras"><code>register-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/register-extras.el">register-extras</a> collects my extensions for<code>register</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">register-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-r"</span><span class="o">.</span><span class="nv">register-extras-dispatch</span><span class="p">))</span></span></span></code></pre></div><h3 id="bookmark"><code>bookmark</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/bookmark.el">bookmark</a> provides a system for recording and jumping to named positions in files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">bookmark</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bookmark-default-file</span><span class="nv">paths-file-bookmarks</span><span class="p">)</span><span class="c1">; Set location of bookmarks file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bookmark-save-flag</span><span class="mi">1</span><span class="p">))</span><span class="c1">; Save bookmarks after each entry</span></span></span></code></pre></div><h2 id="files-and-buffers">files &amp; buffers</h2><h3 id="files"><code>files</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/files.el">files</a> provides core commands for visiting, saving, and managing files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">files</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">savehist</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">confirm-kill-processes</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not prompt to kill running processes when quitting Emacs</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">delete-by-moving-to-trash</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">trash-directory</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="s">"~"</span><span class="s">".Trash"</span><span class="p">)))</span><span class="c1">; fallback for `move-file-to-trash'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remote-file-name-inhibit-delete-by-moving-to-trash</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remote-file-name-inhibit-auto-save</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">find-file-visit-truename</span><span class="no">t</span><span class="p">)</span><span class="c1">; emacs.stackexchange.com/questions/14509/kill-process-buffer-without-confirmation</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">create-lockfiles</span><span class="no">nil</span><span class="p">)</span><span class="c1">; lockfiles are indexed by `org-roam', which causes problems with `org-agenda'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">large-file-warning-threshold</span><span class="p">(</span><span class="nf">*</span><span class="mi">200</span><span class="mi">1000</span><span class="mi">1000</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">enable-local-variables</span><span class="nb">:all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">insert-directory-program</span><span class="s">"/opt/homebrew/bin/gls"</span><span class="p">)</span><span class="c1">; use coreutils to avoid 'listing directory failed' error</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-save-no-message</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">delete-old-versions</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">make-backup-files</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">version-control</span><span class="ss">'never</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-save-visited-interval</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">require-final-newline</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">revert-without-query</span><span class="o">'</span><span class="p">(</span><span class="s">".*"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">kill-buffer-query-functions</span><span class="no">nil</span><span class="p">)</span><span class="c1">; not a customizable variable</span></span></span><span class="line"><span class="cl"><span class="c1">;; we enable `auto-save-visited-mode' globally...</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-save-visited-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; ...but then we disable it for all buffers</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">auto-save-visited-mode</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; so that we can then re-enable it for specific buffers via a file-local variable:</span></span></span><span class="line"><span class="cl"><span class="c1">;; # Local Variables:</span></span></span><span class="line"><span class="cl"><span class="c1">;; # eval: (setq-local auto-save-visited-mode t)</span></span></span><span class="line"><span class="cl"><span class="c1">;; # End:</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'recover-session</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable</span><span class="ss">`dired-hide-details-mode'</span><span class="s"> to show dates in</span><span class="ss">`recover-session'</span><span class="s">."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-hide-details-mode</span><span class="mi">-1</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'file-name-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'auto-mode-alist</span><span class="o">'</span><span class="p">(</span><span class="s">"\\.mdx\\'"</span><span class="o">.</span><span class="nv">markdown-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'safe-local-eval-forms</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'after-save-hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'ox-texinfo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">inhibit-message</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-texinfo-export-to-texinfo</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="no">nil</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M--"</span><span class="o">.</span><span class="nv">not-modified</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-a"</span><span class="o">.</span><span class="nv">mark-whole-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s"</span><span class="o">.</span><span class="nv">save-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-b"</span><span class="o">.</span><span class="nv">clone-indirect-buffer-other-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-C-g"</span><span class="o">.</span><span class="nf">abort-recursive-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-C-S-g"</span><span class="o">.</span><span class="nf">top-level</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-C-A-g"</span><span class="o">.</span><span class="nv">keyboard-escape-quit</span><span class="p">)))</span><span class="c1">; ESC ESC ESC</span></span></span></code></pre></div><h3 id="files-extras"><code>files-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/files-extras.el">files-extras</a> collects my extensions for<code>files</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">files-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-;"</span><span class="o">.</span><span class="nv">files-extras-copy-current-path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-f"</span><span class="o">.</span><span class="nv">files-extras-dispatch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-b"</span><span class="o">.</span><span class="nv">files-extras-save-and-revert-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-e"</span><span class="o">.</span><span class="nv">files-extras-eval-region-or-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-s-q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer-switch-to-other-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-q"</span><span class="o">.</span><span class="nv">files-extras-kill-other-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-n"</span><span class="o">.</span><span class="nv">files-extras-new-empty-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-n"</span><span class="o">.</span><span class="nv">files-extras-new-buffer-in-current-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-S"</span><span class="o">.</span><span class="nv">files-extras-save-all-buffers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-s-SPC"</span><span class="o">.</span><span class="nv">files-extras-switch-to-alternate-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-v"</span><span class="o">.</span><span class="nv">files-extras-internet-archive-dwim</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'Info</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">Info-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'apropos</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">apropos-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'calendar</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">calendar-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'completion-list</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">completion-list-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'dired</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">files-extras-ocr-pdf</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ebib</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="nv">files-extras-internet-archive-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-bury-buffer-switch-to-other-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-bury-buffer-switch-to-other-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'elfeed</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'finder</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">finder-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="c1">;; We typically enter these modes to lookup some information and</span></span></span><span class="line"><span class="cl"><span class="c1">;; then return to the previous buffer, so we set `q' to switch to</span></span></span><span class="line"><span class="cl"><span class="c1">;; the other window, and reserve `Q' for the normal behavior</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'help</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">help-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer-switch-to-other-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'helpful</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">helpful-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer-switch-to-other-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ledger-reconcile</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ledger-reconcile-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'markdown-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">files-extras-grammarly-open-in-external-editor</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">gfm-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">files-extras-grammarly-open-in-external-editor</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'mu4e</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">mu4e-headers-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pass</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pass-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-view</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">files-extras-ocr-pdf</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'simple</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">messages-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-bury-buffer-switch-to-other-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'slack</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">slack-activity-feed-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">slack-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">slack-thread-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'special</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">special-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'telega</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">telega-root-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-bury-buffer-switch-to-other-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'tetris</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">tetris-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'view</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">))))</span></span></span></code></pre></div><h3 id="locate"><code>locate</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/locate.el">locate</a> provides an interface for finding files using a locate database.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">locate</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">consult</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">locate-command</span><span class="s">"mdfind"</span><span class="p">))</span><span class="c1">; use the OSX Spotlight backend</span></span></span></code></pre></div><h3 id="autorevert"><code>autorevert</code></h3><p><em>autorevert automatically reverts buffers when their files change on disk.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">autorevert</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-revert-use-notify</span><span class="no">nil</span><span class="p">)</span><span class="c1">; reddit.com/r/emacs/comments/mq2znn/comment/gugo0n4/</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auto-revert-verbose</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">find-file-hook</span><span class="o">.</span><span class="nv">global-auto-revert-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="dired"><code>dired</code></h3><p><em>dired is the Emacs directory editor.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-annot</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">pdf-annot-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">dired-jump</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-listing-switches</span><span class="s">"-AGFhlv --group-directories-first --time-style=long-iso"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-auto-revert-buffer</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-recursive-copies</span><span class="ss">'always</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-recursive-deletes</span><span class="ss">'always</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-no-confirm</span><span class="no">t</span><span class="p">)</span><span class="c1">; never ask for confirmation</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-dwim-target</span><span class="no">t</span><span class="p">)</span><span class="c1">; if Dired buffer in other window, use that buffer's current directory as target</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-vc-rename-file</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-do-revert-buffer</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-create-destination-dirs</span><span class="ss">'ask</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-guess-shell-alist-user</span><span class="o">'</span><span class="p">((</span><span class="s">""</span><span class="s">"open"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">dired-deletion-confirmer</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">x</span><span class="p">)</span><span class="no">t</span><span class="p">))</span><span class="c1">; not a customizable variable</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">put</span><span class="ss">'dired-find-alternate-file</span><span class="ss">'disabled</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not disable dired-find-alternate-file!</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="nv">dired-hide-details-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">visual-line-mode</span><span class="mi">-1</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="nv">dired-extras-subtree-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">dired-do-rename</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">dired-find-alternate-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">dired-do-copy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">dired-isearch-filenames</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"J"</span><span class="o">.</span><span class="nv">dired-jump-other-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">browse-url-extras-of-dired-file-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-extras-dired-find-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">dired-previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">dired-next-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">dired-toggle-read-only</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-z"</span><span class="o">.</span><span class="nv">dired-undo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">dired-prev-dirline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">dired-next-dirline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-,"</span><span class="o">.</span><span class="nv">dired-prev-marked-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-."</span><span class="o">.</span><span class="nv">dired-next-marked-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-o"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="dired-x"><code>dired-x</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/dired-x.el">dired-x</a> provides extra Dired functionality.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">dired-x</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-omit-verbose</span><span class="no">nil</span><span class="p">)</span><span class="c1">; shut up</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-omit-size-limit</span><span class="no">nil</span><span class="p">)</span><span class="c1">; always omit, regardless of directory size</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">dired-omit-files</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="nv">dired-omit-files</span><span class="s">"\\|^.localized$\\|^\\.DS_Store$\\|^\\.pdf-view-restore\\|^Icon\\\015"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="nv">dired-omit-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="dired-extras"><code>dired-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/dired-extras.el">dired-extras</a> collects my extensions for<code>dired</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">dired-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nb">require</span><span class="ss">'dired-extras</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-d"</span><span class="o">.</span><span class="nv">dired-extras-dispatch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">dired-extras-up-directory-reuse</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"-"</span><span class="o">.</span><span class="nv">dired-extras-hide-details-mode-enhanced</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-."</span><span class="o">.</span><span class="nv">dired-extras-dotfiles-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">dired-extras-copy-filename-as-kill-absolute</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">dired-extras-copy-filename-as-kill-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"W"</span><span class="o">.</span><span class="nv">dired-extras-copy-filename-as-kill-sans-extension</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">dired-extras-mark-screenshots</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">dired-extras-sort-toggle-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">dired-extras-do-delete-fast</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">dired-extras-copy-to-remote-docs-directory</span><span class="p">)))</span></span></span></code></pre></div><h3 id="dired-aux"><code>dired-aux</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/dired-aux.el">dired-aux</a> provides auxiliary Dired functions for file operations like compression and diffing.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">dired-aux</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired-x</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; with `unar' installed, `Z' uncompresses `rar' files</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="s">"\\.rar\\'"</span><span class="s">""</span><span class="s">"unar"</span><span class="p">)</span><span class="nv">dired-compress-file-suffixes</span><span class="p">))</span></span></span></code></pre></div><h3 id="dired-git-info"><code>dired-git-info</code></h3><p><em><a href="https://github.com/clemera/dired-git-info">dired-git-info</a> displays information about Git files in Dired.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">dired-git-info</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dgi-commit-message-format</span><span class="s">"%s %cr %an"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">dired-git-info-mode</span><span class="p">)))</span></span></span></code></pre></div><h3 id="dired-du"><code>dired-du</code></h3><p><em><a href="https://github.com/calancha/dired-du">dired-du</a> displays the recursive size of directories in Dired.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">dired-du</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-du-size-format</span><span class="ss">'comma</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"'"</span><span class="o">.</span><span class="nv">dired-du-mode</span><span class="p">)))</span></span></span></code></pre></div><h3 id="image-dired"><code>image-dired</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/image-dired.el">image-dired</a> provides image viewing and thumbnail management in Dired.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">image-dired</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">image-dired-main-image-directory</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"~/Pictures/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">image-dired-external-viewer</span><span class="s">"open"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">image-dired-thumbnail-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">dired-extras-image-copy-filename-as-kill-absolute</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">image-dired-thumbnail-display-external</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">image-dired-display-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">image-dired-display-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">dired-extras-image-dired-current-directory</span><span class="p">)))</span></span></span></code></pre></div><h3 id="nerd-icons-dired"><code>nerd-icons-dired</code></h3><p><em><a href="https://github.com/rainstormstudio/nerd-icons-dired">nerd-icons-dired</a> adds Dired support to nerd-icons.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">nerd-icons-dired</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="nv">nerd-icons-dired-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="wdired"><code>wdired</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/wdired.el">wdired</a> makes Dired buffers editable for renaming files and changing permissions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">wdired</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wdired-allow-to-change-permissions</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">wdired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">wdired-finish-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">wdired-finish-edit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="gnus-dired"><code>gnus-dired</code></h3><p><em>gnus-dired provides utility functions for intersections of<code>gnus</code> and<code>dired</code>.</em></p><p>I use<code>mu4e</code> (see below) rather than<code>gnus</code> to handle email. However, a specific functionality in this feature also works with<code>mu4e</code>, allowing me to attach a file to an email directly from a Dired buffer.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">gnus-dired</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; enable `mu4e' attachments from `dired'</span></span></span><span class="line"><span class="cl"><span class="c1">;; djcbsoftware.nl/code/mu/mu4e/Dired.html</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gnus-dired-mail-mode</span><span class="ss">'mu4e-user-agent</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dired-mode-hook</span><span class="o">.</span><span class="nv">turn-on-gnus-dired-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">gnus-dired-attach</span><span class="p">)))</span></span></span></code></pre></div><h3 id="dired-hacks"><code>dired-hacks</code></h3><p><em><a href="https://github.com/Fuco1/dired-hacks">dired-hacks</a> is a collection of useful dired additions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">dired-hacks</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"Fuco1/dired-hacks"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'dired-subtree-toggle</span><span class="nb">:after</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">dired-omit-mode</span><span class="p">)</span><span class="p">(</span><span class="nv">dired-omit-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'dired-subtree-cycle</span><span class="nb">:after</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">dired-omit-mode</span><span class="p">)</span><span class="p">(</span><span class="nv">dired-omit-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-w"</span><span class="o">.</span><span class="nv">dired-narrow-regexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="nv">dired-subtree-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">dired-subtree-cycle</span><span class="p">)))</span></span></span></code></pre></div><h3 id="dired-quick-sort"><code>dired-quick-sort</code></h3><p><em><a href="https://gitlab.com/xuhdev/dired-quick-sort">dired-quick-sort</a> provides persistent quick sorting of Dired buffers in various ways.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">dired-quick-sort</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"T"</span><span class="o">.</span><span class="nv">dired-quick-sort-transient</span><span class="p">)))</span></span></span></code></pre></div><h3 id="peep-dired"><code>peep-dired</code></h3><p><em><a href="https://github.com/asok/peep-dired">peep-dired</a> supports browsing file contents in other window while browsing directory in dired.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">peep-dired</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"F"</span><span class="o">.</span><span class="nv">peep-dired</span><span class="p">)))</span></span></span></code></pre></div><h3 id="minibuffer"><code>minibuffer</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/minibuffer.el">minibuffer</a> provides minibuffer completion and input facilities.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">minibuffer</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">enable-recursive-minibuffers</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">resize-mini-windows</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">completion-cycle-threshold</span><span class="mi">3</span><span class="p">)</span><span class="c1">; TAB cycle if there are only few candidates</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-default-prompt-format</span><span class="s">" [%s]"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-electric-default-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">minibuffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">previous-history-element</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">next-history-element</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-e"</span><span class="o">.</span><span class="nv">search-query-replace</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="nv">yas-maybe-expand</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">org-roam-node-insert</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ibuffer"><code>ibuffer</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/ibuffer.el">ibuffer</a> provides an advanced, interactive buffer list.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ibuffer</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ibuffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">ibuffer-do-delete</span><span class="p">)))</span></span></span></code></pre></div><h3 id="prot-scratch"><code>prot-scratch</code></h3><p><em>[[<a href="https://github.com/protesilaos/dotfiles/blob/master/emacs">https://github.com/protesilaos/dotfiles/blob/master/emacs</a></em>.emacs.d/prot-lisp/prot-scratch.el][prot-scratch]] supports scratch buffers for an editable major mode of choice._</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">prot-scratch</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:local-repo</span><span class="s">"prot-scratch"</span></span></span><span class="line"><span class="cl"><span class="nb">:main</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-scratch.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-scratch.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prot-scratch-default-mode</span><span class="ss">'org-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-n"</span><span class="o">.</span><span class="nv">prot-scratch-buffer</span><span class="p">))</span></span></span></code></pre></div><h3 id="persistent-scratch"><code>persistent-scratch</code></h3><p><em><a href="https://github.com/Fanael/persistent-scratch">persistent-scratch</a> preserves the scratch buffer across Emacs sessions.</em></p><p>I use this package in combination with<code>prot-scratch</code> (see above) to persist scratch buffers in different modes. This way, I am able to open a scratch buffer in<em>any</em> mode for temporary notes, without running the risk of losing them.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">persistent-scratch</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">persistent-scratch-autosave-interval</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">persistent-scratch-backup-directory</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">no-littering-expand-var-file-name</span><span class="s">"auto-save/scratch-buffers/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">persistent-scratch-setup-default</span><span class="p">))</span></span></span></code></pre></div><h3 id="executable"><code>executable</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/executable.el">executable</a> provides base functionality for executable interpreter scripts.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">executable</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="c1">;; masteringemacs.org/article/script-files-executable-automatically</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">after-save-hook</span><span class="o">.</span><span class="nv">executable-make-buffer-file-executable-if-script-p</span><span class="p">))</span></span></span></code></pre></div><h3 id="uniquify"><code>uniquify</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/uniquify.el">uniquify</a> provides unique buffer names.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">uniquify</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">uniquify-buffer-name-style</span><span class="ss">'forward</span><span class="p">))</span></span></span></code></pre></div><h3 id="reveal-in-osx-finder"><code>reveal-in-osx-finder</code></h3><p><em><a href="https://github.com/kaz-yos/reveal-in-osx-finder">reveal-in-osx-finder</a> lets you open the file at point or the current file-visiting buffer in OS X Finder.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">reveal-in-osx-finder</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"/"</span><span class="o">.</span><span class="nv">reveal-in-osx-finder</span><span class="p">)))</span></span></span></code></pre></div><h3 id="tramp"><code>tramp</code></h3><p><em><a href="https://www.gnu.org/software/tramp/">tramp</a> is a remote file editing package for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">tramp</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired-x</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tramp-auto-save-directory</span><span class="nv">no-littering-var-directory</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; Disable version control on tramp buffers to avoid freezes.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vc-ignore-dir-regexp</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">format</span><span class="s">"\\(%s\\)\\|\\(%s\\)"</span></span></span><span class="line"><span class="cl"><span class="nv">vc-ignore-dir-regexp</span></span></span><span class="line"><span class="cl"><span class="nv">tramp-file-name-regexp</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Don't clean up recentf tramp buffers.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">recentf-auto-cleanup</span><span class="ss">'never</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; This is supposedly [[https://www.emacswiki.org/emacs/TrampMode][faster than the default]], `scp'.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tramp-default-method</span><span class="s">"sshx"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Store TRAMP auto-save files locally.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tramp-auto-save-directory</span><span class="nv">paths-dir-emacs-var</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; A more representative name for this file.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tramp-persistency-file-name</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">tramp-auto-save-directory</span><span class="s">"tramp-connection-history"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Cache SSH passwords during the whole Emacs session.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">password-cache-expiry</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; emacs.stackexchange.com/a/37855/32089</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remote-file-name-inhibit-cache</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Reuse SSH connections. Taken from the TRAMP FAQ.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">customize-set-variable</span><span class="ss">'tramp-ssh-controlmaster-options</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span></span></span><span class="line"><span class="cl"><span class="s">"-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p "</span></span></span><span class="line"><span class="cl"><span class="s">"-o ControlMaster=auto -o ControlPersist=yes"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; This will put in effect PATH changes in the remote ~/.profile.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'tramp-remote-path</span><span class="ss">'tramp-own-remote-path</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'projectile-project-root</span></span></span><span class="line"><span class="cl"><span class="nb">:around</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Ignore remote files."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nv">file-remote-p</span><span class="nv">default-directory</span><span class="ss">'no-identification</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">orig-fun</span><span class="nv">args</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'tramp-connection-properties</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nf">regexp-quote</span><span class="s">"/ssh:fede@tlon.team:"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"direct-async-process"</span><span class="no">t</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pandoc-mode"><code>pandoc-mode</code></h3><p><em><a href="https://github.com/joostkremers/pandoc-mode">pandoc-mode</a> is a minor mode for interacting with Pandoc.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pandoc-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="track-changes">track-changes</h3><p><em><a href="https://elpa.gnu.org/packages/track-changes.html">track-changes</a> provides an API to react to buffer modifications.</em></p><p>I load this explicitly because the version bundled with Emacs 30.2 (1.2) has a known bug (debbugs#73041), where track-changes&ndash;before-beg/end can become inconsistent with the buffer size, triggering a cl-assertion-failed error on buffer modifications. The GNU ELPA version fixes this bug.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">track-changes</span></span></span><span class="line"><span class="cl"><span class="c1">;; The default GNU ELPA recipe clones the full emacs-mirror/emacs repo</span></span></span><span class="line"><span class="cl"><span class="c1">;; and uses a :files spec matching that layout. Use emacs-straight's</span></span></span><span class="line"><span class="cl"><span class="c1">;; lightweight mirror instead, with a flat :files glob.</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:repo</span><span class="s">"https://github.com/emacs-straight/track-changes.git"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"*"</span><span class="p">(</span><span class="nb">:exclude</span><span class="s">".git"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h2 id="windows-and-frames">windows &amp; frames</h2><h3 id="window"><code>window</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/window.el">window</a> provides commands for displaying buffers, scrolling, and managing window layout.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">window</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ebib</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">bury-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">bury-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'simple</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">messages-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">bury-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'telega</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'telega-root-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-q"</span><span class="o">.</span><span class="nv">bury-buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'elfeed</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">scroll-down-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">scroll-up-command</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'helpful</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">helpful-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">scroll-down-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">scroll-up-command</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'mu4e</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">mu4e-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">scroll-down-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">scroll-up-command</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'telega</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">telega-msg-button-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">scroll-down-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">scroll-up-command</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">split-height-threshold</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; move point to top of buffer if `scroll-down-command' invoked when screen can scroll no further</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-error-top-bottom</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">split-width-threshold</span><span class="mi">200</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; we add `*ocr-pdf' buffer to list of buffers not to be displayed,</span></span></span><span class="line"><span class="cl"><span class="c1">;; so that the process runs in the background`</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="s">"*ocr-pdf*"</span><span class="nv">display-buffer-no-window</span><span class="p">)</span><span class="nv">display-buffer-alist</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; The following prevents Emacs from splitting windows indefinitely when the monitor config changes</span></span></span><span class="line"><span class="cl"><span class="c1">;; stackoverflow.com/questions/23207958/how-to-prevent-emacs-dired-from-splitting-frame-into-more-than-two-windows</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'display-buffer-alist</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">shell-command-buffer-name-async</span><span class="nv">display-buffer-no-window</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-override-code</span></span></span><span class="line"><span class="cl"><span class="nb">:window-split</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">add-hook</span><span class="ss">'elpaca-after-init-hook</span><span class="nf">#'</span><span class="nv">window-extras-split-if-unsplit</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-w"</span><span class="o">.</span><span class="nv">delete-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-y"</span><span class="o">.</span><span class="nv">scroll-down-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-h"</span><span class="o">.</span><span class="nv">scroll-up-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-g"</span><span class="o">.</span><span class="nf">scroll-other-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-t"</span><span class="o">.</span><span class="nv">scroll-other-window-down</span><span class="p">)))</span></span></span></code></pre></div><h3 id="window-extras"><code>window-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/window-extras.el">window-extras</a> collects my extensions for<code>window</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">window-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-0"</span><span class="o">.</span><span class="nv">window-extras-switch-to-last-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-0"</span><span class="o">.</span><span class="nv">window-extras-switch-to-minibuffer-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-,"</span><span class="o">.</span><span class="nv">window-extras-buffer-move-left</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-."</span><span class="o">.</span><span class="nv">window-extras-buffer-move-right</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M--"</span><span class="o">.</span><span class="nv">window-extras-buffer-swap</span><span class="p">)</span><span class="c1">; `emacs-mac'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-–"</span><span class="o">.</span><span class="nv">window-extras-buffer-swap</span><span class="p">)))</span><span class="c1">; `emacs-plus'</span></span></span></code></pre></div><h3 id="frame"><code>frame</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/frame.el">frame</a> provides multi-frame management independent of window systems.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">frame</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">window-divider-default-right-width</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">blink-cursor-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">window-divider-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-M-&lt;tab&gt;"</span><span class="o">.</span><span class="nv">other-frame</span><span class="p">)</span><span class="c1">; M-S-TAB</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-N"</span><span class="o">.</span><span class="nv">make-frame</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-W"</span><span class="o">.</span><span class="nf">delete-frame</span><span class="p">)))</span></span></span></code></pre></div><h3 id="frame-extras"><code>frame-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/frame-extras.el">frame-extras</a> collects my extensions for<code>frame</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">frame-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-after-init-hook</span><span class="o">.</span><span class="nv">frame-extras-maximize-frame</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spacious-padding-mode-hook</span><span class="o">.</span><span class="nv">frame-extras-restore-window-divider</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="c1">;; the key bindings below are triggered via Karabiner</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-I"</span><span class="o">.</span><span class="nv">frame-extras-maximize-frame</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-U"</span><span class="o">.</span><span class="nv">frame-extras-left-half</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-P"</span><span class="o">.</span><span class="nv">frame-extras-right-half</span><span class="p">)))</span></span></span></code></pre></div><h3 id="posframe"><code>posframe</code></h3><p><em><a href="https://github.com/tumashu/posframe">posframe</a> supports displaying small popup frames.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">posframe</span><span class="p">)</span></span></span></code></pre></div><h3 id="winum"><code>winum</code></h3><p><em><a href="https://github.com/deb0ch/emacs-winum">winum-mode</a> supports navigation of windows and frames using numbers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">winum</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">winum-scope</span><span class="ss">'frame-local</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">winum-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"&lt;C-m&gt;"</span><span class="o">.</span><span class="nv">winum-select-window-1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-,"</span><span class="o">.</span><span class="nv">winum-select-window-2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-."</span><span class="o">.</span><span class="nv">winum-select-window-3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-/"</span><span class="o">.</span><span class="nv">winum-select-window-4</span><span class="p">)))</span></span></span></code></pre></div><h3 id="winner"><code>winner</code></h3><p><em><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Convenience.html">winner-mode</a> is a global minor mode that records the changes in the window configuration (i.e., how the frames are partitioned into windows), so that you can undo them.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">winner</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'minibuffer-setup-hook</span><span class="ss">'winner-save-unconditionally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">winner-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-W"</span><span class="o">.</span><span class="nv">winner-undo</span><span class="p">))</span></span></span></code></pre></div><h3 id="popper"><code>popper</code></h3><p><em><a href="https://github.com/karthink/popper">popper</a> is a minor-mode to summon and dismiss buffers easily.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">popper</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">popper-reference-buffers</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="s">"\\*Warnings\\*"</span></span></span><span class="line"><span class="cl"><span class="s">"Output\\*$"</span></span></span><span class="line"><span class="cl"><span class="nv">help-mode</span></span></span><span class="line"><span class="cl"><span class="nv">helpful-mode</span></span></span><span class="line"><span class="cl"><span class="nv">compilation-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">popper-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">popper-echo-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">popper-display-control</span><span class="ss">'user</span><span class="p">)</span><span class="c1">; assumes buffer-specific behavior customized via `display-buffer-alist'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">popper-echo-dispatch-keys</span><span class="o">'</span><span class="p">(</span><span class="sc">?a</span><span class="sc">?s</span><span class="sc">?d</span><span class="sc">?f</span><span class="sc">?j</span><span class="sc">?l</span><span class="sc">?r</span><span class="sc">?q</span><span class="sc">?w</span><span class="sc">?e</span><span class="sc">?r</span><span class="sc">?u</span><span class="sc">?i</span><span class="sc">?o</span><span class="sc">?p</span><span class="sc">?z</span><span class="sc">?x</span><span class="sc">?c</span><span class="sc">?v</span><span class="sc">?m</span><span class="sc">?,</span><span class="sc">?.</span><span class="sc">?/</span><span class="sc">?</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">popper-window-height</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Set WINDOW to a size up to 33% of the frame height."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">fit-window-to-buffer</span></span></span><span class="line"><span class="cl"><span class="nv">window</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">floor</span><span class="p">(</span><span class="nv">frame-height</span><span class="p">)</span><span class="mi">3</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-o"</span><span class="o">.</span><span class="nv">popper-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-o"</span><span class="o">.</span><span class="nv">popper-toggle-type</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-o"</span><span class="o">.</span><span class="nv">popper-cycle</span><span class="p">)))</span></span></span></code></pre></div><h3 id="avy"><code>avy</code></h3><p><em><a href="https://github.com/abo-abo/avy">avy</a> lets you jump to any visible text using a char-based decision tree.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">avy</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ebib</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-goto-line</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'isearch</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">isearch-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">avy-isearch</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">avy-case-fold-search</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">avy-timeout-seconds</span><span class="mf">0.2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">avy-all-windows</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">avy-keys</span><span class="p">(</span><span class="nf">append</span><span class="o">'</span><span class="p">(</span><span class="sc">?k</span><span class="p">)</span><span class="nv">popper-echo-dispatch-keys</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="p">(</span><span class="nv">alist-get</span><span class="sc">?r</span><span class="nv">avy-dispatch-alist</span><span class="p">)</span><span class="ss">'avy-extras-action-mark-to-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-s-m"</span><span class="o">.</span><span class="nv">avy-goto-line-above</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-."</span><span class="o">.</span><span class="nv">avy-goto-line-below</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-k"</span><span class="o">.</span><span class="nv">avy-goto-word-1-above</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-l"</span><span class="o">.</span><span class="nv">avy-goto-word-1-below</span><span class="p">)))</span></span></span></code></pre></div><h3 id="avy-extras"><code>avy-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/avy-extras.el">avy-extras</a> collects my extensions for<code>avy</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">avy-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-s-u"</span><span class="o">.</span><span class="nv">avy-extras-goto-word-in-line-behind</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-p"</span><span class="o">.</span><span class="nv">avy-extras-goto-word-in-line-ahead</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-,"</span><span class="o">.</span><span class="nv">avy-extras-goto-end-of-line-above</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-/"</span><span class="o">.</span><span class="nv">avy-extras-goto-end-of-line-below</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-j"</span><span class="o">.</span><span class="nv">avy-extras-goto-char-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s-;"</span><span class="o">.</span><span class="nv">avy-extras-goto-char-forward</span><span class="p">)))</span></span></span></code></pre></div><h3 id="writeroom-mode"><code>writeroom-mode</code></h3><p><em><a href="https://github.com/joostkremers/writeroom-mode">writeroom-mode</a> provides distraction-free writing for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">writeroom-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">writeroom-global-effects</span><span class="o">'</span><span class="p">(</span><span class="nv">writeroom-set-fullscreen</span></span></span><span class="line"><span class="cl"><span class="nv">writeroom-set-alpha</span></span></span><span class="line"><span class="cl"><span class="nv">writeroom-set-menu-bar-lines</span></span></span><span class="line"><span class="cl"><span class="nv">writeroom-set-tool-bar-lines</span></span></span><span class="line"><span class="cl"><span class="nv">writeroom-set-vertical-scroll-bars</span></span></span><span class="line"><span class="cl"><span class="nv">writeroom-set-bottom-divider-width</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">arg</span><span class="p">)</span><span class="p">(</span><span class="nv">tab-bar-mode</span><span class="p">(</span><span class="nf">*</span><span class="mi">-1</span><span class="nv">arg</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">writeroom-restore-window-config</span><span class="no">t</span><span class="p">)</span><span class="c1">; upon leaving `writeroom mode', restore pre-existing number of windows</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">writeroom-major-modes</span><span class="o">'</span><span class="p">(</span><span class="nv">org-mode</span></span></span><span class="line"><span class="cl"><span class="nv">elfeed-search-mode</span></span></span><span class="line"><span class="cl"><span class="nv">elfeed-show-mode</span></span></span><span class="line"><span class="cl"><span class="nv">eww-mode</span></span></span><span class="line"><span class="cl"><span class="nv">eww-buffers-mode</span><span class="p">))</span><span class="c1">; major modes activated in global-writeroom-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">writeroom-fullscreen-effect</span><span class="ss">'maximized</span><span class="p">)</span><span class="c1">; disables annoying fullscreen transition effect on macos</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">writeroom-maximize-window</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'writeroom-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:before</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Set</span><span class="ss">`writeroom-width'</span><span class="s"> to the width of the window in which it is invoked."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">writeroom-width</span><span class="p">(</span><span class="nf">window-total-width</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-u"</span><span class="o">.</span><span class="nv">writeroom-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="logos">logos</h3><p><em><a href="https://protesilaos.com/emacs/logos">logos</a> provides a simple focus mode for reading, writing, and presentation.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">logos</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Treat outline headings (org *, elisp ;;;, markdown #) as pages</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">logos-outlines-are-pages</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Aesthetic tweaks for `logos-focus-mode' (all buffer-local)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">logos-hide-cursor</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="nv">logos-hide-mode-line</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nv">logos-hide-header-line</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nv">logos-hide-buffer-boundaries</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nv">logos-hide-fringe</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nv">logos-variable-pitch</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="nv">logos-buffer-read-only</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="nv">logos-scroll-lock</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="nv">logos-olivetti</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Recenter at top on page motion so each "slide" starts at the top</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">ps/logos-recenter-top</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Use</span><span class="ss">`recenter'</span><span class="s"> to reposition the view at the top."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nv">derived-mode-p</span><span class="ss">'prog-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">recenter</span><span class="mi">0</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'logos-page-motion-hook</span><span class="nf">#'</span><span class="nv">ps/logos-recenter-top</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(([</span><span class="nv">remap</span><span class="nf">narrow-to-region</span><span class="p">]</span><span class="o">.</span><span class="nv">logos-narrow-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">([</span><span class="nv">remap</span><span class="nv">forward-page</span><span class="p">]</span><span class="o">.</span><span class="nv">logos-forward-page-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">([</span><span class="nv">remap</span><span class="nv">backward-page</span><span class="p">]</span><span class="o">.</span><span class="nv">logos-backward-page-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;f9&gt;"</span><span class="o">.</span><span class="nv">logos-focus-mode</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ace-link"><code>ace-link</code></h3><p><em><a href="https://github.com/abo-abo/ace-link">ace-link</a> lets you quickly follow links in Emacs, Vimium-style.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ace-link</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ace-link-extras"><code>ace-link-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/ace-link-extras.el">ace-link-extras</a> collects my extensions for<code>ace-link</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">ace-link-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ace-link</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">mode</span><span class="o">'</span><span class="p">(</span><span class="nv">slack-message-buffer-mode</span></span></span><span class="line"><span class="cl"><span class="nv">slack-thread-message-buffer-mode</span></span></span><span class="line"><span class="cl"><span class="nv">slack-activity-feed-buffer-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="p">(</span><span class="nf">list</span><span class="ss">'ace-link-extras-slack</span><span class="nv">mode</span><span class="p">)</span><span class="nv">ace-link-major-mode-actions</span><span class="p">)))</span></span></span></code></pre></div><h2 id="date-and-time">date &amp; time</h2><h3 id="calendar"><code>calendar</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/calendar/calendar.el">calendar</a> provides a collection of calendar-related functions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">calendar</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-week-start-day</span><span class="mi">1</span><span class="p">)</span><span class="c1">; week starts on Monday</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-set-date-style</span><span class="ss">'iso</span><span class="p">)</span><span class="c1">; this isn't the default?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-time-display-form</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">24-hours</span><span class="s">":"</span><span class="nv">minutes</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="nv">time-zone</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="s">" ("</span><span class="nv">time-zone</span><span class="s">")"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-mark-holidays-flag</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-time-zone-style</span><span class="ss">'numeric</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">holiday-bahai-holidays</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-d"</span><span class="o">.</span><span class="nv">calendar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-="</span><span class="o">.</span><span class="s">"C-u A-s-="</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">calendar-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-m"</span><span class="o">.</span><span class="nv">calendar-set-mark</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-u"</span><span class="o">.</span><span class="nv">calendar-backward-day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-i"</span><span class="o">.</span><span class="nv">calendar-backward-week</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-o"</span><span class="o">.</span><span class="nv">calendar-forward-week</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-p"</span><span class="o">.</span><span class="nv">calendar-forward-day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-m"</span><span class="o">.</span><span class="nv">calendar-backward-month</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-,"</span><span class="o">.</span><span class="nv">calendar-backward-year</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-."</span><span class="o">.</span><span class="nv">calendar-forward-year</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-/"</span><span class="o">.</span><span class="nv">calendar-forward-month</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-f"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-b"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"="</span><span class="o">.</span><span class="nv">calendar-count-days-region</span><span class="p">)))</span></span></span></code></pre></div><h3 id="calendar-extras"><code>calendar-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/calendar-extras.el">calendar-extras</a> collects my extensions for<code>calendar</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">calendar-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-extras-location-name</span><span class="s">"Buenos Aires"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">calendar-extras-use-geolocation</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="holidays"><code>holidays</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e819413e24d81875abaf81c281115e695ad5cc28/lisp/calendar/holidays.el#L98">holidays</a> provides holiday functions for<code>calendar</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">holidays</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">holiday</span><span class="o">'</span><span class="p">((</span><span class="nv">holiday-float</span><span class="mi">6</span><span class="mi">0</span><span class="mi">3</span><span class="s">"Father's Day"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">holiday-float</span><span class="mi">5</span><span class="mi">0</span><span class="mi">2</span><span class="s">"Mother's Day"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">delete</span><span class="nv">holiday</span><span class="nv">holiday-general-holidays</span><span class="p">)))</span></span></span></code></pre></div><h3 id="institution-calendar"><code>institution-calendar</code></h3><p><em><a href="https://github.com/protesilaos/institution-calendar">institution-calendar</a> augments the<code>calendar</code> buffer to include Oxford/Calendar term indicators.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">institution-calendar</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/institution-calendar"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">institution-calendar-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-gcal"><code>org-gcal</code></h3><p><em><a href="https://github.com/kidd/org-gcal.el">org-gcal</a> integrates<code>org-mode</code> with Google Calendar.</em></p><p>(That&rsquo;s the actively maintained fork; the<a href="https://github.com/myuhe/org-gcal.el/issues/124#issuecomment-642859466">official repository</a> is no longer maintained.)</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-gcal</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/org-gcal.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"fix/strip-html-descriptions"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span><span class="c1">; https://github.com/kidd/org-gcal.el/pull/276</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">auth-source-pass</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-client-id</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"host"</span><span class="s">"auth-sources/org-gcal"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-client-secret</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"auth-sources/org-gcal"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-fetch-file-alist</span><span class="o">`</span><span class="p">((</span><span class="o">,</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_GMAIL"</span><span class="p">)</span><span class="o">.</span><span class="o">,</span><span class="nv">paths-file-calendar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"EPOCH_EMAIL"</span><span class="p">)</span><span class="o">.</span><span class="o">,</span><span class="nv">paths-file-calendar</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-recurring-events-mode</span><span class="ss">'top-level</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-remove-api-cancelled-events</span><span class="no">nil</span><span class="p">)</span><span class="c1">; never remove cancelled events</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-notify-p</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-up-days</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-down-days</span><span class="mi">7</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-gcal-auto-archive</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; see the relevant section in this config file for more details on how to set</span></span></span><span class="line"><span class="cl"><span class="c1">;; up `org-gcal' with asymmetric encryption</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'plstore</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-gcal-extras"><code>org-gcal-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-gcal-extras.el">org-gcal-extras</a> collects my extensions for<code>org-gcal</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-gcal-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-gcal</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="calfw"><code>calfw</code></h3><p><em><a href="https://github.com/haji-ali/emacs-calfw">calf</a> is a calendar framework for Emacs.</em></p><p>The original package is no longer maintained. A<a href="https://github.com/haji-ali/emacs-calfw">fork</a> by Abdul-Lateef Haji-Ali below added a few improvements. But that fork itself ceased to be maintained so I am now using my own fork.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">calfw</span></span></span><span class="line"><span class="cl"><span class="c1">;; :ensure (:host github</span></span></span><span class="line"><span class="cl"><span class="c1">;; :repo "benthamite/emacs-calfw")</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-agenda</span><span class="p">)</span></span></span></code></pre></div><h3 id="calfw-org"><code>calfw-org</code></h3><p><em><a href="https://github.com/benthamite/emacs-calfw/blob/master/calfw-org.el">calfw-org</a> display org-agenda items in the calfw buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">calfw-org</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">calfw</span><span class="nv">org</span><span class="p">)</span></span></span></code></pre></div><h3 id="calfw-blocks"><code>calfw-blocks</code></h3><p><em><a href="https://github.com/benthamite/calfw-blocks">calfw-blocks</a> provides visual enhancements for calfw.</em></p><p>The original package appears to no longer be maintained, so I have created my own fork.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">calfw-blocks</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nv">calfw-blocks</span></span></span><span class="line"><span class="cl"><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/calfw-blocks"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">calfw</span><span class="p">)</span></span></span></code></pre></div><h3 id="time"><code>time</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e819413e24d81875abaf81c281115e695ad5cc28/lisp/time.el#L2">time</a> provides facilities to display the current date and time, and a new-mail indicator mode line.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">time</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zoneinfo-style-world-list</span><span class="o">'</span><span class="p">((</span><span class="s">"America/Buenos_Aires"</span><span class="s">"Buenos Aires"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Europe/London"</span><span class="s">"London"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Europe/Madrid"</span><span class="s">"Madrid"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"America/New_York"</span><span class="s">"New York"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"America/Los_Angeles"</span><span class="s">"San Francisco"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Europe/Stockholm"</span><span class="s">"Stockholm"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">world-clock-list</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">world-clock-time-format</span><span class="s">"%R %z (%Z) %A %d %B"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">world-clock-buffer-name</span><span class="s">"*world-clock*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">world-clock-timer-enable</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">world-clock-timer-second</span><span class="mi">60</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-time-interval</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-time-format</span><span class="s">"%a %e %b %T %z"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-time-default-load-average</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-time-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-A-t"</span><span class="o">.</span><span class="nv">world-clock</span><span class="p">))</span></span></span></code></pre></div><h3 id="timer-list"><code>timer-list</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/timer-list.el">timer-list</a> lists active timers in a tabulated buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">timer-list</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; disable warning</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">put</span><span class="ss">'list-timers</span><span class="ss">'disabled</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="tmr"><code>tmr</code></h3><p><em><a href="https://protesilaos.com/emacs/tmr">tmr</a> set timers using a convenient notation.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">tmr</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">eq</span><span class="nv">system-type</span><span class="ss">'darwin</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">tmr-sound-file</span><span class="s">"/System/Library/Sounds/Blow.aiff"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="display-wttr"><code>display-wttr</code></h3><p><em><a href="https://git.sr.ht/~josegpt/display-wttr">display-wttr</a> displays weather information in the mode line.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">display-wttr</span></span></span><span class="line"><span class="cl"><span class="nb">:disabled</span><span class="c1">; triggering lots of errors</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">calendar-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-wttr-interval</span><span class="p">(</span><span class="nf">*</span><span class="mi">15</span><span class="mi">60</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-wttr-locations</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">calendar-extras-location-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-wttr-mode</span><span class="p">))</span></span></span></code></pre></div><h2 id="history">history</h2><h3 id="savehist"><code>savehist</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e819413e24d81875abaf81c281115e695ad5cc28/lisp/savehist.el">savehist</a> makes Emacs remember completion history across sessions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">savehist</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">history-length</span><span class="no">t</span><span class="p">)</span><span class="c1">; unlimited history</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">savehist-save-minibuffer-history</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">savehist-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="simple"><code>simple</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/simple.el">simple</a> registers additional variables for persistence across sessions via savehist.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">var</span><span class="o">'</span><span class="p">(</span><span class="nv">command-history</span></span></span><span class="line"><span class="cl"><span class="nv">extended-command-history</span></span></span><span class="line"><span class="cl"><span class="nv">kill-ring</span></span></span><span class="line"><span class="cl"><span class="nv">mark-ring</span></span></span><span class="line"><span class="cl"><span class="nv">shell-command-history</span></span></span><span class="line"><span class="cl"><span class="nv">read-expression-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="nv">var</span><span class="p">))))</span></span></span></code></pre></div><h3 id="saveplace"><code>saveplace</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e819413e24d81875abaf81c281115e695ad5cc28/lisp/saveplace.el">saveplace</a> makes Emacs remember point position in file across sessions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">saveplace</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">save-place-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="session"><code>session</code></h3><p><em><a href="https://github.com/emacsorphanage/session">session</a> lets you use variables, registers and buffer places across sessions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">session</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">session-globals-include</span><span class="o">'</span><span class="p">((</span><span class="nv">kill-ring</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">session-file-alist</span><span class="mi">100</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-history</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nv">search-ring</span><span class="nv">regexp-search-ring</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpaca-after-init-hook</span><span class="o">.</span><span class="nv">session-initialize</span><span class="p">))</span></span></span></code></pre></div><h3 id="recentf"><code>recentf</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e819413e24d81875abaf81c281115e695ad5cc28/lisp/recentf.el">recentf</a> makes Emacs remember the most recently visited files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">recentf</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">recentf-max-saved-items</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; github.com/emacscollective/no-littering#suggested-settings</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'recentf-exclude</span><span class="nv">no-littering-var-directory</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'recentf-exclude</span><span class="nv">no-littering-etc-directory</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">find-file-hook</span><span class="p">)</span></span></span></code></pre></div><h2 id="search-and-replace">search &amp; replace</h2><h3 id="elgrep"><code>elgrep</code></h3><p><em><a href="https://github.com/TobiasZawada/elgrep">elgrep</a> is an Emacs implementation of grep that requires no external dependencies.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elgrep</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">elgrep-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">elgrep-edit-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">elgrep-save</span><span class="p">)))</span></span></span></code></pre></div><h3 id="isearch"><code>isearch</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/isearch.el">isearch</a> provides incremental search.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">isearch</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">search-default-mode</span><span class="nf">#'</span><span class="nv">char-fold-to-regexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">isearch-yank-on-move</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">isearch-lazy-count</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lazy-count-prefix-format</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lazy-count-suffix-format</span><span class="s">" (%s/%s)"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">isearch-allow-scroll</span><span class="ss">'unlimited</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">search-upper-case</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">search-exit-option</span><span class="no">t</span><span class="p">)</span><span class="c1">; `t' is the default, but some alternative value may be more sensible</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">var</span><span class="o">'</span><span class="p">(</span><span class="nv">regexp-search-ring</span><span class="nv">search-ring</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="nv">var</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">isearch-mode-end-hook</span><span class="o">.</span><span class="nv">recenter-top-bottom</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">isearch-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s"</span><span class="o">.</span><span class="nv">isearch-delete-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-d"</span><span class="o">.</span><span class="s">"C-- C-H-M-s"</span><span class="p">)</span><span class="c1">; delete forward char</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-g"</span><span class="o">.</span><span class="nv">isearch-abort</span><span class="p">)</span><span class="c1">; "quit once"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-g"</span><span class="o">.</span><span class="nv">isearch-exit</span><span class="p">)</span><span class="c1">; "quit twice"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-. "</span><span class="o">.</span><span class="nv">isearch-toggle-char-fold</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-,"</span><span class="o">.</span><span class="nv">isearch-forward-symbol-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-."</span><span class="o">.</span><span class="nv">isearch-forward-thing-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-/"</span><span class="o">.</span><span class="nv">isearch-complete</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-m"</span><span class="o">.</span><span class="nv">isearch-toggle-lax-whitespace</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-a"</span><span class="o">.</span><span class="nv">isearch-toggle-regexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-b"</span><span class="o">.</span><span class="nv">isearch-beginning-of-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-d"</span><span class="o">.</span><span class="nv">isearch-toggle-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-f"</span><span class="o">.</span><span class="nv">isearch-highlight-lines-matching-regexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-i"</span><span class="o">.</span><span class="nv">isearch-toggle-invisible</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-l"</span><span class="o">.</span><span class="nv">isearch-yank-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-m"</span><span class="o">.</span><span class="nv">isearch-toggle-symbol</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-n"</span><span class="o">.</span><span class="nv">isearch-end-of-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-o"</span><span class="o">.</span><span class="nv">isearch-occur</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-p"</span><span class="o">.</span><span class="nv">isearch-highlight-regexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-v"</span><span class="o">.</span><span class="nv">isearch-yank-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-y"</span><span class="o">.</span><span class="nv">isearch-forward-symbol-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">isearch-ring-retreat</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">isearch-ring-advance</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-e"</span><span class="o">.</span><span class="nv">isearch-query-replace</span><span class="p">)))</span></span></span></code></pre></div><p>To check:<a href="https://karthinks.com/software/bridging-islands-in-emacs-1/">Bridging Islands in Emacs: re-builder and query-replace-regexp | Karthinks</a></p><h3 id="isearch-extras"><code>isearch-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/isearch-extras.el">isearch-extras</a> collects my extensions for<code>isearch</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">isearch-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'isearch-mode</span><span class="nb">:around</span><span class="nf">#'</span><span class="nv">isearch-extras-use-selection</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">isearch-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-&lt;return&gt;"</span><span class="o">.</span><span class="nv">isearch-extras-exit-other-end</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">isearch-extras-copy-match</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-p"</span><span class="o">.</span><span class="nv">isearch-extras-project-search</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-l"</span><span class="o">.</span><span class="nv">isearch-extras-consult-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-v"</span><span class="o">.</span><span class="nv">isearch-extras-yank-kill-literally</span><span class="p">)))</span></span></span></code></pre></div><h3 id="replace"><code>replace</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/replace.el">replace</a> provides search-and-replace commands.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">replace</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; emacs.stackexchange.com/a/12318/32089</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">query-replace-from-history-variable</span><span class="ss">'regexp-search-ring</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">case-replace</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-a"</span><span class="o">.</span><span class="nv">query-replace</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-s"</span><span class="o">.</span><span class="nv">query-replace-regexp</span><span class="p">)))</span></span></span></code></pre></div><h3 id="substitute"><code>substitute</code></h3><p><em><a href="https://git.sr.ht/~protesilaos/substitute">substitute</a> efficiently replaces targets in the buffer or context.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">substitute</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/substitute"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">substitute-post-replace-functions</span><span class="o">.</span><span class="nv">substitute-report-operation</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-b"</span><span class="o">.</span><span class="nv">substitute-target-in-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">prog-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-d"</span><span class="o">.</span><span class="nv">substitute-target-in-defun</span><span class="p">)))</span></span></span></code></pre></div><h3 id="imenu"><code>imenu</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/imenu.el">imenu</a> is a framework for mode-specific buffer indexes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">imenu</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-imenu-depth</span><span class="mi">3</span><span class="p">))</span></span></span></code></pre></div><h3 id="pcre2el"><code>pcre2el</code></h3><p><em><a href="https://github.com/joddie/pcre2el">pcre2el</a> supports conversion between PCRE, Emacs and rx regexp syntax.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pcre2el</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="wgrep"><code>wgrep</code></h3><p><em><a href="https://github.com/mhayashi1120/Emacs-wgrep">wgrep</a> lets you create a writable grep buffer and apply the changes to files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">wgrep</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wgrep-auto-save-buffer</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wgrep-enable-key</span><span class="s">"r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">wgrep-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">wgrep-finish-edit</span><span class="p">)))</span></span></span></code></pre></div><h2 id="minibuffer-completion">minibuffer completion</h2><table><thead><tr><th>package</th><th>what it does</th></tr></thead><tbody><tr><td>vertico</td><td>minibuffer completion UI</td></tr><tr><td>consult</td><td>minibuffer completion backend</td></tr><tr><td>orderless</td><td>minibuffer completion styles</td></tr><tr><td>marginalia</td><td>minibuffer completion annotations</td></tr><tr><td>embark</td><td>minibuffer completion actions</td></tr></tbody></table><p>For an introduction to minibuffer completion, I recommend<a href="https://www.youtube.com/watch?v=d3aaxOqwHhI">this video</a> by Protesilaos Stavrou. For a comprehensive overview of both minibuffer completion and completion at point, I recommend<a href="https://www.youtube.com/watch?v=fnE0lXoe7Y0">this video</a> by Andrew Tropin.</p><h3 id="bindings"><code>bindings</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/bindings.el">bindings</a> defines standard key bindings and some variables.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">bindings</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;C-i&gt;"</span><span class="o">.</span><span class="nv">complete-symbol</span><span class="p">))</span></span></span></code></pre></div><h3 id="vertico"><code>vertico</code></h3><p><em><a href="https://github.com/minad/vertico">vertico</a> is a vertical completion UI based on the default completion system.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">vertico</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:files</span><span class="p">(</span><span class="nb">:defaults</span><span class="s">"extensions/*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:includes</span><span class="p">(</span><span class="nv">vertico-indexed</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-flat</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-grid</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-mouse</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-quick</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-buffer</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-repeat</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-reverse</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-directory</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-multiform</span></span></span><span class="line"><span class="cl"><span class="nv">vertico-unobtrusive</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-multiform-commands</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">consult-line</span><span class="nv">buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-imenu</span><span class="nv">buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-grep</span><span class="nv">buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">isearch-extras-consult-line</span><span class="nv">buffer</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-multiform-categories</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">grid</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-cycle</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-count</span><span class="mi">16</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vertico-multiform-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="c1">;; youtu.be/L_4pLN0gXGI?t=779</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">rfn-eshadow-update-overlay-hook</span><span class="o">.</span><span class="nv">vertico-directory-tidy</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">vertico-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;C-i&gt;"</span><span class="o">.</span><span class="nv">vertico-exit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">vertico-quick-exit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="nv">vertico-previous-group</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-l"</span><span class="o">.</span><span class="nv">vertico-next-group</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-w"</span><span class="o">.</span><span class="nv">vertico-directory-up</span><span class="p">)))</span></span></span></code></pre></div><h3 id="embark"><code>embark</code></h3><p><em><a href="https://github.com/oantolin/embark">embark</a> provides contextually relevant actions in completion menus and in normal buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">embark</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">embark-confirm-act-all</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defvar-keymap</span><span class="nv">embark-yasnippet-completion-actions</span></span></span><span class="line"><span class="cl"><span class="nb">:doc</span><span class="s">"Keymap for actions on yasnippet completions."</span></span></span><span class="line"><span class="cl"><span class="nb">:parent</span><span class="nv">embark-general-map</span></span></span><span class="line"><span class="cl"><span class="s">"d"</span><span class="nf">#'</span><span class="nv">consult-yasnippet-visit-snippet-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'embark-keymap-alist</span><span class="o">'</span><span class="p">(</span><span class="nv">yasnippet</span><span class="o">.</span><span class="nv">embark-yasnippet-completion-actions</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">keymap-set</span><span class="nv">embark-general-map</span><span class="s">"?"</span><span class="nf">#'</span><span class="nv">gptel-quick</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">keymap-set</span><span class="nv">embark-defun-map</span><span class="s">"R"</span><span class="nf">#'</span><span class="nv">gptel-extras-rewrite-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-;"</span><span class="o">.</span><span class="nv">embark-act</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-;"</span><span class="o">.</span><span class="nv">embark-act-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h B"</span><span class="o">.</span><span class="nv">embark-bindings</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">embark-general-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"DEL"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nf">delete-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">helpful-symbol</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">embark-file-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nf">delete-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">embark-general-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">embark-insert</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">embark-identifier-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">citar-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">embark-file-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">files-extras-copy-contents</span><span class="p">)))</span></span></span></code></pre></div><h3 id="consult"><code>consult</code></h3><p><em><a href="https://github.com/minad/consult">consult</a> provides practical commands based on the Emacs completion function<code>completing-read</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'helpful</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">helpful-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-outline</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'markdown-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-outline</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'gfm-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">gfm-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-outline</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'outline</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">outline-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-outline</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; we call this wrapper to silence the annoying two lines of debug info that</span></span></span><span class="line"><span class="cl"><span class="c1">;; `mdfind' outputs, which show briefly in the echo area and pollute the</span></span></span><span class="line"><span class="cl"><span class="c1">;; `consult' search field. the file is in the `bin' directory of this repo.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-locate-args</span><span class="s">"mdfind-wrapper"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-narrow-key</span><span class="s">"&lt;"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-widen-key</span><span class="s">"&gt;"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-grep-max-columns</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">consult-ripgrep-args</span><span class="p">(</span><span class="nf">concat</span><span class="nv">consult-ripgrep-args</span><span class="s">" --hidden"</span><span class="p">))</span><span class="c1">; include hidden files</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-H-l"</span><span class="o">.</span><span class="nv">consult-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-f"</span><span class="o">.</span><span class="nv">consult-find</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-imenu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-b"</span><span class="o">.</span><span class="nv">consult-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-B"</span><span class="o">.</span><span class="nv">consult-project-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-i"</span><span class="o">.</span><span class="nv">consult-info</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-R"</span><span class="o">.</span><span class="nv">consult-history</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-V"</span><span class="o">.</span><span class="nv">consult-yank-pop</span><span class="p">)))</span></span></span></code></pre></div><h3 id="consult-extras"><code>consult-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/consult-extras.el">consult-extras</a> collects my extensions for<code>consult</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">consult-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-F"</span><span class="o">.</span><span class="nv">consult-extras-locate-file-current</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-k"</span><span class="o">.</span><span class="nv">consult-extras-locate-current</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-p"</span><span class="o">.</span><span class="nv">consult-extras-ripgrep-current</span><span class="p">)))</span></span></span></code></pre></div><h3 id="consult-dir"><code>consult-dir</code></h3><p><em><a href="https://github.com/karthink/consult-dir">consult-dir</a> enables insertion of paths into the minibuffer prompt.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult-dir</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">consult</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-dir-default-command</span><span class="ss">'consult-dir-dired</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">minibuffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-d"</span><span class="o">.</span><span class="nv">consult-dir</span><span class="p">)))</span></span></span></code></pre></div><h3 id="consult-git-log-grep"><code>consult-git-log-grep</code></h3><p><em><a href="https://github.com/ghosty141/consult-git-log-grep">consult-git-log-grep</a> provides an interactive way to search the git log using<code>consult</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult-git-log-grep</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">consult</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="consult-yasnippet"><code>consult-yasnippet</code></h3><p><em><a href="https://github.com/mohkale/consult-yasnippet/tree/cdb256d2c50e4f8473c6052e1009441b65b8f8ab">consult-yasnippet</a> provides<code>consult</code> functionality to<code>yasnippet</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult-yasnippet</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; we delay previews to avoid accidentally triggering snippets that execute elisp code</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">consult-customize</span><span class="nv">consult-yasnippet</span><span class="nb">:preview-key</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'vertico-multiform-commands</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">consult-yasnippet</span><span class="nv">grid</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-y"</span><span class="o">.</span><span class="nv">consult-yasnippet</span><span class="p">))</span></span></span></code></pre></div><h3 id="embark-consult"><code>embark-consult</code></h3><p><em><a href="https://github.com/oantolin/embark/blob/master/embark-consult.el">embark-consult</a> provides integration between<code>embark</code> and<code>consult</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">embark-consult</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">embark</span><span class="nv">consult</span><span class="p">)</span></span></span></code></pre></div><h3 id="marginalia"><code>marginalia</code></h3><p><em><a href="https://github.com/minad/marginalia">marginalia</a> displays annotations (such as docstrings) next to completion candidates.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">marginalia</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">marginalia-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="orderless"><code>orderless</code></h3><p><em><a href="https://github.com/oantolin/orderless">orderless</a> is an completion style that matches multiple regexps in any order.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">orderless</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">completion-styles</span><span class="o">'</span><span class="p">(</span><span class="nv">orderless</span><span class="nv">basic</span><span class="nv">partial-completion</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">completion-category-overrides</span><span class="o">'</span><span class="p">((</span><span class="nv">file</span><span class="p">(</span><span class="nv">styles</span><span class="nv">basic</span><span class="nv">partial-completion</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orderless-matching-styles</span><span class="o">'</span><span class="p">(</span><span class="nv">orderless-regexp</span><span class="p">)))</span></span></span></code></pre></div><h3 id="orderless-extras"><code>orderless-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/orderless-extras.el">orderless-extras</a> collects my extensions for<code>orderless</code>.</em></p><p>I define the following style dispatchers to extend<code>orderless</code> functionality:</p><table><thead><tr><th>Suffix</th><th>Matching Style</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td>~</td><td>orderless-flex</td><td>abc~</td><td>Flex/fuzzy matching</td></tr><tr><td>,</td><td>orderless-initialism</td><td>abc,</td><td>Match initials (e.g., &ldquo;abc&rdquo; → &ldquo;a-b-c&rdquo;)</td></tr><tr><td>;</td><td>orderless-prefixes</td><td>abc;</td><td>Match word prefixes</td></tr><tr><td>!</td><td>orderless-without-literal</td><td>!abc</td><td>Exclude matches containing pattern</td></tr></tbody></table><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">orderless-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">orderless</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orderless-style-dispatchers</span><span class="o">'</span><span class="p">(</span><span class="nv">orderless-extras-flex-dispatcher</span></span></span><span class="line"><span class="cl"><span class="nv">orderless-extras-initialism-dispatcher</span></span></span><span class="line"><span class="cl"><span class="nv">orderless-extras-prefixes-dispatcher</span></span></span><span class="line"><span class="cl"><span class="nv">orderless-extras-exclusion-dispatcher</span><span class="p">)))</span></span></span></code></pre></div><h3 id="affe"><code>affe</code></h3><p><em><a href="https://github.com/minad/affe">affe</a> is an Asynchronous Fuzzy Finder for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">affe</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/minad/affe?tab=readme-ov-file#installation-and-configuration</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">affe-regexp-compiler</span><span class="nf">#'</span><span class="nv">affe-orderless-regexp-compiler</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">affe-count</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">affe-orderless-regexp-compiler</span><span class="p">(</span><span class="nv">input</span><span class="nv">_type</span><span class="nv">_ignorecase</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">input</span><span class="p">(</span><span class="nf">cdr</span><span class="p">(</span><span class="nv">orderless-compile</span><span class="nv">input</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="nv">input</span><span class="p">(</span><span class="nv">apply-partially</span><span class="nf">#'</span><span class="nv">orderless--highlight</span><span class="nv">input</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-P"</span><span class="o">.</span><span class="nv">affe-grep</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-K"</span><span class="o">.</span><span class="nv">affe-find</span><span class="p">)))</span></span></span></code></pre></div><h3 id="nerd-icons-completion"><code>nerd-icons-completion</code></h3><p><em><a href="https://github.com/rainstormstudio/nerd-icons-completion">nerd-icons-completion</a> displays nerd icons in completion candidates.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">nerd-icons-completion</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">marginalia</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">nerd-icons-completion-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">marginalia-mode-hook</span><span class="o">.</span><span class="nv">nerd-icons-completion-marginalia-setup</span><span class="p">))</span></span></span></code></pre></div><h3 id="ido"><code>ido</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/ido.el">ido</a> is a completion package for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ido</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">dired</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'ido-file-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">ido-find-file</span><span class="p">)))</span></span></span></code></pre></div><h3 id="which-key"><code>which-key</code></h3><p><em><a href="https://github.com/justbur/emacs-which-key">which-key</a> displays available keybindings in a popup.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">which-key</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">which-key-idle-delay</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">which-key-mode</span><span class="p">))</span></span></span></code></pre></div><h2 id="completion-at-point">completion at point</h2><table><thead><tr><th>package</th><th>what it does</th></tr></thead><tbody><tr><td>corfu</td><td>completion at point UI</td></tr><tr><td>cape</td><td>completion at point backend</td></tr></tbody></table><h3 id="corfu"><code>corfu</code></h3><p><em><a href="https://github.com/minad/corfu">corfu</a> enhances completion at point with a small completion popup.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">corfu</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:files</span><span class="p">(</span><span class="nb">:defaults</span><span class="s">"extensions/*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:includes</span><span class="p">(</span><span class="nv">corfu-info</span></span></span><span class="line"><span class="cl"><span class="nv">corfu-echo</span></span></span><span class="line"><span class="cl"><span class="nv">corfu-history</span></span></span><span class="line"><span class="cl"><span class="nv">corfu-popupinfo</span></span></span><span class="line"><span class="cl"><span class="nv">corfu-quick</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-auto</span><span class="no">t</span><span class="p">)</span><span class="c1">;; Enable auto completion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-quit-no-match</span><span class="no">t</span><span class="p">)</span><span class="c1">;; Automatically quit if there is no match</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-cycle</span><span class="nv">vertico-cycle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-count</span><span class="nv">vertico-count</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-auto-prefix</span><span class="mi">3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-auto-delay</span><span class="mf">0.5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-popupinfo-delay</span><span class="mf">0.1</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">corfu-default</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-corfu-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'corfu-history</span><span class="ss">'savehist-additional-variables</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prog-mode-hook</span><span class="o">.</span><span class="nv">corfu-popupinfo-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prog-mode-hook</span><span class="o">.</span><span class="nv">corfu-echo-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">corfu-mode-hook</span><span class="o">.</span><span class="nv">corfu-history-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">corfu-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">corfu-quick-complete</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">corfu-complete</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"RET"</span><span class="o">.</span><span class="nv">corfu-complete</span><span class="p">)))</span></span></span></code></pre></div><h3 id="corfu-extras"><code>corfu-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/corfu-extras.el">corfu-extras</a> collects my extensions for<code>corfu</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">corfu-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-setup-hook</span><span class="o">.</span><span class="nv">corfu-extras-enable-always-in-minibuffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">corfu-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-m"</span><span class="o">.</span><span class="nv">corfu-extras-move-to-minibuffer</span><span class="p">)))</span></span></span></code></pre></div><h3 id="cape"><code>cape</code></h3><p><em><a href="https://github.com/minad/cape">cape</a> provides completion-at-point extensions</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">cape</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">corfu</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">cape-dabbrev-min-length</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">cape-enable-completions</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Enable file and emoji completion in the current buffer."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-local</span><span class="nv">completion-at-point-functions</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="nf">#'</span><span class="nv">cape-file</span><span class="nv">completion-at-point-functions</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nv">completion-at-point-functions</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="nf">#'</span><span class="nv">cape-emoji</span><span class="nv">completion-at-point-functions</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">text-mode-hook</span><span class="nv">prog-mode-hook</span><span class="p">)</span><span class="o">.</span><span class="nv">cape-enable-completions</span><span class="p">))</span></span></span></code></pre></div><h3 id="corg"><code>corg</code></h3><p><em><a href="https://github.com/isamert/corg.el">corg</a> provides provides completion-at-point for org-mode source block and dynamic block headers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">corg</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"isamert/corg.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-mode-hook</span><span class="o">.</span><span class="nv">corg-setup</span><span class="p">))</span></span></span></code></pre></div><h2 id="help">help</h2><h3 id="help"><code>help</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/help.el">help</a> is the built-in help system.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">help</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">help-window-select</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lossage-size</span><span class="mi">10000</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-h C-k"</span><span class="o">.</span><span class="nv">describe-keymap</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h C-."</span><span class="o">.</span><span class="nv">display-local-help</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">help-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-help</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">input-decode-map</span></span></span><span class="line"><span class="cl"><span class="p">([</span><span class="sc">?\C</span><span class="nv">-m</span><span class="p">]</span><span class="o">.</span><span class="p">[</span><span class="nv">C-m</span><span class="p">])</span></span></span><span class="line"><span class="cl"><span class="p">([</span><span class="sc">?\C</span><span class="nv">-i</span><span class="p">]</span><span class="o">.</span><span class="p">[</span><span class="nv">C-i</span><span class="p">])))</span></span></span></code></pre></div><h3 id="help-at-pt"><code>help-at-pt</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/help-at-pt.el">help-at-pt</a> displays local help based on text properties at point.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">help-at-pt</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">help-at-pt-display-when-idle</span><span class="ss">'never</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">help-at-pt-timer-delay</span><span class="mi">1</span><span class="p">)</span><span class="c1">; show help immediately when enabled</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">help-at-pt-set-timer</span><span class="p">))</span><span class="c1">; set timer, thus enabling local help</span></span></span></code></pre></div><h3 id="helpful"><code>helpful</code></h3><p><em><a href="https://github.com/Wilfred/helpful">helpful</a> enhances the Emacs help buffer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">helpful</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; always use `helpful', even when `describe-function' is called by a program</span></span></span><span class="line"><span class="cl"><span class="c1">;; (e.g. `transient')</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'describe-function</span><span class="nb">:override</span><span class="nf">#'</span><span class="nv">helpful-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">minibuffer-setup-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nb">require</span><span class="ss">'helpful</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-h k"</span><span class="o">.</span><span class="nv">helpful-key</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h f"</span><span class="o">.</span><span class="nv">helpful-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h c"</span><span class="o">.</span><span class="nv">helpful-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h o"</span><span class="o">.</span><span class="nv">helpful-symbol</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h v"</span><span class="o">.</span><span class="nv">helpful-variable</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h ."</span><span class="o">.</span><span class="nv">helpful-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">helpful-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-help</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">files-extras-copy-as-kill-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="info"><code>info</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/info.el">info</a> is the Info documentation browser.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">info</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'Info-history-list</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">Info-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-info</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">Info-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"/"</span><span class="o">.</span><span class="nv">Info-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">Info-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">Info-backward-node</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">Info-forward-node</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">Info-menu</span><span class="p">)))</span></span></span></code></pre></div><h3 id="man"><code>man</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/man.el">man</a> is a manual page viewer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">man</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">Man-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-man</span><span class="p">)))</span></span></span></code></pre></div><h3 id="woman"><code>woman</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/woman.el">woman</a> browses manual pages without the man command.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">woman</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">woman-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-woman</span><span class="p">)))</span></span></span></code></pre></div><h3 id="shortdoc"><code>shortdoc</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/e7260d4eb3ed1bebcaa9e2b934f162d4bb42e413/lisp/emacs-lisp/shortdoc.el">shortdoc</a> provides short function summaries.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">shortdoc</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-h u"</span><span class="o">.</span><span class="nv">shortdoc-display-group</span><span class="p">))</span></span></span></code></pre></div><h3 id="find-func"><code>find-func</code></h3><p><em>find-func finds the definition of the Emacs Lisp function near point.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">find-func</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-L"</span><span class="o">.</span><span class="nv">find-library</span><span class="p">))</span></span></span></code></pre></div><h3 id="elisp-refs"><code>elisp-refs</code></h3><p><em><a href="https://github.com/Wilfred/elisp-refs">elisp-refs</a> finds references to functions, macros and variables in Elisp files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">elisp-refs</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">elisp-refs-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-help</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elisp-demos"><code>elisp-demos</code></h3><p><em><a href="https://github.com/xuchunyang/elisp-demos">elisp-demos</a> displays examples for many Elisp functions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elisp-demos</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">helpful</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'helpful-update</span><span class="nb">:after</span><span class="ss">'elisp-demos-advice-helpful-update</span><span class="p">))</span></span></span></code></pre></div><h2 id="keyboard-macros">keyboard macros</h2><h3 id="kmacro"><code>kmacro</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/kmacro.el">kmacro</a> provides a simplified interface for keyboard macros.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">kmacro</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">kmacro-set-counter</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">var</span><span class="o">'</span><span class="p">(</span><span class="nv">kmacro-ring</span><span class="nv">last-kbd-macro</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="nv">var</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-M-s-h"</span><span class="o">.</span><span class="nv">kmacro-end-or-call-macro</span><span class="p">)</span><span class="c1">; = H-h, to circumvent OSX mapping</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-H"</span><span class="o">.</span><span class="nv">kmacro-start-macro-or-insert-counter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-s-h"</span><span class="o">.</span><span class="nv">kmacro-set-counter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-h"</span><span class="o">.</span><span class="nv">kmacro-edit-macro</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-A-h"</span><span class="o">.</span><span class="nv">kmacro-bind-to-key</span><span class="p">)))</span></span></span></code></pre></div><h3 id="kmacro-extras"><code>kmacro-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/kmacro-extras.el">kmacro-extras</a> collects my extensions for<code>kmacro</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">kmacro-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-A-h"</span><span class="o">.</span><span class="nv">kmacro-extras-counter-toggle-alpha-number</span><span class="p">))</span></span></span></code></pre></div><h2 id="shell">shell</h2><h3 id="simple"><code>simple</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/simple.el">simple</a> configures shell command behaviour for interactive use.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shell-command-switch</span><span class="s">"-ic"</span><span class="p">)</span><span class="c1">; https://stackoverflow.com/a/12229404/4479455</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">async-shell-command-buffer</span><span class="ss">'new-buffer</span><span class="p">))</span><span class="c1">; don't ask for confirmation before running command in a new buffer</span></span></span></code></pre></div><h3 id="shell"><code>shell</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/shell.el">shell</a> provides a shell-mode interface for inferior shell processes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">shell</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="c1">;; remove maddening "saving session" messages in non-interactive shells</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">filtered-env</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">seq-filter</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">var</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">var-name</span><span class="p">(</span><span class="nf">car</span><span class="p">(</span><span class="nv">split-string</span><span class="nv">var</span><span class="s">"="</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nf">member</span><span class="nv">var-name</span><span class="o">'</span><span class="p">(</span><span class="s">"TERM_PROGRAM"</span><span class="s">"TERM_SESSION_ID"</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="nv">process-environment</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">process-environment</span><span class="nv">filtered-env</span></span></span><span class="line"><span class="cl"><span class="nv">shell-command-environment</span><span class="nv">filtered-env</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-s"</span><span class="o">.</span><span class="nv">shell</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">shell-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">comint-previous-input</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">comint-next-input</span><span class="p">)))</span></span></span></code></pre></div><h3 id="eshell"><code>eshell</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/eshell/eshell.el">eshell</a> is the Emacs shell, a shell implemented entirely in Emacs Lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">eshell</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-banner-message</span><span class="s">""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-save-history-on-exit</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-hist-ignoredups</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-history-size</span><span class="mi">100000</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-last-dir-ring-size</span><span class="mi">1000</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'esh-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-e"</span><span class="o">.</span><span class="nv">eshell</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">eshell-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="nv">yas-next-field-or-maybe-expand</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="nv">yas-next-field-or-maybe-expand</span><span class="p">)</span><span class="c1">; why is this necessary for eshell only?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-z"</span><span class="o">.</span><span class="nv">eshell-kill-input</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-m"</span><span class="o">.</span><span class="nf">beginning-of-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">eshell-previous-matching-input-from-input</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">eshell-next-matching-input-from-input</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">eshell/clear</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">eshell-send-eof-to-process</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="em-hist"><code>em-hist</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/eshell/em-hist.el">em-hist</a> provides history management for eshell.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">em-hist</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-hist-ignoredups</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-save-history-on-exit</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="eshell-syntax-highlighting"><code>eshell-syntax-highlighting</code></h3><p><em><a href="https://github.com/akreisher/eshell-syntax-highlighting">eshell-syntax-highlighting</a> provides syntax highlighting for eshell-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">eshell-syntax-highlighting</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">eshell</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-mode-hook</span><span class="o">.</span><span class="nv">eshell-syntax-highlighting-global-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="dwim-shell-command"><code>dwim-shell-command</code></h3><p><em><a href="https://github.com/xenodium/dwim-shell-command">dwim-shell-command</a> supports Emacs shell commands with dwim behaviour.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">dwim-shell-command</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"xenodium/dwim-shell-command"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="eat"><code>eat</code></h3><p><em><a href="https://codeberg.org/akib/emacs-eat">eat</a> is a terminal emulator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">eat</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">codeberg</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"akib/emacs-eat"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"*.el"</span><span class="p">(</span><span class="s">"term"</span><span class="s">"term/*.el"</span><span class="p">)</span><span class="s">"*.texi"</span></span></span><span class="line"><span class="cl"><span class="s">"*.ti"</span><span class="p">(</span><span class="s">"terminfo/e"</span><span class="s">"terminfo/e/*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"terminfo/65"</span><span class="s">"terminfo/65/*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"integration"</span><span class="s">"integration/*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:exclude</span><span class="s">".dir-locals.el"</span><span class="s">"*-tests.el"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eat-term-name</span><span class="s">"xterm-256color"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-load-hook</span><span class="o">.</span><span class="nv">eat-eshell-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eshell-load-hook</span><span class="o">.</span><span class="nv">eat-eshell-visual-command-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="eat-extras"><code>eat-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/eat-extras.el">eat-extras</a> collects my extensions for<code>eat</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">eat-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">eat</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eat-mode-hook</span><span class="o">.</span><span class="nv">eat-extras-use-fixed-pitch-font</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eat-extras-setup-semi-char-mode-map</span><span class="p">))</span></span></span></code></pre></div><h3 id="vterm"><code>vterm</code></h3><p><em><a href="https://github.com/akermu/emacs-libvterm">vterm</a> is another terminal emulator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">vterm</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vterm-always-compile-module</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="vterm-extras"><code>vterm-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/vterm-extras.el">vterm-extras</a> collects my extensions for<code>vterm</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">vterm-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">vterm</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">vterm-extras-setup-keymap</span><span class="p">))</span></span></span></code></pre></div><h2 id="spelling-and-grammar">spelling &amp; grammar</h2><h3 id="jinx"><code>jinx</code></h3><p><em><a href="https://github.com/minad/jinx">jinx</a> is a highly performant spell-checker for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">jinx</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">jinx-languages</span><span class="s">"en"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">jinx-misspelled</span><span class="nb">:underline</span><span class="o">'</span><span class="p">(</span><span class="nb">:color</span><span class="s">"#008000"</span><span class="nb">:style</span><span class="nv">wave</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'vertico-multiform-categories</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">jinx</span><span class="nv">grid</span><span class="p">(</span><span class="nv">vertico-grid-annotate</span><span class="o">.</span><span class="mi">20</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">text-mode-hook</span><span class="nv">prog-mode-hook</span><span class="nv">conf-mode-hook</span><span class="p">)</span><span class="o">.</span><span class="nv">jinx-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-p"</span><span class="o">.</span><span class="nv">jinx-correct</span><span class="p">)))</span></span></span></code></pre></div><h3 id="jinx-extras"><code>jinx-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/jinx-extras.el">jinx-extras</a> collects my extensions for<code>jinx</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">jinx-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">jinx</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-M-p"</span><span class="o">.</span><span class="nv">jinx-extras-toggle-languages</span><span class="p">)))</span></span></span></code></pre></div><h3 id="flycheck"><code>flycheck</code></h3><p><em><a href="https://github.com/flycheck/flycheck">flycheck</a> is a syntax-checker for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">flycheck</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; move temporary flycheck files to a temporary directory</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-temp-prefix</span><span class="p">(</span><span class="nf">concat</span><span class="nv">temporary-file-directory</span><span class="s">"flycheck-"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-emacs-lisp-load-path</span><span class="ss">'inherit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-indication-mode</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-display-errors-delay</span><span class="mf">0.5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-checker-error-threshold</span><span class="mi">10000</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; org-lint runs synchronously in-process; it freezes Emacs on large org files</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-disabled-checkers</span><span class="o">'</span><span class="p">(</span><span class="nv">org-lint</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/skeeto/elfeed/pull/448#issuecomment-1120336279</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-global-modes</span><span class="o">'</span><span class="p">(</span><span class="nv">not</span><span class="o">.</span><span class="p">(</span><span class="nv">elfeed-search-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">flycheck-error</span><span class="nb">:underline</span><span class="o">'</span><span class="p">(</span><span class="nb">:color</span><span class="s">"#ff0000"</span><span class="nb">:style</span><span class="nv">wave</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-warning</span><span class="nb">:underline</span><span class="o">'</span><span class="p">(</span><span class="nb">:color</span><span class="s">"#0000ff"</span><span class="nb">:style</span><span class="nv">wave</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">find-file-hook</span><span class="o">.</span><span class="nv">global-flycheck-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-src-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable</span><span class="ss">`emacs-lisp-checkdoc'</span><span class="s"> in</span><span class="ss">`org-src'</span><span class="s"> blocks."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-local</span><span class="nv">flycheck-disabled-checkers</span><span class="o">'</span><span class="p">(</span><span class="nv">emacs-lisp-checkdoc</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">after-change-major-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable flycheck in selected buffers."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">member</span><span class="p">(</span><span class="nf">buffer-name</span><span class="p">)</span><span class="o">'</span><span class="p">(</span><span class="s">"*scratch*"</span><span class="s">"notes"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-mode</span><span class="mi">-1</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">flycheck-next-error</span><span class="p">))</span></span></span></code></pre></div><h3 id="consult-flycheck"><code>consult-flycheck</code></h3><p><em><a href="https://github.com/minad/consult-flycheck">consult-flycheck</a> integrates<code>flycheck</code> with<code>consult</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult-flycheck</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">consult</span><span class="nv">flyckeck</span><span class="p">)</span></span></span></code></pre></div><h3 id="flycheck-ledger"><code>flycheck-ledger</code></h3><p><em><a href="https://github.com/purcell/flycheck-ledger">flycheck-ledger</a> provides<code>flycheck</code> support for<code>ledger-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">flycheck-ledger</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">flycheck</span><span class="nv">ledger-mode</span><span class="p">)</span></span></span></code></pre></div><h3 id="flycheck-languagetool"><code>flycheck-languagetool</code></h3><p><em><a href="https://github.com/emacs-languagetool/flycheck-languagetool">flycheck-languagetool</a> provides<code>flycheck</code> support for<a href="https://languagetool.org/">LanguageTool</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">flycheck-languagetool</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/flycheck-languagetool"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"fix/guard-stale-buffer-positions"</span><span class="p">)</span><span class="c1">; https://github.com/emacs-languagetool/flycheck-languagetool/pull/40</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">flycheck</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">flycheck-languagetool-server-jar</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">expand-file-name</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-external-repos</span><span class="s">"LanguageTool/languagetool-server.jar"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-languagetool-check-params</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"level"</span><span class="o">.</span><span class="s">"picky"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"disabledRules"</span><span class="o">.</span><span class="s">"ARROWS,DASH_RULE,DATE_NEW_YEAR,EN_QUOTES,GITHUB,WHITESPACE_RULE"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">flycheck-languagetool-enable</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Enable</span><span class="ss">`flycheck-languagetool'</span><span class="s"> in selected buffers."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nb">or</span><span class="p">(</span><span class="nv">derived-mode-p</span><span class="ss">'forge-post-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'gfm-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'mhtml-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'flycheck-error-message-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'mu4e-compose-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'mu4e-view-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'org-journal-mode</span></span></span><span class="line"><span class="cl"><span class="ss">'org-msg-edit-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nf">file-directory-p</span><span class="nv">default-directory</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-select-checker</span><span class="ss">'languagetool</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">flycheck-languagetool-toggle</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Toggle the LanguageTool checker in the current buffer."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">eq</span><span class="nv">flycheck-checker</span><span class="ss">'languagetool</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-local</span><span class="nv">flycheck-checker</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"LanguageTool disabled"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-select-checker</span><span class="ss">'languagetool</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"LanguageTool enabled"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">markdown-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">org-mode-hook</span></span></span><span class="line"><span class="cl"><span class="nv">org-msg-edit-mode-hook</span><span class="p">)</span><span class="o">.</span><span class="nv">flycheck-languagetool-enable</span><span class="p">))</span></span></span></code></pre></div><h3 id="flymake-mdl"><code>flymake-mdl</code></h3><p><em><a href="https://github.com/MicahElliott/flymake-mdl">flymake-mdl</a> provides a flymake backend for markdownlint.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">flymake-mdl</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"MicahElliott/flymake-mdl"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">markdown-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h2 id="prose">prose</h2><h3 id="text-mode"><code>text-mode</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/textmodes/text-mode.el">text-mode</a> is the major mode for editing plain text.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">text-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">text-mode-hook</span><span class="o">.</span><span class="nv">simple-extras-visual-line-mode-enhanced</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">text-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable ispell completion in text mode."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'completion-at-point-functions</span><span class="nf">#'</span><span class="nv">ispell-completion-at-point</span><span class="no">t</span><span class="p">))))</span></span></span></code></pre></div><h3 id="atomic-chrome"><code>atomic-chrome</code></h3><p><em><a href="https://github.com/KarimAziev/atomic-chrome">atomic chrome</a> enables editing of browser input fields in Emacs.</em></p><p>I use a fork that is better maintained, together with the associated<a href="https://github.com/KarimAziev/chrome-emacs">Chrome Emacs</a> browser extension.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">atomic-chrome</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:repo</span><span class="s">"KarimAziev/atomic-chrome"</span></span></span><span class="line"><span class="cl"><span class="nb">:host</span><span class="nv">github</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">atomic-chrome-default-major-mode</span><span class="ss">'markdown-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">atomic-chrome-create-file-strategy</span><span class="ss">'buffer</span><span class="p">)</span><span class="c1">; needed for proper recognition of modes</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">atomic-chrome-url-major-mode-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"github\\.com"</span><span class="o">.</span><span class="nv">gfm-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"wikipedia\\.org"</span><span class="o">.</span><span class="nv">mediawiki-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"timelines\\.issarice\\.com"</span><span class="o">.</span><span class="nv">mediawiki-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">atomic-chrome-extension-type-list</span><span class="o">'</span><span class="p">(</span><span class="nv">atomic-chrome</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">atomic-chrome-start-server</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">atomic-chrome-edit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">atomic-chrome-close-current-buffer</span><span class="p">)))</span></span></span></code></pre></div><h3 id="markdown-mode"><code>markdown-mode</code></h3><p><em><a href="https://github.com/jrblevin/markdown-mode">markdown-mode</a> is a major mode for editing Markdown-formatted text.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">markdown-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">markdown-fontify-code-blocks-natively</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">markdown-command</span><span class="s">"pandoc --from markdown --to html"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">markdown-disable-tooltip-prompt</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">markdown-italic-underscore</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; pop code block indirect buffers in the same window, mirroring the org behavior</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'display-buffer-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="s">"\\*edit-indirect.*\\*"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">display-buffer-same-window</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">gfm-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">markdown-insert-gfm-code-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">markdown-edit-code-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-t"</span><span class="o">.</span><span class="nv">markdown-mode-extras-copy-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">markdown-outline-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">markdown-outline-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-f"</span><span class="o">.</span><span class="nv">markdown-footnote-goto-text</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-r"</span><span class="o">.</span><span class="nv">markdown-footnote-return</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">markdown-insert-bold</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">markdown-insert-code</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">markdown-insert-footnote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">markdown-insert-italic</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">markdown-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">markdown-preview</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">markdown-insert-gfm-code-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">markdown-edit-code-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-t"</span><span class="o">.</span><span class="nv">markdown-mode-extras-copy-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">markdown-outline-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">markdown-outline-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-f"</span><span class="o">.</span><span class="nv">markdown-footnote-goto-text</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-r"</span><span class="o">.</span><span class="nv">markdown-footnote-return</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">markdown-insert-bold</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">markdown-insert-code</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">markdown-insert-footnote</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">markdown-insert-italic</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">markdown-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">markdown-preview</span><span class="p">)))</span></span></span></code></pre></div><h3 id="markdown-mode-extras"><code>markdown-mode-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/markdown-mode-extras.el">markdown-mode-extras</a> collects my extensions for<code>markdown-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">markdown-mode-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">gfm-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-t"</span><span class="o">.</span><span class="nv">markdown-mode-extras-copy-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">markdown-mode-extras-insert-locator</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">markdown-mode-extras-remove-url-in-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">markdown-mode-extras-paste-with-conversion</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-v"</span><span class="o">.</span><span class="nv">markdown-mode-extras-org-paste-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-t"</span><span class="o">.</span><span class="nv">markdown-mode-extras-copy-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">markdown-mode-extras-insert-locator</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">markdown-mode-extras-remove-url-in-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">markdown-mode-extras-paste-with-conversion</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-v"</span><span class="o">.</span><span class="nv">markdown-mode-extras-org-paste-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-v"</span><span class="o">.</span><span class="nv">markdown-mode-extras-org-paste-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="grip-mode"><code>grip-mode</code></h3><p><em><a href="https://github.com/seagle0128/grip-mode">grip-mode</a> provides org-mode and Github-flavored Markdown preview using grip.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">grip-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'markdown-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">grip-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">grip-github-user</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"user"</span><span class="s">"tlon/core/api.github.com/grip-mode"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">grip-github-password</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"tlon/core/api.github.com/grip-mode"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'xwidget</span><span class="p">))</span></span></span></code></pre></div><h3 id="xwidget"><code>xwidget</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/xwidget.el">xwidget</a> provides API functions for xwidgets.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">xwidget</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; do not prompt user when attempting to kill xwidget buffer</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'kill-buffer-query-functions</span><span class="nf">#'</span><span class="nv">xwidget-kill-buffer-query-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">xwidget-webkit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">xwidget-webkit-scroll-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">xwidget-webkit-scroll-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">xwidget-webkit-scroll-top</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">xwidget-webkit-scroll-bottom</span><span class="p">)))</span></span></span></code></pre></div><h3 id="edit-indirect"><code>edit-indirect</code></h3><p><em><a href="https://github.com/Fanael/edit-indirect">edit-indirect</a> supports editing regions in separate buffers.</em></p><p>This package is required by the<code>markdown-mode</code> command<code>markdown-edit-code-block</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">edit-indirect</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">markdown-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">edit-indirect-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">edit-indirect-commit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="mediawiki"><code>mediawiki</code></h3><p><em><a href="https://github.com/hexmode/mediawiki-el">mediawiki</a> is an Emacs interface to editing mediawiki sites.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">mediawiki</span></span></span><span class="line"><span class="cl"><span class="c1">;; :ensure (:tag "2.4.3") ; otherwise can't authenticate; https://github.com/hexmode/mediawiki-el/issues/48</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mediawiki-site-alist</span><span class="o">`</span><span class="p">((</span><span class="s">"Wikipedia"</span></span></span><span class="line"><span class="cl"><span class="s">"https://en.wikipedia.org/w/"</span></span></span><span class="line"><span class="cl"><span class="s">"Sir Paul"</span></span></span><span class="line"><span class="cl"><span class="o">,</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"chrome/auth.wikimedia.org/Sir_Paul"</span><span class="p">)</span><span class="s">""</span></span></span><span class="line"><span class="cl"><span class="nb">:description</span><span class="s">"English Wikipedia"</span><span class="nb">:first-page</span><span class="s">"Main Page"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mediawiki-draft-data-file</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-notes</span><span class="s">"drafts.wiki"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">mediawiki-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">mediawiki-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">mediawiki-prev-header</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">mediawiki-next-header</span><span class="p">)))</span></span></span></code></pre></div><h3 id="wikipedia"><code>wikipedia</code></h3><p><em><a href="https://github.com/benthamite/wikipedia">wikipedia</a> is an Emacs interface for Wikipedia, with a focus on fast editing workflows, review tools, and optional local/offline browsing of watched pages.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">wikipedia</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/wikipedia"</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-draft-directory</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-google-drive</span><span class="s">"wikipedia"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-ai-model</span><span class="ss">'gemini-flash-lite-latest</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-auto-update-mode</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-ai-review-auto</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-ai-summarize-auto</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-watchlist-score-reason-auto</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">wikipedia-watchlist-sort-by-score</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-p"</span><span class="o">.</span><span class="nv">wikipedia-transient</span><span class="p">)))</span></span></span></code></pre></div><h3 id="gdocs"><code>gdocs</code></h3><p><em><a href="https://github.com/benthamite/gdocs">gdocs</a> provides Emacs integration with Google Docs</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">gdocs</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/gdocs"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdocs-accounts</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="s">"personal"</span><span class="o">.</span><span class="p">((</span><span class="nv">client-id</span><span class="o">.</span><span class="o">,</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"gdocs-client-id"</span><span class="s">"chrome/cloud.google.com"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">client-secret</span><span class="o">.</span><span class="o">,</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"gdocs-client-secret"</span><span class="s">"chrome/cloud.google.com"</span><span class="p">)))))))</span></span></span></code></pre></div><h3 id="gdrive"><code>gdrive</code></h3><p><em><a href="https://github.com/benthamite/gdrive">gdrive</a> is an interface to Google Drive.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">gdrive</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/gdrive"</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-file</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dotemacs</span><span class="s">"etc/gdrive-users.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">gdrive-extras-mark-multiple-and-share</span><span class="p">(</span><span class="kp">&amp;optional</span><span class="nv">file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Search for each line in FILE and share the selected results.</span></span></span><span class="line"><span class="cl"><span class="s">The file should contain one search query per line."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'gdrive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdrive-mark-clear</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">if-let</span><span class="p">((</span><span class="nv">file</span><span class="p">(</span><span class="nb">or</span><span class="nv">file</span><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nv">y-or-n-p</span><span class="s">"Read file? "</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">read-file-name</span><span class="s">"File: "</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">lines</span><span class="p">(</span><span class="nv">files-extras-lines-to-list</span><span class="nv">file</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">line</span><span class="nv">lines</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdrive-extras--mark-matching-results</span><span class="nv">line</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdrive-extras--mark-matching-results</span><span class="p">(</span><span class="nf">read-string</span><span class="s">"ID: "</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdrive-share-results</span><span class="nv">gdrive-marked-files</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">gdrive-extras--mark-matching-results</span><span class="p">(</span><span class="nf">string</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Mark the files that match STRING."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">results</span><span class="p">(</span><span class="nv">gdrive-act-on-selected-search-results</span><span class="nf">string</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gdrive-mark-results</span><span class="nv">results</span><span class="p">))))</span></span></span></code></pre></div><h3 id="ledger-mode"><code>ledger-mode</code></h3><p><em><a href="https://github.com/ledger/ledger-mode">ledger-mode</a> is a major mode for interacting with the Ledger accounting system.</em></p><p>To populate the database of historical prices:</p><ul><li>commodities:<a href="https://github.com/LukasJoswiak/blog-code/blob/master/2020/tracking-commodity-prices-ledger/prices.py">https://github.com/LukasJoswiak/blog-code/blob/master/2020/tracking-commodity-prices-ledger/prices.py</a><ul><li>accompanying post:<a href="https://lukasjoswiak.com/tracking-commodity-prices-in-ledger/">https://lukasjoswiak.com/tracking-commodity-prices-in-ledger/</a></li></ul></li><li>crypto:<a href="https://github.com/cjtapper/coinprices">https://github.com/cjtapper/coinprices</a></li><li>currencies:<a href="https://github.com/wakatara/get-FX">https://github.com/wakatara/get-FX</a><ul><li>couldn&rsquo;t make it work, so I just entered the rates manually once and will use those</li></ul></li></ul><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ledger-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-default-date-format</span><span class="nv">ledger-iso-date-format</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-reconcile-default-commodity</span><span class="s">"ARS"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-mode-extras-currencies</span><span class="o">'</span><span class="p">(</span><span class="s">"USD"</span><span class="s">"EUR"</span><span class="s">"GBP"</span><span class="s">"ARS"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-schedule-file</span><span class="nv">paths-file-tlon-ledger-schedule-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-schedule-look-forward</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-schedule-look-backward</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">report</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"net worth"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' -f %(ledger-file) bal --strict"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"net worth (USD)"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' -f %(ledger-file) --price-db .pricedb --exchange USD bal ^assets ^liabilities --strict"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"account"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' -f %(ledger-file) reg %(account) --price-db .pricedb"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"account (USD)"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' -f %(ledger-file) reg %(account) --price-db .pricedb --exchange USD --limit \"commodity == 'USD'\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"cost basis"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' -f %(ledger-file) --basis bal %(account) --strict"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"account (unrounded)"</span></span></span><span class="line"><span class="cl"><span class="s">"%(binary) --date-format '%Y-%m-%d' --unround -f %(ledger-file) reg %(account)"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'ledger-reports</span><span class="nv">report</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ledger-reconcile-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">mouse-wheel-mode</span><span class="mi">-1</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ledger-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">ledger-navigate-next-xact-or-directive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">ledger-navigate-prev-xact-or-directive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-e"</span><span class="o">.</span><span class="nv">ledger-toggle-current-transaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-="</span><span class="o">.</span><span class="nv">ledger-reconcile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">ledger-add-transaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">ledger-post-edit-amount</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">ledger-delete-current-transaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ledger-occur</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">ledger-report-goto</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">ledger-insert-effective-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">ledger-report-quit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">ledger-display-ledger-stats</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">ledger-report-edit-report</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">ledger-display-balance-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-q"</span><span class="o">.</span><span class="nv">ledger-post-align-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">ledger-report</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">ledger-report-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">ledger-schedule-upcoming</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">ledger-copy-transaction-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">ledger-fully-complete-xact</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-y"</span><span class="o">.</span><span class="nv">ledger-copy-transaction-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">ledger-report-redo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ledger-report-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">ledger-navigate-next-xact-or-directive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">ledger-navigate-prev-xact-or-directive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ledger-reconcile-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">ledger-reconcile-quit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ledger-mode-extras"><code>ledger-mode-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/ledger-mode-extras.el">ledger-mode-extras</a> collects my extensions for<code>ledger-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">ledger-mode-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ledger-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ledger-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-SPC"</span><span class="o">.</span><span class="nv">ledger-mode-extras-new-entry-below</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">ledger-mode-extras-sort-region-or-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">ledger-mode-extras-extras-sort-region-or-buffer-reversed</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-a"</span><span class="o">.</span><span class="nv">ledger-mode-extras-report-account</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-b"</span><span class="o">.</span><span class="nv">ledger-mode-extras-decrease-date-by-one-day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-c"</span><span class="o">.</span><span class="nv">ledger-mode-extras-copy-transaction-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-f"</span><span class="o">.</span><span class="nv">ledger-mode-extras-increase-date-by-one-day</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-t"</span><span class="o">.</span><span class="nv">ledger-mode-extras-sort-region-or-buffer-reversed</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-u"</span><span class="o">.</span><span class="nv">ledger-mode-extras-report-net-worth-USD</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-w"</span><span class="o">.</span><span class="nv">ledger-mode-extras-report-net-worth</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">ledger-mode-extras-align-and-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-c"</span><span class="o">.</span><span class="nv">ledger-mode-extras-copy-transaction-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">ledger-mode-extras-kill-transaction-at-point</span><span class="p">)))</span></span></span></code></pre></div><h2 id="translation">translation</h2><h3 id="tlon"><code>tlon</code></h3><p><em><a href="https://github.com/tlon-team/tlon">tlon</a> is a set of Emacs commands that my team uses in various contexts.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">tlon</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"tlon-team/tlon.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span><span class="c1">; clone entire repo, not just last commit</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">paths</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'forge</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">forge-topic-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">tlon-visit-counterpart-or-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"'"</span><span class="o">.</span><span class="nv">tlon-open-forge-file</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'magit</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">magit-status-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">tlon-visit-counterpart-or-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"'"</span><span class="o">.</span><span class="nv">tlon-open-forge-file</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'markdown-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">markdown-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-;"</span><span class="o">.</span><span class="nv">tlon-md-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-e"</span><span class="o">.</span><span class="nv">tlon-yaml-edit-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">tlon-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">tlon-md-insert-locator</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">tlon-md-insert-entity</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-SPC"</span><span class="o">.</span><span class="nv">tlon-md-beginning-of-buffer-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-&lt;tab&gt;"</span><span class="o">.</span><span class="nv">tlon-md-end-of-buffer-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">gfm-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-;"</span><span class="o">.</span><span class="nv">tlon-md-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-e"</span><span class="o">.</span><span class="nv">tlon-yaml-edit-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">tlon-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">tlon-md-insert-locator</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">tlon-md-insert-entity</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-SPC"</span><span class="o">.</span><span class="nv">tlon-md-beginning-of-buffer-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-&lt;tab&gt;"</span><span class="o">.</span><span class="nv">tlon-md-end-of-buffer-dwim</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tlon-forg-archive-todo-on-close</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tlon-forg-sort-after-sync-or-capture</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">60</span><span class="mi">60</span><span class="p">)</span><span class="no">t</span><span class="nf">#'</span><span class="nv">tlon-pull-issues-in-all-repos</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'tlon-db</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">tlon-db-extras--suppress-debugger</span><span class="p">(</span><span class="nv">orig-fun</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Call ORIG-FUN with ARGS with</span><span class="ss">`debug-on-error'</span><span class="s"> bound to nil.</span></span></span><span class="line"><span class="cl"><span class="s">When</span><span class="ss">`tlon-db-get-entries-no-confirm'</span><span class="s"> runs from its idle timer,</span></span></span><span class="line"><span class="cl"><span class="ss">`url-retrieve-synchronously'</span><span class="s"> calls</span><span class="ss">`accept-process-output'</span><span class="s">, which</span></span></span><span class="line"><span class="cl"><span class="s">can fire sentinels for unrelated connections (e.g. ghub/Forge).</span></span></span><span class="line"><span class="cl"><span class="s">If those sentinels signal an error while</span><span class="ss">`debug-on-error'</span><span class="s"> is t,</span></span></span><span class="line"><span class="cl"><span class="s">the debugger's</span><span class="ss">`recursive-edit'</span><span class="s"> freezes Emacs inside the timer."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">debug-on-error</span><span class="no">nil</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">condition-case</span><span class="nv">err</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">orig-fun</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ne">error</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"tlon-db: periodic refresh failed: %s"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">error-message-string</span><span class="nv">err</span><span class="p">))))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'tlon-db-get-entries-no-confirm</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="nf">#'</span><span class="nv">tlon-db-extras--suppress-debugger</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">init-post-init-hook</span><span class="o">.</span><span class="nv">tlon-initialize</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"M-j"</span><span class="o">.</span><span class="nv">tlon-node-find</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-r"</span><span class="o">.</span><span class="nv">tlon-dispatch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-?"</span><span class="o">.</span><span class="nv">tlon-mdx-insert-cite</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-p"</span><span class="o">.</span><span class="nv">tlon-grep</span><span class="p">)))</span></span></span></code></pre></div><h3 id="johnson"><code>johnson</code></h3><p><em><a href="https://github.com/benthamite/johnson">johnson</a> is a multi-format dictionary UI for Emacs, providing the functionality of programs such as GoldenDict.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">johnson</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/johnson"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">johnson-dictionary-directories</span><span class="o">'</span><span class="p">(</span><span class="s">"/Users/pablostafforini/My Drive/Dictionaries/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-o"</span><span class="o">.</span><span class="nv">johnson-lookup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">johnson-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">johnson-prev-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">johnson-next-section</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">johnson-ace-link</span><span class="p">)))</span></span></span></code></pre></div><h3 id="go-translate"><code>go-translate</code></h3><p><em><a href="https://github.com/lorniu/go-translate">go-translate</a> is an Emacs translator that supports multiple translation engines.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">go-translate</span></span></span><span class="line"><span class="cl"><span class="nb">:disabled</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-translate-list</span><span class="o">'</span><span class="p">((</span><span class="s">"en"</span><span class="s">"es"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-default-translator</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-translator</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:picker</span><span class="c1">; used to pick source text, from, to. choose one.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;;(gts-noprompt-picker)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-noprompt-picker :texter (gts-whole-buffer-texter))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-prompt-picker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-prompt-picker :single t)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-prompt-picker :texter (gts-current-or-selection-texter) :single t)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:engines</span><span class="c1">; engines, one or more. Provide a parser to give different output.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span></span></span><span class="line"><span class="cl"><span class="c1">;; (gts-bing-engine)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-google-engine)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-google-rpc-engine)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-deepl-engine</span><span class="nb">:auth-key</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"key"</span><span class="p">(</span><span class="nf">concat</span><span class="s">"tlon/babel/deepl.com/"</span><span class="nv">tlon-email-shared</span><span class="p">))</span><span class="nb">:pro</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; (gts-google-engine :parser (gts-google-summary-parser))</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-google-engine :parser (gts-google-parser))</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-google-rpc-engine :parser (gts-google-rpc-summary-parser) :url "https://translate.google.com")</span></span></span><span class="line"><span class="cl"><span class="c1">;; (gts-google-rpc-engine :parser (gts-google-rpc-parser) :url "https://translate.google.com")</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:render</span><span class="c1">; render, only one, used to consumer the output result. Install posframe yourself when use gts-posframe-xxx</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; (gts-buffer-render)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-posframe-pop-render)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-posframe-pop-render :backcolor "#333333" :forecolor "#ffffff")</span></span></span><span class="line"><span class="cl"><span class="c1">;; (gts-posframe-pin-render)</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-posframe-pin-render :position (cons 1200 20))</span></span></span><span class="line"><span class="cl"><span class="c1">;;(gts-posframe-pin-render :width 80 :height 25 :position (cons 1000 20) :forecolor "#ffffff" :backcolor "#111111")</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-kill-ring-render</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:splitter</span><span class="c1">; optional, used to split text into several parts, and the translation result will be a list.</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">gts-paragraph-splitter</span><span class="p">))))</span></span></span></code></pre></div><h3 id="powerthesaurus"><code>powerthesaurus</code></h3><p><em><a href="https://github.com/SavchenkoValeriy/emacs-powerthesaurus">powerthesaurus</a> is an Emacs client for<a href="https://www.powerthesaurus.org/">power thesaurus</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">powerthesaurus</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-y"</span><span class="o">.</span><span class="nv">powerthesaurus-transient</span><span class="p">))</span></span></span></code></pre></div><h3 id="reverso"><code>reverso</code></h3><p><em><a href="https://github.com/SqrtMinusOne/reverso.el">reverso</a> is an Emacs client for<a href="https://www.reverso.net/">reverso</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">reverso</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"SqrtMinusOne/reverso.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">reverso-languages</span><span class="o">'</span><span class="p">(</span><span class="nv">spanish</span><span class="nv">english</span><span class="nv">french</span><span class="nv">german</span><span class="nv">italian</span><span class="nv">portuguese</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-Y"</span><span class="o">.</span><span class="nv">reverso</span><span class="p">))</span></span></span></code></pre></div><h3 id="dictionary"><code>dictionary</code></h3><p><em>dictionary is a client for rfc2229 dictionary servers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">dictionary</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dictionary-server</span><span class="s">"dict.org"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">dictionary-use-single-buffer</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h2 id="docs">docs</h2><h3 id="pdf-tools"><code>pdf-tools</code></h3><p><em><a href="https://github.com/vedang/pdf-tools">pdf-tools</a> is a support library for PDF files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pdf-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:mode</span><span class="p">(</span><span class="s">"\\.pdf\\'"</span><span class="o">.</span><span class="nv">pdf-view-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">:any</span><span class="nv">dired-extras</span><span class="nv">ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-tools-install</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-annot</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-annot-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-annot-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">pdf-view-goto-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">pdf-view-previous-line-or-previous-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">pdf-view-next-line-or-next-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">pdf-view-kill-ring-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-u"</span><span class="o">.</span><span class="nv">pdf-view-midnight-minor-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-history</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-history-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-annot-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">pdf-view-goto-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">pdf-view-previous-line-or-previous-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">pdf-view-next-line-or-next-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">pdf-view-kill-ring-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-u"</span><span class="o">.</span><span class="nv">pdf-view-midnight-minor-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-use-scaling</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-use-imagemagick</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-resize-factor</span><span class="mf">1.01</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-annot-default-annotation-properties</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">label</span><span class="o">.</span><span class="nf">user-full-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">text</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"#ff0000"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">icon</span><span class="o">.</span><span class="s">"Note"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">highlight</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"LightBlue2"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">underline</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"blue"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">squiggly</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"orange"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">strike-out</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"red"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-cache-prefetch-minor-mode</span><span class="mi">-1</span><span class="p">)</span><span class="c1">; https://github.com/vedang/pdf-tools/issues/278#issuecomment-2096894629</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-mode-hook</span><span class="o">.</span><span class="nv">pdf-view-fit-page-to-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">pdf-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">save-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-annot-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">pdf-view-goto-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">pdf-view-previous-line-or-previous-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">pdf-view-next-line-or-next-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-c"</span><span class="o">.</span><span class="nv">pdf-view-kill-ring-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-u"</span><span class="o">.</span><span class="nv">pdf-view-midnight-minor-mode</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pdf-tools-extras"><code>pdf-tools-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/pdf-tools-extras.el">pdf-tools-extras</a> collects my extensions for<code>pdf-tools</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">pdf-tools-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-annot</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-annot-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">pdf-tools-extras-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-count-words</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">pdf-annot-extras-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">pdf-tools-extras-toggle-writeroom</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-externally</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-history</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">pdf-history-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">pdf-tools-extras-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-count-words</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">pdf-annot-extras-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">pdf-tools-extras-toggle-writeroom</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-externally</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-tools-enabled-hook</span><span class="o">.</span><span class="nv">pdf-tools-extras-apply-theme</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-mode-hook</span><span class="o">.</span><span class="nv">pdf-tools-extras-sel-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">pdf-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">pdf-tools-extras-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-count-words</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">pdf-annot-extras-add-highlight-markup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">pdf-tools-extras-toggle-writeroom</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">pdf-tools-extras-open-externally</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pdf-tools-pages"><code>pdf-tools-pages</code></h3><p><em><a href="https://github.com/benthamite/pdf-tools-pages">pdf-tools-pages</a> is a simple<code>pdf-tools</code> extension I created to delete and extract pages from PDF files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pdf-tools-pages</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/pdf-tools-pages"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pdf-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-annot</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-annot-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">pdf-tools-pages-clear-page-selection</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">pdf-tools-pages-delete-selected-pages</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S"</span><span class="o">.</span><span class="nv">pdf-tools-pages-select-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">pdf-tools-pages-extract-selected-pages</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-history</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">pdf-history-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">pdf-tools-pages-clear-page-selection</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">pdf-tools-pages-delete-selected-pages</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S"</span><span class="o">.</span><span class="nv">pdf-tools-pages-select-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">pdf-tools-pages-extract-selected-pages</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">pdf-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">pdf-tools-pages-clear-page-selection</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">pdf-tools-pages-delete-selected-pages</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S"</span><span class="o">.</span><span class="nv">pdf-tools-pages-select-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">pdf-tools-pages-extract-selected-pages</span><span class="p">)))</span></span></span></code></pre></div><h3 id="scroll-other-window"><code>scroll-other-window</code></h3><p><em><a href="https://github.com/benthamite/scroll-other-window">scroll-other-window</a> enables scrolling of the other window in<code>pdf-tools</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nf">scroll-other-window</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/scroll-other-window"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pdf-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-tools-enabled-hook</span><span class="o">.</span><span class="nv">sow-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">sow-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-g"</span><span class="o">.</span><span class="nv">sow-scroll-other-window-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-t"</span><span class="o">.</span><span class="nv">sow-scroll-other-window</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pdf-view-restore"><code>pdf-view-restore</code></h3><p><em><a href="https://github.com/007kevin/pdf-view-restore">pdf-view-restore</a> adds support to saving and reopening the last known PDF position.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pdf-view-restore</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pdf-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/007kevin/pdf-view-restore/issues/6</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">pdf-view-restore-mode-conditionally</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Enable</span><span class="ss">`pdf-view-restore-mode'</span><span class="s"> iff the current buffer is visiting a PDF."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-restore-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pdf-view-mode-hook</span><span class="o">.</span><span class="nv">pdf-view-restore-mode-conditionally</span><span class="p">))</span></span></span></code></pre></div><h3 id="moon-reader"><code>moon-reader</code></h3><p><em><a href="https://github.com/benthamite/moon-reader">moon-reader</a> synchronizes page position between pdf-tools and Moon+ Reader.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">moon-reader</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/moon-reader"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">pdf-view-restore</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">moon-reader-cache-directory</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-google-drive</span><span class="s">"Apps/Books/.Moon+/Cache/"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-pdftools"><code>org-pdftools</code></h3><p><em><a href="https://github.com/fuxialexander/org-pdftools">org-pdftools</a> adds org link support for pdf-tools.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-pdftools</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">pdf-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-mode-hook</span><span class="o">.</span><span class="nv">org-pdftools-setup-link</span><span class="p">))</span></span></span></code></pre></div><h3 id="nov"><code>nov</code></h3><p><em><a href="https://depp.brause.cc/nov.el/">nov</a> is a major mode for reading EPUBs in Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">nov</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="djvu"><code>djvu</code></h3><p><em><a href="https://elpa.gnu.org/packages/djvu.html">djvu</a> is a major mode for viewing and editing Djvu files in Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">djvu</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h2 id="programming">programming</h2><h3 id="prog-mode"><code>prog-mode</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/prog-mode.el">prog-mode</a> is the base major mode for programming language modes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">prog-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'shell</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">shell-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nf">exit-recursive-edit</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-prettify-symbols-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-v"</span><span class="o">.</span><span class="nv">set-variable</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-d"</span><span class="o">.</span><span class="nv">toggle-debug-on-error</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-d"</span><span class="o">.</span><span class="nv">toggle-debug-on-quit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">prog-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-i"</span><span class="o">.</span><span class="nv">mark-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">xref-find-definitions</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">consult-flycheck</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-q"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-q"</span><span class="o">.</span><span class="nv">prog-fill-reindent-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">emacs-lisp-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nf">exit-recursive-edit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="treesit"><code>treesit</code></h3><p><em>treesit provides Tree-sitter-based syntax highlighting in Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">treesit</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">treesit-language-source-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">typescript</span><span class="s">"https://github.com/tree-sitter/tree-sitter-typescript"</span><span class="s">"master"</span><span class="s">"typescript/src"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tsx</span><span class="s">"https://github.com/tree-sitter/tree-sitter-typescript"</span><span class="s">"master"</span><span class="s">"tsx/src"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nv">treesit-language-available-p</span><span class="ss">'typescript</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">treesit-install-language-grammar</span><span class="ss">'typescript</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nv">treesit-language-available-p</span><span class="ss">'tsx</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">treesit-install-language-grammar</span><span class="ss">'tsx</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elisp-mode"><code>elisp-mode</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/elisp-mode.el">elisp-mode</a> is the major mode for editing Emacs Lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">elisp-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">instrument-defun</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Instrument the current defun."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-defun</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">emacs-lisp-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nf">eval-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">eval-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">instrument-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">lisp-interaction-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nf">eval-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">eval-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">instrument-defun</span><span class="p">)))</span></span></span></code></pre></div><h3 id="lisp-mode"><code>lisp-mode</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/lisp-mode.el">lisp-mode</a> is the major mode for editing Lisp code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">lisp-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; default is 65, which overrides the value of `fill-column'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emacs-lisp-docstring-fill-column</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="curl-to-elisp"><code>curl-to-elisp</code></h3><p><em><a href="https://github.com/xuchunyang/curl-to-elisp">curl-to-elisp</a> converts cURL command to Emacs Lisp code.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">curl-to-elisp</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="f"><code>f</code></h3><p><em><a href="https://github.com/rejeep/f.el">f</a> is a modern API for working with files and directories in Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">f</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="s"><code>s</code></h3><p><em><a href="https://github.com/magnars/s.el">s</a> is a string manipulation library.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">s</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="backtrace"><code>backtrace</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/backtrace.el">backtrace</a> provides generic facilities for displaying backtraces.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nf">backtrace</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">backtrace-line-length</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="debug"><code>debug</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/debug.el">debug</a> is the Emacs Lisp debugger.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">debug</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">debug-save-backtrace</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Save the backtrace at point and copy its path to the kill-ring."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nv">string-match-p</span><span class="s">"\\*Backtrace\\*"</span><span class="p">(</span><span class="nf">buffer-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">contents</span><span class="p">(</span><span class="nf">buffer-string</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-downloads</span><span class="s">"backtrace.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nf">message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-temp-buffer</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="nv">contents</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">write-region</span><span class="p">(</span><span class="nf">point-min</span><span class="p">)</span><span class="p">(</span><span class="nf">point-max</span><span class="p">)</span><span class="nv">file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nf">message</span><span class="p">(</span><span class="nf">format</span><span class="s">"Backtrace saved to \"%s\" (%s)"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">abbreviate-file-name</span><span class="nv">file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-size-human-readable</span><span class="p">(</span><span class="nv">file-attribute-size</span><span class="p">(</span><span class="nf">file-attributes</span><span class="nv">file</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">kill-new</span><span class="nv">file</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">kill-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"%s"</span><span class="nf">message</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">debugger-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">debug-save-backtrace</span><span class="p">)))</span></span></span></code></pre></div><h3 id="edebug"><code>edebug</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/edebug.el">edebug</a> is a source-level debugger for Emacs Lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">edebug</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">edebug-sit-for-seconds</span><span class="mi">10</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">edebug-sit-on-break</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; do not truncate print results</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">print-level</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">print-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">print-circle</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">edebug-print-level</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">edebug-print-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">edebug-print-circle</span><span class="no">nil</span><span class="p">)</span><span class="c1">; disable confusing #N= and #N# print syntax</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">emacs-lisp-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-d"</span><span class="o">.</span><span class="nv">edebug-defun</span><span class="p">)))</span></span></span></code></pre></div><h3 id="macrostep"><code>macrostep</code></h3><p><em><a href="https://github.com/joddie/macrostep">macrostep</a> is an interactive macro-expander.</em></p><p>See<a href="https://www.youtube.com/watch?v=odkYXXYOxpo">this video</a> (starting at 7:30) for an introduction to this package.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">macrostep</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="js"><code>js</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/js.el">js</a> is a major mode for editing JavaScript.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">js</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">js-indent-level</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">js-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">eww-extras-browse-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-,"</span><span class="o">.</span><span class="nv">window-extras-buffer-move-left</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-."</span><span class="o">.</span><span class="nv">window-extras-buffer-move-right</span><span class="p">)))</span></span></span></code></pre></div><h3 id="js2-mode"><code>js2-mode</code></h3><p><em><a href="https://github.com/mooz/js2-mode">js2-mode</a> is a Javascript editing mode for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">js2-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="clojure"><code>clojure</code></h3><p><em><a href="https://github.com/clojure-emacs/clojure-mode">clojure-mode</a> provides support for the Clojure(Script) programming language.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">clojure-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="haskell-mode"><code>haskell-mode</code></h3><p><em><a href="https://github.com/haskell/haskell-mode">haskell-mode</a> is a major mode for Haskell.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">haskell-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="python"><code>python</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/python.el">python</a> is the major mode for editing Python.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">python</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">python-shell-interpreter</span><span class="s">"/Users/pablostafforini/.pyenv/shims/python3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-babel-python-command</span><span class="s">"/Users/pablostafforini/.pyenv/shims/python3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">flycheck-python-pycompile-executable</span><span class="s">"/Users/pablostafforini/.pyenv/shims/python3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">python-indent-offset</span><span class="mi">4</span><span class="p">)</span><span class="c1">; Set default to suppress warning message</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">python-indent-guess-indent-offset</span><span class="no">nil</span><span class="p">)</span><span class="c1">; Don't try to guess indent</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-babel-do-load-languages</span></span></span><span class="line"><span class="cl"><span class="ss">'org-babel-load-languages</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">python</span><span class="o">.</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">python-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-c p"</span><span class="o">.</span><span class="nv">run-python</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">python-shell-send-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">python-shell-send-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">python-shell-send-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">python-shell-send-string</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">python-shell-send-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">python-shell-send-statement</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">python-ts-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-c p"</span><span class="o">.</span><span class="nv">run-python</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">python-shell-send-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">python-shell-send-defun</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">python-shell-send-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">python-shell-send-string</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">python-shell-send-region</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">python-shell-send-statement</span><span class="p">)))</span></span></span></code></pre></div><h3 id="pyenv-mode"><code>pyenv-mode</code></h3><p><em><a href="https://github.com/pythonic-emacs/pyenv-mode">pyenv-mode</a> integrates pyenv with python-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pyenv-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">python</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'exec-path</span><span class="s">"~/.pyenv/bin"</span><span class="p">))</span></span></span></code></pre></div><h3 id="pet"><code>pet</code></h3><p><em><a href="https://github.com/wyuenho/emacs-pet">pet</a> tracks down the correct Python tooling executables from Python virtual environments.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">pet</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">python</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="c1">;; Disabled by default because it causes slowdown when opening Python files</span></span></span><span class="line"><span class="cl"><span class="c1">;; Uncomment the line below to enable pet-mode automatically</span></span></span><span class="line"><span class="cl"><span class="c1">;; :config</span></span></span><span class="line"><span class="cl"><span class="c1">;; (add-hook 'python-base-mode-hook 'pet-mode -10)</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre></div><h3 id="emacs-ipython-notebook"><code>emacs-ipython-notebook</code></h3><p><em><a href="https://github.com/millejoh/emacs-ipython-notebook">emacs-ipython-notebook</a> is a Jupyter notebook client in Emacs.</em></p><p>This needs to be configured.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ein</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">python</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="go"><code>go</code></h3><p><em><a href="https://github.com/dominikh/go-mode.el">go-mode</a> provides support for the Go programming language.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">go-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="applescript-mode"><code>applescript-mode</code></h3><p><em><a href="https://github.com/emacsorphanage/applescript-mode">applescript-mode</a> is a major mode for editing AppleScript.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">applescript-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="json-mode"><code>json-mode</code></h3><p><em><a href="https://github.com/json-emacs/json-mode">json-mode</a> is a major mode for editing JSON files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">json-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">json-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"RET"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="csv-mode"><code>csv-mode</code></h3><p><em><a href="https://elpa.gnu.org/packages/csv-mode.html">csv-mode</a> is a major mode for editing comma-separated values.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">csv-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="yaml"><code>yaml</code></h3><p><em><a href="https://github.com/zkry/yaml.el">yaml</a> is YAML parser written in Emacs List without any external dependencies.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">yaml</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"zkry/yaml.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="yaml-mode"><code>yaml-mode</code></h3><p><em><a href="https://github.com/yoshiki/yaml-mode">yaml-mode</a> is a major mode for editing YAML files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">yaml-mode</span><span class="p">)</span></span></span></code></pre></div><h3 id="shut-up"><code>shut-up</code></h3><p><em><a href="https://github.com/cask/shut-up/">shut-up</a> provides a macro to silence function calls.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">shut-up</span><span class="p">)</span></span></span></code></pre></div><h3 id="puni"><code>puni</code></h3><p><em><a href="https://github.com/AmaiKinono/puni">puni</a> supports structured editing for many major modes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">puni</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">prog-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-r"</span><span class="o">.</span><span class="nv">puni-forward-kill-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-q"</span><span class="o">.</span><span class="nv">puni-backward-kill-word</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-v"</span><span class="o">.</span><span class="nv">puni-kill-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-z"</span><span class="o">.</span><span class="nv">puni-backward-kill-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-d"</span><span class="o">.</span><span class="nv">puni-forward-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-e"</span><span class="o">.</span><span class="nv">puni-backward-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">puni-beginning-of-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">puni-end-of-sexp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-j"</span><span class="o">.</span><span class="nv">puni-mark-sexp-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-k"</span><span class="o">.</span><span class="nv">puni-mark-sexp-around-point</span><span class="p">)))</span></span></span></code></pre></div><h3 id="hl-todo"><code>hl-todo</code></h3><p><em><a href="https://github.com/tarsius/hl-todo">hl-todo</a> highlights TODO and similar keywords in comments and strings.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">hl-todo</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">hl-todo-keyword-faces</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">append</span><span class="o">'</span><span class="p">((</span><span class="s">"WAITING"</span><span class="o">.</span><span class="s">"blue"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"LATER"</span><span class="o">.</span><span class="s">"violet"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"SOMEDAY"</span><span class="o">.</span><span class="s">"brown"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"DELEGATED"</span><span class="o">.</span><span class="s">"gray"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-todo-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="consult-todo"><code>consult-todo</code></h3><p><em><a href="https://github.com/eki3z/consult-todo">consult-todo</a> uses<code>consult</code> to navigate<code>hl-todo</code> keywords.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">consult-todo</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">hl-todo</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">prog-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">consult-todo</span><span class="p">)))</span></span></span></code></pre></div><h3 id="project"><code>project</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/project.el">project</a> provides various functions for dealing with projects.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">project</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">emacs-lisp-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">project-query-replace-regexp</span><span class="p">)))</span></span></span></code></pre></div><h3 id="hideshow"><code>hideshow</code></h3><p><em>hideshow is a minor mode for block hiding and showing.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">hideshow</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">prog-mode-hook</span><span class="o">.</span><span class="nv">hs-minor-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="aggressive-indent"><code>aggressive-indent</code></h3><p><em><a href="https://github.com/Malabarba/aggressive-indent-mode">aggressive-indent</a> keeps code always indented.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">aggressive-indent</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-aggressive-indent-mode</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'aggressive-indent-excluded-modes</span><span class="ss">'snippet-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="elpy"><code>elpy</code></h3><p><em><a href="https://github.com/jorgenschaefer/elpy">elpy</a> is an Emacs Python development environment.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elpy</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpy-rpc-python-command</span><span class="s">"python3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elpy-rpc-virtualenv-path</span><span class="ss">'current</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; Disabled by default because it causes slowdown when opening Python files</span></span></span><span class="line"><span class="cl"><span class="c1">;; To enable elpy features, run M-x elpy-enable or uncomment the lines below</span></span></span><span class="line"><span class="cl"><span class="c1">;; :config</span></span></span><span class="line"><span class="cl"><span class="c1">;; (elpy-enable)</span></span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre></div><h3 id="eldoc"><code>eldoc</code></h3><p><em><a href="https://elpa.gnu.org/packages/eldoc.html">eldoc</a> show function arglist or variable docstring in echo area.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">eldoc</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; emacs.stackexchange.com/a/55914/32089</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">define-advice</span><span class="nv">elisp-get-fnsym-args-string</span><span class="p">(</span><span class="nb">:around</span><span class="p">(</span><span class="nv">orig-fun</span><span class="nv">sym</span><span class="kp">&amp;rest</span><span class="nv">r</span><span class="p">)</span><span class="nv">docstring</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"If SYM is a function, append its docstring."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">orig-fun</span><span class="nv">sym</span><span class="nv">r</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">doc</span><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nf">fboundp</span><span class="nv">sym</span><span class="p">)</span><span class="p">(</span><span class="nf">documentation</span><span class="nv">sym</span><span class="ss">'raw</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">oneline</span><span class="p">(</span><span class="nb">and</span><span class="nv">doc</span><span class="p">(</span><span class="nf">substring</span><span class="nv">doc</span><span class="mi">0</span><span class="p">(</span><span class="nf">string-match</span><span class="s">"\n"</span><span class="nv">doc</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">and</span><span class="nv">oneline</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">stringp</span><span class="nv">oneline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nv">string=</span><span class="s">""</span><span class="nv">oneline</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="s">" | "</span><span class="p">(</span><span class="nf">propertize</span><span class="nv">oneline</span><span class="ss">'face</span><span class="ss">'italic</span><span class="p">))))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; reddit.com/r/emacs/comments/1l9y7de/showing_org_mode_link_at_point_in_echo_area/</span></span></span><span class="line"><span class="cl"><span class="c1">;; this is natively supported in Emacs 31</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-display-link-info-at-point</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Display the link info in the echo area when the cursor is on an Org mode link."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">when-let*</span><span class="p">((</span><span class="nv">is-face-at-point</span><span class="ss">'org-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">link-info</span><span class="p">(</span><span class="nf">get-text-property</span><span class="p">(</span><span class="nf">point</span><span class="p">)</span><span class="ss">'help-echo</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="c1">;; This will show the link in the echo area without it being logged in</span></span></span><span class="line"><span class="cl"><span class="c1">;; the Messages buffer.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">message-log-max</span><span class="no">nil</span><span class="p">))</span><span class="p">(</span><span class="nf">message</span><span class="s">"%s"</span><span class="nv">link-info</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">h</span><span class="o">'</span><span class="p">(</span><span class="nv">org-mode-hook</span><span class="nv">org-agenda-mode-hook</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="nv">h</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'post-command-hook</span><span class="nf">#'</span><span class="nv">org-display-link-info-at-point</span><span class="no">nil</span><span class="ss">'local</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">is-face-at-point</span><span class="p">(</span><span class="nv">face</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Returns non-nil if given FACE is applied at text at the current point."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">face-at-point</span><span class="p">(</span><span class="nf">get-text-property</span><span class="p">(</span><span class="nf">point</span><span class="p">)</span><span class="ss">'face</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">or</span><span class="p">(</span><span class="nf">eq</span><span class="nv">face-at-point</span><span class="nv">face</span><span class="p">)</span><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nf">listp</span><span class="nv">face-at-point</span><span class="p">)</span><span class="p">(</span><span class="nf">memq</span><span class="nv">face</span><span class="nv">face-at-point</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-eldoc-mode</span><span class="p">))</span></span></span></code></pre></div><h2 id="org-mode">org-mode</h2><h3 id="org"><code>org</code></h3><p><em><a href="https://orgmode.org/">org-mode</a> is a major mode for keeping notes, authoring documents, computational notebooks, literate programming, maintaining to-do lists, planning projects, and more.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-directory</span><span class="nv">paths-dir-org</span><span class="p">)</span><span class="c1">; set org directory</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-todo-keywords</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">sequence</span><span class="s">"TODO(t)"</span></span></span><span class="line"><span class="cl"><span class="s">"DOING(g)"</span></span></span><span class="line"><span class="cl"><span class="s">"IMPORTANT(i)"</span></span></span><span class="line"><span class="cl"><span class="s">"URGENT(u)"</span></span></span><span class="line"><span class="cl"><span class="s">"SOMEDAY(s)"</span></span></span><span class="line"><span class="cl"><span class="s">"MAYBE(m)"</span></span></span><span class="line"><span class="cl"><span class="s">"WAITING(w)"</span></span></span><span class="line"><span class="cl"><span class="s">"PROJECT(p)"</span></span></span><span class="line"><span class="cl"><span class="s">"NEXT(n)"</span></span></span><span class="line"><span class="cl"><span class="s">"LATER(l)"</span></span></span><span class="line"><span class="cl"><span class="s">"|"</span></span></span><span class="line"><span class="cl"><span class="s">"DELEGATED(e)"</span></span></span><span class="line"><span class="cl"><span class="s">"DONE(d)"</span></span></span><span class="line"><span class="cl"><span class="s">"CANCELLED(c)"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-priority-highest</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-priority-default</span><span class="mi">7</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-priority-lowest</span><span class="mi">9</span><span class="p">)</span><span class="c1">; set priorities</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-deadline-warning-days</span><span class="mi">0</span><span class="p">)</span><span class="c1">; show due tasks only on the day the tasks are due</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-hide-emphasis-markers</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-hide-leading-stars</span><span class="no">t</span><span class="p">)</span><span class="c1">; indent every heading and hide all but the last leading star</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-startup-indented</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-log-into-drawer</span><span class="s">"STATES"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-log-done</span><span class="ss">'time</span><span class="p">)</span><span class="c1">; add timestamp when task is marked as DONE</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-log-repeat</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not log TODO status changes for repeating tasks</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-M-RET-may-split-line</span><span class="no">nil</span><span class="p">)</span><span class="c1">; irreal.org/blog/?p=6297</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-loop-over-headlines-in-active-region</span><span class="no">t</span><span class="p">)</span><span class="c1">; Allow simultaneous modification of multiple task statuses.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-ctrl-k-protect-subtree</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-special-ctrl-a/e</span><span class="no">t</span><span class="p">)</span><span class="c1">; `org-beginning-of-line' goes to beginning of first word</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-mark-ring-length</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pretty-entities</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-image-actual-width</span><span class="o">'</span><span class="p">(</span><span class="mi">800</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-link-elisp-confirm-function</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-file-apps</span><span class="o">'</span><span class="p">((</span><span class="nv">auto-mode</span><span class="o">.</span><span class="nv">emacs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">directory</span><span class="o">.</span><span class="nv">emacs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"\\.mm\\'"</span><span class="o">.</span><span class="nv">default</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"\\.x?html?\\'"</span><span class="o">.</span><span class="nv">default</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"\\.pdf\\'"</span><span class="o">.</span><span class="nv">emacs</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-use-tag-inheritance</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-yank-dnd-method</span><span class="ss">'attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-yank-image-save-method</span><span class="nv">paths-dir-org-images</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-structure-template-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"a"</span><span class="o">.</span><span class="s">"export ascii"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="s">"center"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="s">"comment"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="s">"example"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="s">"export"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="s">"export html"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="s">"export latex"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="s">"quote"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="s">"src"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"se"</span><span class="o">.</span><span class="s">"src emacs-lisp"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sE"</span><span class="o">.</span><span class="s">"src emacs-lisp :tangle (init-tangle-conditionally)"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sc"</span><span class="o">.</span><span class="s">"src clojure"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sj"</span><span class="o">.</span><span class="s">"src javascript"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sm"</span><span class="o">.</span><span class="s">"src markdown"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sp"</span><span class="o">.</span><span class="s">"src python"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"sq"</span><span class="o">.</span><span class="s">"src sql"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"ss"</span><span class="o">.</span><span class="s">"src shell"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="s">"verse"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="s">"WP"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; refile</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-reverse-note-order</span><span class="no">t</span><span class="p">)</span><span class="c1">; store notes at the beginning of header</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; export</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-backends</span><span class="o">'</span><span class="p">(</span><span class="nv">ascii</span><span class="nv">html</span><span class="nv">icalendar</span><span class="nv">latex</span><span class="nv">md</span><span class="nv">odt</span><span class="nv">texinfo</span><span class="p">))</span><span class="c1">; set export backends</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-preview-latex-default-process</span><span class="ss">'dvisvgm</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; org-src</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-src-fontify-natively</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; org-crypt</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-tags-exclude-from-inheritance</span><span class="o">'</span><span class="p">(</span><span class="s">"crypt"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">plist-put</span><span class="nv">org-format-latex-options</span><span class="nb">:scale</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">plist-put</span><span class="nv">org-format-latex-options</span><span class="nb">:background</span><span class="s">"Transparent"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">module</span><span class="o">'</span><span class="p">(</span><span class="nv">org-habit</span><span class="nv">org-tempo</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'org-modules</span><span class="nv">module</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; force reloading of first file opened so the buffer is correctly formatted</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'org</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">string-match</span><span class="s">"\\.org$"</span><span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">revert-buffer</span><span class="no">nil</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-z"</span><span class="o">.</span><span class="nv">org-shiftleft</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-x"</span><span class="o">.</span><span class="nv">org-shiftup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-c"</span><span class="o">.</span><span class="nv">org-shiftdown</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-v"</span><span class="o">.</span><span class="nv">org-shiftright</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-a"</span><span class="o">.</span><span class="nv">org-metaleft</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-s"</span><span class="o">.</span><span class="nv">org-metaup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-d"</span><span class="o">.</span><span class="nv">org-metadown</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-f"</span><span class="o">.</span><span class="nv">org-metaright</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-q"</span><span class="o">.</span><span class="nv">org-shiftmetaleft</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-w"</span><span class="o">.</span><span class="nv">org-shiftmetaup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-e"</span><span class="o">.</span><span class="nv">org-shiftmetadown</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-M-s-r"</span><span class="o">.</span><span class="nv">org-shiftmetaright</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-j"</span><span class="o">.</span><span class="nv">consult-extras-org-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-k"</span><span class="o">.</span><span class="nv">org-web-tools-insert-link-for-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">org-transclusion-add-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">ox-clip-formatted-copy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">org-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-i"</span><span class="o">.</span><span class="nv">org-id-copy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;S-left&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;S-right&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;S-up&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;S-down&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-left&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-right&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-S-left&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-S-right&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-up&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;M-down&gt;"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-j"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">org-shifttab</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-,"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-i"</span><span class="o">.</span><span class="nv">org-backward-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-o"</span><span class="o">.</span><span class="nv">org-forward-sentence</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-,"</span><span class="o">.</span><span class="nv">org-backward-paragraph</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-."</span><span class="o">.</span><span class="nv">org-forward-paragraph</span><span class="p">)</span><span class="c1">; org element?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-m"</span><span class="o">.</span><span class="nv">org-beginning-of-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-z"</span><span class="o">.</span><span class="nv">org-end-of-line</span><span class="p">)</span><span class="c1">; karabiner maps `/' to `z'; otherwise I can't trigger the command while holding `shift'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">org-previous-visible-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">org-next-visible-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-M-m"</span><span class="o">.</span><span class="nv">org-previous-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-M-/"</span><span class="o">.</span><span class="nv">org-next-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-t"</span><span class="o">.</span><span class="nv">org-extras-copy-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-M-s-j"</span><span class="o">.</span><span class="nv">org-previous-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-M-s-;"</span><span class="o">.</span><span class="nv">org-next-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-M-t"</span><span class="o">.</span><span class="nv">org-transpose-element</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">org-deadline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-e"</span><span class="o">.</span><span class="nv">org-set-effort</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">org-footnote-action</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-h"</span><span class="o">.</span><span class="nv">org-insert-todo-subheading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-p"</span><span class="o">.</span><span class="nv">org-time-stamp-inactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-p"</span><span class="o">.</span><span class="nv">org-time-stamp</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">org-agenda</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-g"</span><span class="o">.</span><span class="nv">org-gcal-extras-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">org-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-q"</span><span class="o">.</span><span class="nv">org-set-tags-command</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">org-roam-buffer-toggle</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">org-schedule</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">org-todo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-t"</span><span class="o">.</span><span class="nv">org-sort</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">org-clock-split</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-y"</span><span class="o">.</span><span class="nv">org-evaluate-time-range</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">org-edit-special</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-,"</span><span class="o">.</span><span class="nv">org-priority</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-e"</span><span class="o">.</span><span class="nv">org-export-dispatch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-&lt;return&gt;"</span><span class="o">.</span><span class="s">"C-u M-&lt;return&gt;"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-&lt;return&gt;"</span><span class="o">.</span><span class="nv">org-insert-todo-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; bindings with matching commands in Fundamental mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-v"</span><span class="o">.</span><span class="nv">org-yank</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">ace-link-org</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-extras"><code>org-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-extras.el">org-extras</a> collects my extensions for<code>org</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-extras-agenda-switch-to-agenda-current-day-timer</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">10</span><span class="mi">60</span><span class="p">)</span><span class="no">nil</span><span class="nf">#'</span><span class="nv">org-extras-agenda-switch-to-agenda-current-day</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-extras-id-auto-add-excluded-directories</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-dir-anki</span></span></span><span class="line"><span class="cl"><span class="nv">paths-dir-dropbox-tlon-leo</span></span></span><span class="line"><span class="cl"><span class="nv">paths-dir-dropbox-tlon-fede</span></span></span><span class="line"><span class="cl"><span class="nv">paths-dir-android</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dropbox-tlon-leo</span><span class="s">"gptel/"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dropbox-tlon-fede</span><span class="s">"archive/"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dropbox-tlon-core</span><span class="s">"legal/contracts/"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-extras-agenda-files-excluded</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-file-tlon-tareas-leo</span></span></span><span class="line"><span class="cl"><span class="nv">paths-file-tlon-tareas-fede</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-extras-clock-in-add-participants-exclude</span></span></span><span class="line"><span class="cl"><span class="s">"Leo&lt;&gt;Pablo\\|Fede&lt;&gt;Pablo\\|Tlön: group meeting"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">org-extras-agenda-files-excluded</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">append</span><span class="nv">org-extras-agenda-files-excluded</span></span></span><span class="line"><span class="cl"><span class="c1">;; files in `paths-dir-inactive' sans ., .., hidden files and subdirectories</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">seq-filter</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">f</span><span class="p">)</span><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nf">file-directory-p</span><span class="nv">f</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">directory-files</span><span class="nv">paths-dir-inactive</span><span class="no">t</span><span class="s">"^[^.][^/]*$"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">quote</span><span class="p">(</span><span class="nb">:link</span><span class="no">t</span><span class="nb">:maxlevel</span><span class="mi">5</span><span class="nb">:fileskip0</span><span class="no">t</span><span class="nb">:narrow</span><span class="mi">70</span><span class="nb">:formula</span><span class="nf">%</span><span class="nb">:indent</span><span class="no">t</span><span class="nb">:formatter</span><span class="nv">org-extras-clocktable-sorter</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-mode-hook</span><span class="o">.</span><span class="nv">org-extras-enable-nested-src-block-fontification</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">before-save-hook</span><span class="o">.</span><span class="nv">org-extras-id-auto-add-ids-to-headings-in-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-;"</span><span class="o">.</span><span class="nv">org-extras-personal-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-w"</span><span class="o">.</span><span class="nv">org-extras-refile-goto-latest</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-&lt;return&gt;"</span><span class="o">.</span><span class="nv">org-extras-super-return</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">org-extras-paste-with-conversion</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-n"</span><span class="o">.</span><span class="nv">org-extras-jump-to-first-heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-b"</span><span class="o">.</span><span class="nv">org-extras-set-todo-properties</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-h"</span><span class="o">.</span><span class="nv">org-extras-insert-todo-subheading-after-body</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-v"</span><span class="o">.</span><span class="nv">org-extras-paste-image</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-z"</span><span class="o">.</span><span class="nv">org-extras-export-to-ea-wiki</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-w"</span><span class="o">.</span><span class="nv">org-extras-count-words</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-n"</span><span class="o">.</span><span class="nv">org-extras-new-clock-entry-today</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-."</span><span class="o">.</span><span class="nv">org-extras-time-stamp-active-current-time</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-."</span><span class="o">.</span><span class="nv">org-extras-time-stamp-active-current-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-/"</span><span class="o">.</span><span class="nv">org-extras-time-stamp-inactive-current-time</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-/"</span><span class="o">.</span><span class="nv">org-extras-time-stamp-inactive-current-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-u"</span><span class="o">.</span><span class="nv">org-extras-id-update-id-locations</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-c"</span><span class="o">.</span><span class="nv">org-extras-mark-checkbox-complete-and-move-to-next-item</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-o"</span><span class="o">.</span><span class="nv">org-extras-reset-checkbox-state-subtree</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-w"</span><span class="o">.</span><span class="nv">org-extras-refile-and-archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-l"</span><span class="o">.</span><span class="nv">org-extras-url-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-agenda"><code>org-agenda</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-agenda.el">org-agenda</a> provides agenda views for org tasks and appointments.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">org-agenda-hide-tags-regexp</span><span class="s">"project"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-window-setup</span><span class="ss">'current-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-use-time-grid</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-ignore-properties</span><span class="o">'</span><span class="p">(</span><span class="nv">effort</span><span class="nv">appt</span><span class="nv">category</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-dim-blocked-tasks</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-sticky</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-todo-ignore-with-date</span><span class="no">t</span><span class="p">)</span><span class="c1">; exclude tasks with a date.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-todo-ignore-scheduled</span><span class="ss">'future</span><span class="p">)</span><span class="c1">; exclude scheduled tasks.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-restore-windows-after-quit</span><span class="no">t</span><span class="p">)</span><span class="c1">; don't destroy window splits</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-span</span><span class="mi">1</span><span class="p">)</span><span class="c1">; show daily view by default</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-clock-consistency-checks</span><span class="c1">; highlight gaps of five or more minutes in agenda log mode</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nb">:max-duration</span><span class="s">"5:00"</span><span class="nb">:min-duration</span><span class="s">"0:01"</span><span class="nb">:max-gap</span><span class="mi">5</span><span class="nb">:gap-ok-around</span><span class="p">(</span><span class="s">"2:00"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-skip-scheduled-if-done</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-skip-deadline-if-done</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-log-mode-items</span><span class="o">'</span><span class="p">(</span><span class="nv">clock</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-custom-commands</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"E"</span><span class="s">"TODOs without effort"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-ql-block</span><span class="o">'</span><span class="p">(</span><span class="nb">and</span><span class="p">(</span><span class="nv">todo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nv">property</span><span class="s">"effort"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-ql-block-header</span><span class="s">"TODOs without effort"</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="s">"Weekly review"</span></span></span><span class="line"><span class="cl"><span class="nv">agenda</span><span class="s">""</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-agenda-clockreport-mode</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-archives-mode</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-start-day</span><span class="s">"-7d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-span</span><span class="mi">7</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-start-on-weekday</span><span class="mi">0</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="s">"Appointments"</span><span class="nv">agenda*</span><span class="s">"Today's appointments"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-agenda-span</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-max-entries</span><span class="mi">3</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span></span></span><span class="line"><span class="cl"><span class="s">"Reading list"</span></span></span><span class="line"><span class="cl"><span class="nv">tags</span></span></span><span class="line"><span class="cl"><span class="s">"PRIORITY=\"1\"|PRIORITY=\"2\"|PRIORITY=\"3\"|PRIORITY=\"4\"|PRIORITY=\"5\"|PRIORITY=\"6\"|PRIORITY=\"7\"|PRIORITY=\"8\"|PRIORITY=\"9\""</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-agenda-files</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-dir-bibliographic-notes</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g"</span><span class="s">"All TODOs"</span></span></span><span class="line"><span class="cl"><span class="nv">todo</span><span class="s">"TODO"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"G"</span><span class="s">"All Tlön TODOs"</span></span></span><span class="line"><span class="cl"><span class="nv">todo</span><span class="s">"TODO"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">org-agenda-files</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-dir-tlon-todos</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="s">"All tasks with no priority"</span></span></span><span class="line"><span class="cl"><span class="nv">tags-todo</span><span class="s">"-PRIORITY=\"1\"-PRIORITY=\"2\"-PRIORITY=\"3\"-PRIORITY=\"4\"-PRIORITY=\"5\"-PRIORITY=\"6\"-PRIORITY=\"7\"-PRIORITY=\"8\"-PRIORITY=\"9\""</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-files</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-file-calendar</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-archives-mode</span><span class="ss">'trees</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'org-agenda-goto</span><span class="nb">:after</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="kp">&amp;rest</span><span class="nv">_</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Narrow to the entry and its children after jumping to it."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-extras-narrow-to-entry-and-children</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'org-agenda-prepare-buffers</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">fn</span><span class="nv">files</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Skip agenda files that can't be opened (e.g. Dropbox online-only placeholders).</span></span></span><span class="line"><span class="cl"><span class="ss">`org-agenda-prepare-buffers'</span><span class="s"> passes each file to</span><span class="ss">`org-get-agenda-file-buffer'</span><span class="s"/></span></span><span class="line"><span class="cl"><span class="s">and hands the result to</span><span class="ss">`with-current-buffer'</span><span class="s">. When a file cannot be read</span></span></span><span class="line"><span class="cl"><span class="s">\(e.g. a Dropbox online-only placeholder), the call errors out. Pre-filter</span></span></span><span class="line"><span class="cl"><span class="s">the file list so that only openable files reach the original function."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">(</span><span class="nv">readable</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">f</span><span class="nv">files</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">bufferp</span><span class="nv">f</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="nv">f</span><span class="nv">readable</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">condition-case</span><span class="nv">err</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nv">org-get-agenda-file-buffer</span><span class="nv">f</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="nv">f</span><span class="nv">readable</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ne">error</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"org-agenda: skipping unreadable file %s: %s"</span></span></span><span class="line"><span class="cl"><span class="nv">f</span><span class="p">(</span><span class="nf">error-message-string</span><span class="nv">err</span><span class="p">))))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">funcall</span><span class="nv">fn</span><span class="p">(</span><span class="nf">nreverse</span><span class="nv">readable</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'org-habit-toggle-display-in-agenda</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">orig-fun</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Prevent</span><span class="ss">`org-modern-mode'</span><span class="s"> interference with org habits."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="nv">org-habit-show-habits</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-org-modern-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">orig-fun</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-redo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-org-modern-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-org-modern-mode</span><span class="mi">-1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">orig-fun</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-redo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-org-modern-mode</span><span class="mi">-1</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-agenda-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable</span><span class="ss">`visual-line-mode'</span><span class="s"> and</span><span class="ss">`toggle-truncate-lines'</span><span class="s"> in</span><span class="ss">`org-agenda'</span><span class="s">."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">visual-line-mode</span><span class="mi">-1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">toggle-truncate-lines</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">org-agenda</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-agenda-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-g"</span><span class="o">.</span><span class="nv">org-gcal-extras-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">org-save-all-org-buffers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">org-pomodoro</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">org-habit-toggle-display-in-agenda</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">org-clock-convenience-timestamp-up</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">org-clock-convenience-timestamp-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">calendar-extras-calfw-block-agenda</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-org-agenda</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"?"</span><span class="o">.</span><span class="nv">org-agenda-filter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">org-agenda-later</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-b"</span><span class="o">.</span><span class="nv">org-agenda-tree-to-indirect-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">org-agenda-deadline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-t"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-n"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ace-link-extras-org-agenda-clock-in</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">org-agenda-clock-in</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">org-agenda-diary-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">org-agenda-earlier</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"J"</span><span class="o">.</span><span class="nv">org-agenda-goto-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">org-agenda-previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">org-agenda-next-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="o">.</span><span class="nv">org-agenda-date-later</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">org-agenda-open-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="o">.</span><span class="nv">org-agenda-date-earlier</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">org-agenda-kill-all-agenda-buffers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"RET"</span><span class="o">.</span><span class="nv">org-extras-agenda-switch-to-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"/"</span><span class="o">.</span><span class="nv">org-extras-agenda-done-and-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"\""</span><span class="o">.</span><span class="nv">org-extras-agenda-postpone-and-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">org-extras-agenda-toggle-anniversaries</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"SPC"</span><span class="o">.</span><span class="nv">org-extras-agenda-goto-and-start-clock</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">org-extras-agenda-toggle-log-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">org-agenda-schedule</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">org-agenda-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"W"</span><span class="o">.</span><span class="nv">org-agenda-week-view</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">org-agenda-exit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">org-agenda-day-view</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">org-agenda-undo</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-capture"><code>org-capture</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-capture.el">org-capture</a> provides rapid note-taking and task capture.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-capture</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-default-notes-file</span><span class="nv">paths-file-inbox-desktop</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-capture-templates</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="s">"."</span><span class="s">"Todo"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"B3C12507-6A83-42F6-9FFA-9A45F5C8F278"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO %?\n"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; djcbsoftware.nl/code/mu/mu4e/Org_002dmode-links.html</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="s">"Email"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"B3C12507-6A83-42F6-9FFA-9A45F5C8F278"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO Follow up with %:fromname on %a\nSCHEDULED: %t\n\n%i"</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="s">"Telegram"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"B3C12507-6A83-42F6-9FFA-9A45F5C8F278"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO Follow up with %a\nSCHEDULED: %t\n\n%i"</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="s">"Calendar"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="o">,</span><span class="nv">paths-file-calendar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"* TODO [#5] %^ \nDEADLINE: %^T"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="s">"Slack"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"B3C12507-6A83-42F6-9FFA-9A45F5C8F278"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO Follow up %a\nSCHEDULED: %t\n\n%i"</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="s">"Epoch inbox"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="nv">paths-file-epoch-inbox</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO %?\n"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S"</span><span class="s">"Slack to Epoch inbox"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="nv">paths-file-epoch-inbox</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO Follow up %a\nSCHEDULED: %t\n\n%i"</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="s">"Tlön inbox "</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"E9C77367-DED8-4D59-B08C-E6E1CCDDEC3A"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"** TODO %? \n"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="s">"YouTube playlist"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"319B1611-A5A6-42C8-923F-884A354333F9"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"* %(org-web-tools-extras-youtube-dl (current-kill 0))\n[[%c][YouTube link]]"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="nb">:prepend</span><span class="no">t</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; github.com/alphapapa/org-protocol-capture-html#org-capture-template</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="s">"Feed"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"D70DFEBE-A5FD-4BA6-A054-49E7C8F6448A"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"*** %(org-capture-feed-heading)\n%?"</span><span class="nb">:empty-lines</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="s">"Web site"</span><span class="nv">entry</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="nv">paths-file-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"* %a :website:\n\n%U %?\n\n%:initial"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-capture-feed-heading</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Prompt for feed URL, name, and tags, returning a formatted Org heading."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">url</span><span class="p">(</span><span class="nf">read-string</span><span class="s">"Feed URL: "</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">name</span><span class="p">(</span><span class="nf">read-string</span><span class="s">"Name: "</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">id</span><span class="s">"D70DFEBE-A5FD-4BA6-A054-49E7C8F6448A"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="p">(</span><span class="nv">org-id-find-id-file</span><span class="nv">id</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">all-tags</span><span class="p">(</span><span class="nb">when</span><span class="nv">file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-current-buffer</span><span class="p">(</span><span class="nv">find-file-noselect</span><span class="nv">file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">mapcar</span><span class="nf">#'car</span><span class="p">(</span><span class="nv">org-get-buffer-tags</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">selected</span><span class="p">(</span><span class="nv">completing-read-multiple</span><span class="s">"Tags: "</span><span class="nv">all-tags</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tag-str</span><span class="p">(</span><span class="nb">if</span><span class="nv">selected</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="s">" :"</span><span class="p">(</span><span class="nv">string-join</span><span class="nv">selected</span><span class="s">":"</span><span class="p">)</span><span class="s">":"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">""</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">format</span><span class="s">"[[%s][%s]]%s"</span><span class="nv">url</span><span class="nv">name</span><span class="nv">tag-str</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-capture-feed-sort</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Sort feed entries under the Feeds heading alphabetically after capture."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nv">string=</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">org-capture-plist</span><span class="nb">:key</span><span class="p">)</span><span class="s">"f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">marker</span><span class="p">(</span><span class="nv">org-id-find</span><span class="s">"D70DFEBE-A5FD-4BA6-A054-49E7C8F6448A"</span><span class="ss">'marker</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="nv">marker</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-current-buffer</span><span class="p">(</span><span class="nf">marker-buffer</span><span class="nv">marker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">save-excursion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">goto-char</span><span class="nv">marker</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-sort-entries</span><span class="no">nil</span><span class="sc">?a</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">save-buffer</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">set-marker</span><span class="nv">marker</span><span class="no">nil</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-capture-before-finalize-hook</span><span class="o">.</span><span class="nv">org-extras-capture-before-finalize-hook-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-capture-after-finalize-hook</span><span class="o">.</span><span class="nv">org-capture-feed-sort</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-t"</span><span class="o">.</span><span class="nv">org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-t"</span><span class="o">.</span><span class="nv">org-capture-goto-last-stored</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-capture-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">org-capture-finalize</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">org-capture-refile</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-clock"><code>org-clock</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-clock.el">org-clock</a> implements clocking time spent on tasks.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-clock</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-out-when-done</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-persist</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-persist-query-resume</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-in-resume</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-report-include-clocking-task</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-ask-before-exiting</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-history-length</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-into-drawer</span><span class="s">"LOGBOOK"</span><span class="p">)</span><span class="c1">; file task state changes in STATES drawer</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-clock-persistence-insinuate</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-H-j"</span><span class="o">.</span><span class="nv">org-clock-goto</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-H-x"</span><span class="o">.</span><span class="nv">org-clock-cancel</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-i"</span><span class="o">.</span><span class="nv">org-clock-in</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-o"</span><span class="o">.</span><span class="nv">org-clock-out</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-clock-convenience"><code>org-clock-convenience</code></h3><p><em><a href="https://github.com/dfeich/org-clock-convenience">org-clock-convenience</a> provides convenience functions to work with org-mode clocking.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-clock-convenience</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-clock</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-clock-split"><code>org-clock-split</code></h3><p><em><a href="https://github.com/0robustus1/org-clock-split">org-clock-split</a> allows splitting of one clock entry into two contiguous entries.</em></p><p>I’m using a fork that fixes some functionality that broke when org changed<code>org-time-stamp-formats</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-clock-split</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"0robustus1/org-clock-split"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"support-emacs-29.1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-cycle"><code>org-cycle</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-cycle.el">org-cycle</a> controls visibility cycling of org outlines.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-cycle</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cycle-emulate-tab</span><span class="no">nil</span><span class="p">))</span><span class="c1">; TAB always cycles, even if point not on a heading</span></span></span></code></pre></div><h3 id="org-archive"><code>org-archive</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-archive.el">org-archive</a> archives org subtrees.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-archive</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-archive-default-command</span><span class="ss">'org-archive-to-archive-sibling</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-archive-location</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"%s_archive.org::"</span><span class="nv">paths-dir-archive</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">org-archive-subtree-default</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-archive-hierarchically"><code>org-archive-hierarchically</code></h3><p><em><a href="https://gitlab.com/andersjohansson/org-archive-hierarchically">org-archive-hierarchically</a> archives org subtrees in a way that preserves the original heading structure.</em></p><p>I normally archive subtrees with<code>org-archive-to-archive-sibling</code>, but use<code>org-archive-hierarchically</code> for files in public repositories (such as this one).<code>org-archive-to-archive-sibling</code> moves archived tasks to a heading, which is by default collapsed in org, but in Github archived tasks are always fully visible, creating a lot of clutter.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-archive-hierarchically</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">gitlab</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"andersjohansson/org-archive-hierarchically"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-fold"><code>org-fold</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-fold.el">org-fold</a> manages visibility and folding of org outlines.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-fold</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-fold-catch-invisible-edits</span><span class="ss">'smart</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-faces"><code>org-faces</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-faces.el">org-faces</a> defines faces for<code>org-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-faces</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-fontify-quote-and-verse-blocks</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">org-drawer</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-property-value-height</span></span></span><span class="line"><span class="cl"><span class="nb">:foreground</span><span class="s">"LightSkyBlue"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-property-value</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-property-value-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-special-keyword</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-property-value-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-meta-line</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-property-value-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-tag</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-tag-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-document-title</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-code</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-code-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-todo</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-archived</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-1</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-2</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-3</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-4</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-5</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-6</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-7</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-level-8</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-date</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-date-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-block</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-block-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-block-begin-line</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-block-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-quote</span><span class="nb">:family</span><span class="nv">faces-extras-variable-pitch-font</span><span class="nb">:height</span><span class="mf">1.0</span><span class="p">))))</span></span></span></code></pre></div><h3 id="org-id"><code>org-id</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-id.el">org-id</a> manages globally unique IDs for org entries.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-id</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-id-link-to-org-use-id</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; I want these files to be searched for IDs, so that I can use</span></span></span><span class="line"><span class="cl"><span class="c1">;; org-capture templates with them, but do not want them to be part</span></span></span><span class="line"><span class="cl"><span class="c1">;; of org-agenda or org-roam.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-id-extra-files</span><span class="p">(</span><span class="nf">list</span></span></span><span class="line"><span class="cl"><span class="nv">paths-file-tlon-tareas-leo</span></span></span><span class="line"><span class="cl"><span class="nv">paths-file-tlon-tareas-fede</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-id-ensure-locations-hash-table</span><span class="p">(</span><span class="kp">&amp;rest</span><span class="nv">_</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Ensure</span><span class="ss">`org-id-locations'</span><span class="s"> is a hash table.</span></span></span><span class="line"><span class="cl"><span class="s">If</span><span class="ss">`org-id-update-id-locations'</span><span class="s"> is interrupted between building the</span></span></span><span class="line"><span class="cl"><span class="s">alist and converting it to a hash table,</span><span class="ss">`org-id-locations'</span><span class="s"> can be</span></span></span><span class="line"><span class="cl"><span class="s">left as an alist, causing</span><span class="ss">`puthash'</span><span class="s"> errors in</span><span class="ss">`org-id-add-location'</span><span class="s">."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nb">and</span><span class="nv">org-id-locations</span><span class="p">(</span><span class="nv">not</span><span class="p">(</span><span class="nf">hash-table-p</span><span class="nv">org-id-locations</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-id-locations</span><span class="p">(</span><span class="nv">org-id-alist-to-hash</span><span class="nv">org-id-locations</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'org-id-add-location</span><span class="nb">:before</span><span class="nf">#'</span><span class="nv">org-id-ensure-locations-hash-table</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-list"><code>org-list</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-list.el">org-list</a> handles plain lists in org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-list</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-plain-list-ordered-item-terminator</span><span class="sc">?.</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-list-indent-offset</span><span class="mi">2</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-refile"><code>org-refile</code></h3><p><em>org-refile refiles subtrees to various locations.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-refile</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-refile-targets</span><span class="o">'</span><span class="p">((</span><span class="nv">org-agenda-files</span><span class="nb">:maxlevel</span><span class="o">.</span><span class="mi">9</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">files-extras-open-buffer-files</span><span class="nb">:maxlevel</span><span class="o">.</span><span class="mi">9</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">nil</span><span class="nb">:maxlevel</span><span class="o">.</span><span class="mi">9</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-refile-use-outline-path</span><span class="ss">'level3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-outline-path-complete-in-steps</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-refile-allow-creating-parent-nodes</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-refile-use-cache</span><span class="no">t</span><span class="p">)</span><span class="c1">; build cache at startup</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Regenerate cache every half hour</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">60</span><span class="mi">30</span><span class="p">)</span><span class="no">t</span><span class="nf">#'</span><span class="nv">org-extras-refile-regenerate-cache</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-keys"><code>org-keys</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-keys.el">org-keys</a> manages speed keys and key bindings for org-mode.</em></p><p>Enable speed keys. To trigger a speed key, point must be at the very beginning of an org headline. Type &lsquo;?&rsquo; for a list of keys.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-keys</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-return-follows-link</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-use-speed-commands</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-speed-commands</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"Outline navigation"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-move-safe</span><span class="ss">'org-previous-visible-heading</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-move-safe</span><span class="ss">'org-forward-heading-same-level</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-move-safe</span><span class="ss">'org-backward-heading-same-level</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-move-safe</span><span class="ss">'org-next-visible-heading</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-move-safe</span><span class="ss">'outline-up-heading</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="p">(</span><span class="nv">consult-extras-org-heading</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Outline structure editing"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-metaleft</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-metadown</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-metaup</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-metaright</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-shiftmetaleft</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-shiftmetadown</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-shiftmetaup</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-shiftmetaright</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Archiving"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-archive-subtree-default</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"'"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-force-cycle-archived</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Meta data editing"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-todo</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Clock"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-extras-jump-to-latest-clock-entry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H"</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">org-extras-jump-to-latest-clock-entry</span><span class="p">)</span><span class="p">(</span><span class="nv">org-extras-clone-clock-entry</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-clock-in</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-clock-out</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Regular editing"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="p">(</span><span class="nv">undo-only</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-cut-subtree</span><span class="p">))</span><span class="c1">; capital 'X' to prevent accidents</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-copy-subtree</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-yank</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Other"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-id-copy</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-priority</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"u"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-speed-command-help</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g"</span><span class="o">.</span><span class="p">(</span><span class="nv">org-agenda</span><span class="p">)))))</span></span></span></code></pre></div><h3 id="ol"><code>ol</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ol.el">ol</a> implements the org link framework.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ol</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-link-search-must-match-exact-headline</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-ellipsis</span><span class="s">" "</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-L"</span><span class="o">.</span><span class="nv">org-store-link</span><span class="p">))</span></span></span></code></pre></div><h3 id="ol-bbdb"><code>ol-bbdb</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ol-bbdb.el">ol-bbdb</a> provides support for links to BBDB records in org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ol-bbdb</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">bbdb</span><span class="nv">ol</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-bbdb-anniversary-field</span><span class="ss">'birthday</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-protocol"><code>org-protocol</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-protocol.el">org-protocol</a> intercepts calls from emacsclient to trigger custom actions.</em></p><p><a href="https://www.orgroam.com/manual.html#Mac-OS">This section of the org-roam manual</a> describes how to set up<code>org-protocol</code> on macOS. Note that<a href="https://bitbucket.org/mituharu/emacs-mac/">emacs-mac</a> supports<code>org-protocol</code> out of the box and doesn&rsquo;t require turning on the Emacs server.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-protocol</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="p">)</span></span></span></code></pre></div><h3 id="ox"><code>ox</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ox.el">ox</a> is the generic export engine for org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-exclude-tags</span><span class="o">'</span><span class="p">(</span><span class="s">"noexport"</span><span class="s">"ARCHIVE"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-broken-links</span><span class="ss">'mark</span><span class="p">)</span><span class="c1">; allow export with broken links</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-section-numbers</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not add numbers to section headings</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-toc</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not include table of contents</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-title</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not include title</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-headline-levels</span><span class="mi">4</span><span class="p">)</span><span class="c1">; include up to level 4 headlines</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-tasks</span><span class="no">nil</span><span class="p">)</span><span class="c1">; exclude headings with TODO keywords</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-with-todo-keywords</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not render TODO keywords in headings</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-preserve-breaks</span><span class="no">t</span><span class="p">)</span><span class="c1">; respect single breaks when exporting</span></span></span><span class="line"><span class="cl"><span class="c1">;; (org-export-with-author nil "do not include author")</span></span></span><span class="line"><span class="cl"><span class="c1">;; (org-export-with-date nil "do not include export date")</span></span></span><span class="line"><span class="cl"><span class="c1">;; (org-html-validation-link nil "do not include validation link")</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-show-temporary-export-buffer</span><span class="no">nil</span><span class="p">))</span><span class="c1">; bury temporary export buffers generated by `org-msg'</span></span></span></code></pre></div><h3 id="ox-html"><code>ox-html</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ox-html.el">ox-html</a> is the HTML back-end for the org export engine.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ox-html</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-html-postamble</span><span class="no">nil</span><span class="p">))</span><span class="c1">; the three lines above unnecessary when this set to nil</span></span></span></code></pre></div><h3 id="ox-latex"><code>ox-latex</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ox-latex.el">ox-latex</a> is the LaTeX back-end for the org export engine.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ox-latex</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; get rid of temporary LaTeX files upon export</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-latex-logfiles-extensions</span><span class="p">(</span><span class="nb">quote</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"lof"</span><span class="s">"lot"</span><span class="s">"tex"</span><span class="s">"aux"</span><span class="s">"idx"</span><span class="s">"log"</span><span class="s">"out"</span><span class="s">"toc"</span><span class="s">"nav"</span><span class="s">"snm"</span><span class="s">"vrb"</span><span class="s">"dvi"</span><span class="s">"fdb_latexmk"</span><span class="s">"blg"</span><span class="s">"brf"</span><span class="s">"fls"</span><span class="s">"entoc"</span><span class="s">"ps"</span><span class="s">"spl"</span><span class="s">"bbl"</span><span class="s">"pygtex"</span><span class="s">"pygstyle"</span><span class="p">))))</span></span></span></code></pre></div><h3 id="ox-hugo"><code>ox-hugo</code></h3><p><em><a href="https://github.com/kaushalmodi/ox-hugo">ox-hugo</a> is an org-mode exporter back-end for Hugo.</em></p><p>Hugo should be able to export<code>org-cite</code> citations.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ox-hugo</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-hugo-default-section-directory</span><span class="s">"posts"</span><span class="p">))</span></span></span></code></pre></div><h3 id="ox-hugo-extras"><code>ox-hugo-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/ox-hugo-extras.el">ox-hugo-extras</a> collects my extensions for<code>ox-hugo</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">ox-hugo-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ox-hugo</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="stafforini"><code>stafforini</code></h3><p><em><a href="https://github.com/benthamite/stafforini.el">stafforini</a> is a private package that provides Emacs commands for building and previewing my personal site, built with Hugo.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">stafforini</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"benthamite/stafforini.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">((</span><span class="s">"A-H-s"</span><span class="o">.</span><span class="nv">stafforini-menu</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ox-pandoc"><code>ox-pandoc</code></h3><p><em><a href="https://github.com/kawabata/ox-pandoc">ox-pandoc</a> is an org-mode exporter that uses Pandoc.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ox-pandoc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ox-gfm"><code>ox-gfm</code></h3><p><em><a href="https://github.com/larstvei/ox-gfm">ox-gfm</a> is a Github Flavored Markdown org-mode exporter.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ox-gfm</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">ox</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ob"><code>ob</code></h3><p><em>ob provides support for code blocks in org-mode.</em></p><p>Note to self: Typescript syntax highlighting works fine, but calling<code>org-edit-special</code> triggers an error; see the gptel conversation named<code>typescript-syntax-highlighting</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ob</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-confirm-babel-evaluate</span><span class="ss">'org-extras-confirm-babel-evaluate</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-export-use-babel</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; enable lexical binding in code blocks</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">setcdr</span><span class="p">(</span><span class="nf">assq</span><span class="nb">:lexical</span><span class="nv">org-babel-default-header-args:emacs-lisp</span><span class="p">)</span><span class="s">"no"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; Prevent code-block evaluation during export while preserving noweb expansion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="p">(</span><span class="nv">alist-get</span><span class="nb">:eval</span><span class="nv">org-babel-default-header-args</span><span class="p">)</span><span class="s">"never-export"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-babel-default-header-args:python</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nb">:exports</span><span class="o">.</span><span class="s">"both"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:results</span><span class="o">.</span><span class="s">"replace output"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:session</span><span class="o">.</span><span class="s">"none"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:cache</span><span class="o">.</span><span class="s">"no"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:noweb</span><span class="o">.</span><span class="s">"no"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:hlines</span><span class="o">.</span><span class="s">"no"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:tangle</span><span class="o">.</span><span class="s">"no"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-babel-do-load-languages</span></span></span><span class="line"><span class="cl"><span class="ss">'org-babel-load-languages</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">emacs-lisp</span><span class="o">.</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shell</span><span class="o">.</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">python</span><span class="o">.</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">R</span><span class="o">.</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nf">cons</span><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nf">cons</span><span class="s">"j"</span><span class="ss">'org-babel-next-src-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="s">"k"</span><span class="ss">'org-babel-previous-src-block</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="s">"n"</span><span class="ss">'org-babel-insert-header-arg</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="s">"p"</span><span class="ss">'org-babel-remove-result-one-or-many</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'org-babel-key-bindings</span><span class="nf">cons</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ob-typescript"><code>ob-typescript</code></h3><p><em><a href="https://github.com/lurdan/ob-typescript">ob-typescript</a> enables the execution of typescript code blocks.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ob-typescript</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ob</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-babel-default-header-args:typescript</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nb">:mode</span><span class="o">.</span><span class="nv">typescript-ts-mode</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'org-babel-load-languages</span><span class="o">'</span><span class="p">(</span><span class="nv">typescript</span><span class="o">.</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'major-mode-remap-alist</span><span class="o">'</span><span class="p">(</span><span class="nv">typescript-mode</span><span class="o">.</span><span class="nv">typescript-ts-mode</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defalias</span><span class="ss">'typescript-mode</span><span class="ss">'typescript-ts-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-tempo"><code>org-tempo</code></h3><p><em>org-tempo provides completion templates for org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-tempo</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-src"><code>org-src</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-src.el">org-src</a> manages source code blocks in org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-src</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-edit-src-content-indentation</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-src-preserve-indentation</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-src-window-setup</span><span class="ss">'current-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-src-tab-acts-natively</span><span class="no">nil</span><span class="p">)</span><span class="c1">; When set to `nil', newlines will be properly indented</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-src-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">org-edit-src-exit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-table"><code>org-table</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-table.el">org-table</a> is the plain-text table editor for org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-table</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-table-fedit-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">org-table-fedit-finish</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-table-wrap"><code>org-table-wrap</code></h3><p><em><a href="https://github.com/benthamite/org-table-wrap">org-table-wrap</a> provides visual word-wrapping for org mode tables.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-table-wrap</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/org-table-wrap"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-table</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-table-wrap-width-fraction</span><span class="mf">0.8</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-mode-hook</span><span class="o">.</span><span class="nv">org-table-wrap-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="orgtbl-edit"><code>orgtbl-edit</code></h3><p><em><a href="https://github.com/shankar2k/orgtbl-edit">orgtbl-edit</a> allows editing a spreadsheet or text-delimited file as an org table.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">orgtbl-edit</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"shankar2k/orgtbl-edit"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-table</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="orgtbl-join"><code>orgtbl-join</code></h3><p><em><a href="https://github.com/tbanel/orgtbljoin">orgtbl-join</a> joins two org tables on a common column.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">orgtbl-join</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-table</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-crypt"><code>org-crypt</code></h3><p><em><a href="https://orgmode.org/manual/Org-Crypt.html">org-crypt</a> encrypts the text under all headlines with a designated tag.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-crypt</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-crypt-key</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_GMAIL"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-crypt-disable-auto-save</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-crypt-use-before-save-magic</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-element"><code>org-element</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-element.el">org-element</a> implements a parser and an API for org syntax.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-element</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; set to nil to temporarily disable cache and avoid `org-element-cache' errors</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-element-use-cache</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; `org-capture' creates an indirect buffer with `clone', which copies</span></span></span><span class="line"><span class="cl"><span class="c1">;; the base buffer's cache. The cloned cache is immediately stale</span></span></span><span class="line"><span class="cl"><span class="c1">;; because the capture buffer is narrowed and has the template inserted.</span></span></span><span class="line"><span class="cl"><span class="c1">;; Reset it so the cache is rebuilt from scratch in the capture buffer.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'org-capture-mode-hook</span><span class="nf">#'</span><span class="nv">org-element-cache-reset</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; `org-element-at-point' wraps its cache recovery code in</span></span></span><span class="line"><span class="cl"><span class="c1">;; `condition-case-unless-debug', which is disabled when</span></span></span><span class="line"><span class="cl"><span class="c1">;; `debug-on-error' is non-nil. This causes every cache error—stale</span></span></span><span class="line"><span class="cl"><span class="c1">;; entries, invalid search bounds, missing parents—to enter the</span></span></span><span class="line"><span class="cl"><span class="c1">;; debugger instead of being handled by Org's built-in reset-and-retry</span></span></span><span class="line"><span class="cl"><span class="c1">;; logic. Temporarily binding `debug-on-error' to nil lets the</span></span></span><span class="line"><span class="cl"><span class="c1">;; existing recovery work while preserving the debugger for all other</span></span></span><span class="line"><span class="cl"><span class="c1">;; code.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">define-advice</span><span class="nv">org-element-at-point</span><span class="p">(</span><span class="nb">:around</span><span class="p">(</span><span class="nv">fn</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span><span class="nv">let-cache-recovery-work</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">debug-on-error</span><span class="no">nil</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">fn</span><span class="nv">args</span><span class="p">))))</span></span></span></code></pre></div><h3 id="org-lint"><code>org-lint</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-lint.el">org-lint</a> checks org files for common errors.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-lint</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-habit"><code>org-habit</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-habit.el">org-habit</a> tracks habits and displays consistency graphs in the agenda.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-habit</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-today-glyph</span><span class="mh">#x1f4c5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-completed-glyph</span><span class="mh">#x2713</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-preceding-days</span><span class="mi">25</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-following-days</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-graph-column</span><span class="mi">85</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-show-habits</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-habit-show-habits-only-for-today</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-contrib"><code>org-contrib</code></h3><p><em><a href="https://git.sr.ht/~bzg/org-contrib">org-contrib</a> features add-ons to<code>org-mode</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-contrib</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-checklist"><code>org-checklist</code></h3><p><em><a href="https://git.sr.ht/~bzg/org-contrib/tree/main/item/lisp/org-checklist.el">org-checklist</a> resets checkboxes in repeating org entries.</em></p><p>Allows reset of checkboxes in recurring tasks. This works only on headings that have the property<code>RESET_CHECK_BOXES</code> set to<code>t</code>. You can set the property of a heading by invoking the command<code>org-set-property</code> with point on that heading or immediately under it.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-checklist</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-contrib</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-make-toc"><code>org-make-toc</code></h3><p><em><a href="https://github.com/alphapapa/org-make-toc">org-make-toc</a> generates automatic tables of contents for org files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-make-toc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-journal"><code>org-journal</code></h3><p><em><a href="https://github.com/bastibe/org-journal">org-journal</a> is an org-mode based journaling mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-journal</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-journal-dir</span><span class="nv">paths-dir-journal</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-journal-date-format</span><span class="s">"%A, %d %B %Y"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-journal-file-format</span><span class="s">"%Y-%m-%d.org"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-journal-new-entry-in-journal</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Create a new journal entry in the selected journal."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">journal-dirs</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-dir-tlon-todos</span><span class="nv">paths-dir-journal</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="p">(</span><span class="nf">mapcar</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">dir</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="p">(</span><span class="nf">file-name-nondirectory</span><span class="p">(</span><span class="nf">directory-file-name</span><span class="nv">dir</span><span class="p">))</span><span class="nv">dir</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nv">journal-dirs</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">choice</span><span class="p">(</span><span class="nf">completing-read</span><span class="s">"Journal: "</span><span class="nf">cons</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-journal-dir</span><span class="p">(</span><span class="nv">alist-get</span><span class="nv">choice</span><span class="nf">cons</span><span class="no">nil</span><span class="no">nil</span><span class="ss">'string=</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-journal-new-entry</span><span class="no">nil</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-j"</span><span class="o">.</span><span class="nv">org-journal-new-entry-in-journal</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-contacts"><code>org-contacts</code></h3><p><em><a href="https://repo.or.cz/org-contacts.git">org-contacts</a> is a contacts management system for Org Mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-contacts</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">tlon</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-contacts-files</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-tlon-repos</span><span class="s">"babel-core/contacts.org"</span><span class="p">))))</span></span></span></code></pre></div><h3 id="org-vcard"><code>org-vcard</code></h3><p><em><a href="https://github.com/pinoaffe/org-vcard">org-vcard</a> imports and exports vCards from within org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-vcard</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; optimized for macOS Contacts.app</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-vcard-styles-languages-mappings</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"flat"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"en"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"3.0"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;TYPE=\"home\";PREF=1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;TYPE=\"home\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"BIRTHDAY"</span><span class="o">.</span><span class="s">"BDAY"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"EMAIL"</span><span class="o">.</span><span class="s">"EMAIL;PREF=1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"FN"</span><span class="o">.</span><span class="s">"FN"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"PHOTO"</span><span class="o">.</span><span class="s">"PHOTO;TYPE=JPEG"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"URL"</span><span class="o">.</span><span class="s">"item1.URL;type=pref"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"4.0"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;TYPE=\"home\";PREF=1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;TYPE=\"home\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"BIRTHDAY"</span><span class="o">.</span><span class="s">"BDAY"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"EMAIL"</span><span class="o">.</span><span class="s">"EMAIL;PREF=1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"FN"</span><span class="o">.</span><span class="s">"FN"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"PHOTO"</span><span class="o">.</span><span class="s">"PHOTO;TYPE=JPEG"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"URL"</span><span class="o">.</span><span class="s">"URL;PREF=1"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"2.1"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;HOME;PREF"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"ADDRESS_HOME"</span><span class="o">.</span><span class="s">"ADR;HOME"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"BIRTHDAY"</span><span class="o">.</span><span class="s">"BDAY"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"EMAIL"</span><span class="o">.</span><span class="s">"EMAIL;PREF"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"FN"</span><span class="o">.</span><span class="s">"FN"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"PHOTO"</span><span class="o">.</span><span class="s">"PHOTO;TYPE=JPEG"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"URL"</span><span class="o">.</span><span class="s">"URL;PREF"</span><span class="p">)))))))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">org-vcard--save-photo-and-make-link</span><span class="p">(</span><span class="nv">base64-data</span><span class="nv">contact-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Save base64 photo data to file and return org link."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">photo-dir</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="s">"contact-photos"</span><span class="nv">user-emacs-directory</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">safe-name</span><span class="p">(</span><span class="nv">replace-regexp-in-string</span><span class="s">"[^a-zA-Z0-9]"</span><span class="s">"_"</span><span class="nv">contact-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">filename</span><span class="p">(</span><span class="nf">expand-file-name</span><span class="p">(</span><span class="nf">concat</span><span class="nv">safe-name</span><span class="s">".jpg"</span><span class="p">)</span><span class="nv">photo-dir</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">unless</span><span class="p">(</span><span class="nf">file-directory-p</span><span class="nv">photo-dir</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">make-directory</span><span class="nv">photo-dir</span><span class="no">t</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-temp-file</span><span class="nv">filename</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">set-buffer-multibyte</span><span class="no">nil</span><span class="p">)</span><span class="c1">; Use unibyte mode for binary data</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">coding-system-for-write</span><span class="ss">'binary</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Remove potential MIME type header if present</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">string-match</span><span class="s">"^data:image/[^;]+;base64,"</span><span class="nv">base64-data</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">base64-data</span><span class="p">(</span><span class="nf">substring</span><span class="nv">base64-data</span><span class="p">(</span><span class="nf">match-end</span><span class="mi">0</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Process base64 data in chunks</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">chunk-size</span><span class="mi">4096</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">start</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">total-length</span><span class="p">(</span><span class="nf">length</span><span class="nv">base64-data</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">while</span><span class="p">(</span><span class="nf">&lt;</span><span class="nv">start</span><span class="nv">total-length</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">end</span><span class="p">(</span><span class="nf">min</span><span class="p">(</span><span class="nf">+</span><span class="nv">start</span><span class="nv">chunk-size</span><span class="p">)</span><span class="nv">total-length</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">chunk</span><span class="p">(</span><span class="nf">substring</span><span class="nv">base64-data</span><span class="nv">start</span><span class="nv">end</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="p">(</span><span class="nf">base64-decode-string</span><span class="nv">chunk</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">start</span><span class="nv">end</span><span class="p">))))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">format</span><span class="s">"\n#+ATTR_ORG: :width 300\n[[file:%s]]\n"</span><span class="nv">filename</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'org-vcard--transfer-write</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">orig-fun</span><span class="nv">direction</span><span class="nv">content</span><span class="nv">destination</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Convert PHOTO properties to image links before writing."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">eq</span><span class="nv">direction</span><span class="ss">'import</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">((</span><span class="nv">modified-content</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-temp-buffer</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="nv">content</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">goto-char</span><span class="p">(</span><span class="nf">point-min</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">while</span><span class="p">(</span><span class="nf">re-search-forward</span><span class="s">"^:PHOTO: \\(.+\\)$"</span><span class="no">nil</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">base64-data</span><span class="p">(</span><span class="nv">match-string</span><span class="mi">1</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">heading</span><span class="p">(</span><span class="nb">save-excursion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">re-search-backward</span><span class="s">"^\\* \\(.+\\)$"</span><span class="no">nil</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">match-string</span><span class="mi">1</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">photo-link</span><span class="p">(</span><span class="nb">condition-case</span><span class="nv">err</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-vcard--save-photo-and-make-link</span></span></span><span class="line"><span class="cl"><span class="nv">base64-data</span><span class="nv">heading</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ne">error</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"Error processing photo for %s: %s"</span></span></span><span class="line"><span class="cl"><span class="nv">heading</span><span class="p">(</span><span class="nf">error-message-string</span><span class="nv">err</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="s">":PHOTO: [Error processing photo]\n"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">delete-region</span><span class="p">(</span><span class="nf">line-beginning-position</span><span class="p">)</span><span class="p">(</span><span class="nf">line-end-position</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Delete any following empty line</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">when</span><span class="p">(</span><span class="nf">looking-at</span><span class="s">"\n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">delete-char</span><span class="mi">1</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">save-excursion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">re-search-forward</span><span class="s">":END:\n"</span><span class="no">nil</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="nv">photo-link</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">buffer-string</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">funcall</span><span class="nv">orig-fun</span><span class="nv">direction</span><span class="nv">modified-content</span><span class="nv">destination</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">funcall</span><span class="nv">orig-fun</span><span class="nv">direction</span><span class="nv">content</span><span class="nv">destination</span><span class="p">)))))</span></span></span></code></pre></div><h3 id="org-autosort"><code>org-autosort</code></h3><p><em><a href="https://github.com/yantar92/org-autosort">org-autosort</a> sorts entries in org files automatically.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-autosort</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"yantar92/org-autosort"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span><span class="p">)</span></span></span></code></pre></div><h3 id="ox-clip"><code>ox-clip</code></h3><p><em><a href="https://github.com/jkitchin/ox-clip">ox-clip</a> copies selected regions in org-mode as formatted text on the clipboard.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ox-clip</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; github.com/jkitchin/ox-clip/issues/13</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ox-clip-osx-cmd</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"HTML"</span><span class="o">.</span><span class="s">"hexdump -ve '1/1 \"%.2x\"' | xargs printf \"set the clipboard to {text:\\\" \\\", «class HTML»:«data HTML%s»}\" | osascript -"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Markdown"</span><span class="o">.</span><span class="s">"pandoc --wrap=none -f html -t \"markdown-smart+hard_line_breaks\" - | grep -v \"^:::\" | sed 's/{#.*}//g' | sed 's/\\\\`/</span><span class="ss">`/g'</span><span class="s"> | pbcopy"</span><span class="p">))))</span></span></span></code></pre></div><h3 id="elgantt"><code>elgantt</code></h3><p><em><a href="https://github.com/legalnonsense/elgantt/">elgantt</a> is a gantt chart for org mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elgantt</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"legalnonsense/elgantt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-pomodoro"><code>org-pomodoro</code></h3><p><em><a href="https://github.com/marcinkoziej/org-pomodoro">org-pomodoro</a> provides org-mode support for the Pomodoro technique.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-pomodoro</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">org-agenda</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-length</span><span class="mi">25</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-short-break-length</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-long-break-length</span><span class="nv">org-pomodoro-short-break-length</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-finished-sound</span><span class="s">"/System/Library/Sounds/Blow.aiff"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-long-break-sound</span><span class="nv">org-pomodoro-finished-sound</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-short-break-sound</span><span class="nv">org-pomodoro-finished-sound</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-started-hook</span><span class="o">.</span><span class="nv">org-extras-pomodoro-format-timer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-started-hook</span><span class="o">.</span><span class="nv">tab-bar-extras-disable-all-notifications</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-started-hook</span><span class="o">.</span><span class="nv">org-extras-narrow-to-entry-and-children</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-finished-hook</span><span class="o">.</span><span class="nv">tab-bar-extras-enable-all-notifications</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-pomodoro-finished-hook</span><span class="o">.</span><span class="nf">widen</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-I"</span><span class="o">.</span><span class="nv">org-pomodoro</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-e"</span><span class="o">.</span><span class="nv">org-pomodoro-extend-last-clock</span><span class="p">)))</span></span></span></code></pre></div><ul><li>check:<a href="https://gist.github.com/bravosierrasierra/1d98a89a7bcb618ef70c6c4a92af1a96#file-org-pomodoro-plus">https://gist.github.com/bravosierrasierra/1d98a89a7bcb618ef70c6c4a92af1a96#file-org-pomodoro-plus</a></li></ul><h3 id="org-pomodoro-extras"><code>org-pomodoro-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-pomodoro-extras.el">org-pomodoro-extras</a> collects my extensions for<code>org-pomodoro</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-pomodoro-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-pomodoro</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-percentile"><code>org-percentile</code></h3><p><em><a href="https://github.com/benthamite/org-percentile">org-percentile</a> is a productivity tool that let’s you compete with your past self.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-percentile</span></span></span><span class="line"><span class="cl"><span class="nb">:disabled</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/org-percentile"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-clock</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-percentile-data-file</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dropbox</span><span class="s">"misc/org-percentile-data.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-percentile-mode</span><span class="p">))</span></span></span></code></pre></div><h2 id="note-taking">note-taking</h2><h3 id="org-roam"><code>org-roam</code></h3><p><em><a href="https://github.com/org-roam/org-roam">org-roam</a> is a Roam replica with org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-roam</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/org-roam"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"fix/handle-nil-db-version"</span><span class="p">)</span><span class="c1">; https://github.com/org-roam/org-roam/pull/2609</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-directory</span><span class="nv">paths-dir-org-roam</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-node-display-template</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="s">"${title:*} "</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">propertize</span><span class="s">"${tags:10}"</span><span class="ss">'face</span><span class="ss">'org-tag</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-node-display-template</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="s">"${hierarchy:160} "</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">propertize</span><span class="s">"${tags:20}"</span><span class="ss">'face</span><span class="ss">'org-tag</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="c1">;; exclude selected headings based on other criteria</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-db-node-include-function</span><span class="nf">#'</span><span class="nv">org-roam-extras-node-include-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'org-roam-bibtex</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">org-roam-mode-sections</span><span class="p">(</span><span class="nf">append</span><span class="nv">org-roam-mode-sections</span><span class="o">'</span><span class="p">(</span><span class="nv">orb-section-reference</span><span class="nv">orb-section-abstract</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; include transcluded links in `org-roam' backlinks</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">delete</span><span class="o">'</span><span class="p">(</span><span class="nv">keyword</span><span class="s">"transclude"</span><span class="p">)</span><span class="nv">org-roam-db-extra-links-exclude-keys</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/org-roam/org-roam/issues/2550#issuecomment-3451456331</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'org-roam-capture</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">org-roam-capture-new-node-hook</span><span class="no">nil</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">org-roam-node-insert</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">org-roam-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-org</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-roam-extras"><code>org-roam-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-roam-extras.el">org-roam-extras</a> collects my extensions for<code>org-roam</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-roam-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-extras-auto-show-backlink-buffer</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; exclude headings in specific files and directories</span></span></span><span class="line"><span class="cl"><span class="c1">;; Set here rather than in :custom so that `org-roam-extras-excluded-dirs'</span></span></span><span class="line"><span class="cl"><span class="c1">;; and `org-roam-extras-excluded-files' are guaranteed to be defined (they</span></span></span><span class="line"><span class="cl"><span class="c1">;; are void if org-roam loads first, e.g. via a citar idle timer).</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">org-roam-file-exclude-regexp</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let</span><span class="p">(</span><span class="nv">result</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">dir-or-file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">append</span></span></span><span class="line"><span class="cl"><span class="nv">org-roam-extras-excluded-dirs</span></span></span><span class="line"><span class="cl"><span class="nv">org-roam-extras-excluded-files</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">regexp-opt</span><span class="nv">result</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nf">file-directory-p</span><span class="nv">dir-or-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-relative-name</span><span class="nv">dir-or-file</span><span class="nv">paths-dir-org-roam</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nv">dir-or-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nv">result</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-extras-setup-db-sync</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-capture-prepare-finalize-hook</span><span class="o">.</span><span class="nv">org-roam-extras-remove-file-level-properties</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-N"</span><span class="o">.</span><span class="nv">org-roam-extras-new-note</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-j"</span><span class="o">.</span><span class="nv">org-roam-extras-node-find</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-J"</span><span class="o">.</span><span class="nv">org-roam-extras-node-find-special</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-roam-ui"><code>org-roam-ui</code></h3><p><em><a href="https://github.com/org-roam/org-roam-ui">org-roam-ui</a> is a graphical frontend for exploring org-roam.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-roam-ui</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"org-roam/org-roam-ui"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"main"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"*.el"</span><span class="s">"out"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-roam</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-ui-sync-theme</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-ui-follow</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-ui-update-on-save</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-ui-open-on-start</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-transclusion"><code>org-transclusion</code></h3><p><em><a href="https://github.com/nobiot/org-transclusion">org-transclusion</a> supports<a href="https://en.wikipedia.org/wiki/Transclusion">transclusion</a> with org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-transclusion</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">element</span><span class="o">'</span><span class="p">(</span><span class="nv">headline</span><span class="nv">drawer</span><span class="nv">property-drawer</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="nv">element</span><span class="nv">org-transclusion-exclude-elements</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">face-spec-set</span><span class="ss">'org-transclusion-fringe</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((((</span><span class="nv">background</span><span class="nv">light</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:foreground</span><span class="s">"black"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:foreground</span><span class="s">"white"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="ss">'face-override-spec</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">face-spec-set</span><span class="ss">'org-transclusion-source-fringe</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((((</span><span class="nv">background</span><span class="nv">light</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:foreground</span><span class="s">"black"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:foreground</span><span class="s">"white"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="ss">'face-override-spec</span><span class="p">))</span></span></span></code></pre></div><h3 id="vulpea"><code>vulpea</code></h3><p><em><a href="https://github.com/d12frosted/vulpea">vulpea</a> is a collection of functions for note-taking based on<code>org</code> and<code>org-roam</code>.</em></p><p>I use this package to define a dynamic agenda, as explained and illustrated<a href="https://d12frosted.io/posts/2021-01-16-task-management-with-roam-vol5.html">here</a>. I&rsquo;ve made some changes to the system in that link, specifically to exclude files and directories at various stages:</p><ol><li>At the broadest level, I exclude files and directories from the function (<code>org-extras-id-auto-add-ids-to-headings-in-file</code>) that otherwise automatically adds an ID to every org heading in a file-visiting buffer. Headings so excluded are not indexed by org-roam, because a heading requires an ID to be indexed. For details, see that function’s docstring. For examples of how this is used in my config, see the variables<code>org-extras-id-auto-add-excluded-files</code> and<code>org-extras-id-auto-add-excluded-directories</code> under the<code>org-id</code> section of this file.</li><li>I then exclude some headings with IDs from the org-roam database. For examples of how this is used in my config, see the variables<code>org-roam-file-exclude-regexp</code> and<code>org-roam-db-node-include-function</code> under the<code>org-roam</code> section of this file.</li><li>Finally, I selectively include in<code>org-agenda-files</code> files that satisfy certain conditions (as defined by<code>vulpea-extras-project-p</code>) and files modified recently (as specified by<code>org-roam-extras-recent</code>), and exclude from<code>org-agenda-files</code> files listed in<code>org-extras-agenda-files-excluded</code>.</li></ol><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">vulpea</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">org-roam</span><span class="p">)</span></span></span></code></pre></div><h3 id="vulpea-extras"><code>vulpea-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/vulpea-extras.el">vulpea-extras</a> collects my extensions for<code>vulpea</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">vulpea-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">find-file-hook</span><span class="nv">before-save-hook</span><span class="p">)</span><span class="o">.</span><span class="nv">vulpea-extras-project-update-tag</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-noter"><code>org-noter</code></h3><p><em><a href="https://github.com/org-noter/org-noter">org-noter</a> is an org-mode document annotator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-noter</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"org-noter/org-noter"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'pdf-annot</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">pdf-annot-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">org-noter-create-skeleton</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-notes-search-path</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">paths-dir-bibliographic-notes</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-auto-save-last-location</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-always-create-frame</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-separate-notes-from-heading</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-kill-frame-at-session-end</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-noter-use-indirect-buffer</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="nv">paths-file-orb-noter-template</span><span class="nv">org-extras-id-auto-add-excluded-files</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-noter-notes-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-n"</span><span class="o">.</span><span class="nv">org-noter-sync-current-note</span><span class="p">)))</span></span></span></code></pre></div><ul><li>To check:<a href="https://org-roam.discourse.group/t/org-roam-bibtex-in-a-sub-directory/649/5">https://org-roam.discourse.group/t/org-roam-bibtex-in-a-sub-directory/649/5</a></li><li><a href="https://notes.andymatuschak.org/About_these_notes">https://notes.andymatuschak.org/About_these_notes</a></li></ul><h3 id="org-noter-extras"><code>org-noter-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-noter-extras.el">org-noter-extras</a> collects my extensions for<code>org-noter</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-noter-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-noter</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-noter-notes-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">org-noter-extras-cleanup-annotation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">org-noter-extras-dehyphenate</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">org-noter-extras-sync-prev-note</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-l"</span><span class="o">.</span><span class="nv">org-noter-extras-sync-next-note</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">org-noter-extras-highlight-offset</span><span class="p">)))</span></span></span></code></pre></div><h2 id="spaced-repetition">spaced-repetition</h2><h3 id="anki-editor"><code>anki-editor</code></h3><p><em><a href="https://github.com/anki-editor/anki-editor">anki-editor</a> is a minor mode for making Anki cards with Org Mode.</em></p><p>The<a href="https://github.com/louietan/anki-editor">original package</a> is abandoned, but there is an actively maintained<a href="https://github.com/anki-editor/anki-editor">fork</a>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">anki-editor</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"anki-editor/anki-editor"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/anki-editor/anki-editor/issues/116</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">anki-editor-export-note-fields-on-push</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">anki-editor-org-tags-as-anki-tags</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="anki-editor-extras"><code>anki-editor-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/anki-editor-extras.el">anki-editor-extras</a> collects my extensions for<code>anki-editor</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">anki-editor-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">anki-editor</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ankiorg"><code>ankiorg</code></h3><p><em><a href="https://github.com/orgtre/ankiorg">ankiorg</a> is an anki-editor add-on which pulls Anki notes to Org.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ankiorg</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span><span class="nb">:repo</span><span class="s">"orgtre/ankiorg"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">anki-editor</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ankiorg-sql-database</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">no-littering-var-directory</span><span class="s">"ankiorg/collection.anki2"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ankiorg-media-directory</span></span></span><span class="line"><span class="cl"><span class="nv">no-littering-var-directory</span><span class="s">"ankiorg/img"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ankiorg-pick-deck-all-directly</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="anki-noter"><code>anki-noter</code></h3><p><em><a href="https://github.com/benthamite/anki-noter">anki-noter</a> AI-powered Anki notes generator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">anki-noter</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/anki-noter"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h2 id="reference-and-citation">reference &amp; citation</h2><p>See<a href="https://github.com/emacs-citar/citar/wiki/Comparisons#summary-of-diverse-emacs-bibliographic-and-citation-packages">this section</a> of citar&rsquo;s manual for a handy summary of the main bibliographic and citation Emacs packages.</p><p>I split my bibliographies into two categories: personal and work. The files providing my personal bibliography are defined in<code>paths-files-bibliography-personal</code>. The files providing my work bibliography are defined in<code>tlon-bibliography-files</code>. I then define<code>paths-files-bibliography-all</code> as the concatenation of these two lists. Finally, this master variable is used to set the values of the user options for all package that define bibliographies:</p><ul><li><code>bibtex-files</code> (for<code>bibtext</code>)</li><li><code>bibtex-completion-bibliography</code> (for<code>bibtex-completion</code>)</li><li><code>citar-bibliography</code> (for<code>citar</code>)</li><li><code>ebib-preload-bib-files</code> (for<code>ebib</code>)</li></ul><p>Each of these packages requires<code>tlon</code>, since the latter must load for<code>paths-files-bibliography-all</code> to be set.</p><h3 id="oc"><code>oc</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/oc.el">oc</a> is Org mode&rsquo;s built-in citation handling library.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">oc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span><span class="nv">el-patch</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-insert-processor</span><span class="ss">'citar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-follow-processor</span><span class="ss">'citar</span><span class="p">)</span><span class="c1">; `org-open-at-point' integration</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-activate-processor</span><span class="ss">'citar</span><span class="p">)</span><span class="c1">;</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-export-processors</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="no">t</span><span class="o">.</span><span class="p">(</span><span class="nv">csl</span><span class="s">"long-template.csl"</span><span class="p">)))))</span></span></span></code></pre></div><h3 id="oc-csl"><code>oc-csl</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/oc-csl.el">oc-csl</a> is a CSL citation processor for Org mode&rsquo;s citation system.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">oc-csl</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">oc</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-csl-styles-dir</span><span class="nv">paths-dir-tlon-csl-styles</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-csl-locales-dir</span><span class="nv">paths-dir-tlon-csl-locales</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-footnote"><code>org-footnote</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/org/org-footnote.el">org-footnote</a> provides footnote support in org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">org-footnote</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-footnote-auto-adjust</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="citeproc"><code>citeproc</code></h3><p><em><a href="https://github.com/andras-simonyi/citeproc-el">citeproc</a> is a CSL 1.0.2 Citation Processor for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">citeproc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">oc</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="bibtex"><code>bibtex</code></h3><p><em>bibtex is major mode for editing and validating BibTeX<code>.bib</code> files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">bibtex</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ebib</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-files</span><span class="nv">paths-files-bibliography-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; This corresponds (roughly?) to `auth+year+shorttitle(3,3)' on Better BibTeX</span></span></span><span class="line"><span class="cl"><span class="c1">;; retorque.re/zotero-better-bibtex/citing/</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-search-entry-globally</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-names</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-name-case-convert-function</span><span class="ss">'capitalize</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-year-length</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-year-title-separator</span><span class="s">""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-title-terminators</span><span class="s">"[.!?;]\\|--"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titlewords</span><span class="mi">3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titlewords-stretch</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titleword-case-convert-function</span><span class="ss">'capitalize</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titleword-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titleword-separator</span><span class="s">""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-titleword-ignore</span><span class="o">'</span><span class="p">(</span><span class="s">"A"</span><span class="s">"a"</span><span class="s">"An"</span><span class="s">"an"</span><span class="s">"On"</span><span class="s">"on"</span><span class="s">"The"</span><span class="s">"the"</span><span class="s">"Eine?"</span><span class="s">"Der"</span><span class="s">"Die"</span><span class="s">"Das"</span><span class="s">"El"</span><span class="s">"La"</span><span class="s">"Lo"</span><span class="s">"Los"</span><span class="s">"Las"</span><span class="s">"Un"</span><span class="s">"Una"</span><span class="s">"Unos"</span><span class="s">"Unas"</span><span class="s">"el"</span><span class="s">"la"</span><span class="s">"lo"</span><span class="s">"los"</span><span class="s">"las"</span><span class="s">"un"</span><span class="s">"una"</span><span class="s">"unos"</span><span class="s">"unas"</span><span class="s">"y"</span><span class="s">"o"</span><span class="s">"Le"</span><span class="s">"La"</span><span class="s">"L'"</span><span class="s">"Les"</span><span class="s">"Un"</span><span class="s">"Une"</span><span class="s">"Des"</span><span class="s">"Du"</span><span class="s">"De la"</span><span class="s">"De l'"</span><span class="s">"Des"</span><span class="s">"le"</span><span class="s">"la"</span><span class="s">"l'"</span><span class="s">"les"</span><span class="s">"un"</span><span class="s">"une"</span><span class="s">"des"</span><span class="s">"du"</span><span class="s">"de la"</span><span class="s">"de l'"</span><span class="s">"des"</span><span class="s">"Lo"</span><span class="s">"Il"</span><span class="s">"La"</span><span class="s">"L'"</span><span class="s">"Gli"</span><span class="s">"I"</span><span class="s">"Le"</span><span class="s">"Uno"</span><span class="s">"lo"</span><span class="s">"il"</span><span class="s">"la"</span><span class="s">"l'"</span><span class="s">"gli"</span><span class="s">"i"</span><span class="s">"le"</span><span class="s">"uno"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Remove accents</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-autokey-before-presentation-function</span><span class="ss">'simple-extras-asciify-string</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; check tweaked version of `bibtex-format-entry' above</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-entry-format</span><span class="o">'</span><span class="p">(</span><span class="nv">opts-or-alts-fields</span><span class="nv">last-comma</span><span class="nv">delimiters</span><span class="nv">page-dashes</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-field-indentation</span><span class="mi">8</span><span class="p">)</span><span class="c1">; match ebib value</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'tlon</span><span class="p">)</span><span class="c1">; see explanatory note under ‘reference &amp; citation’</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="s">"\\."</span><span class="o">.</span><span class="s">""</span><span class="p">)</span><span class="nv">bibtex-autokey-name-change-strings</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; add extra entry types</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">entry</span><span class="o">'</span><span class="p">((</span><span class="s">"Video"</span><span class="o">.</span><span class="s">"Video file"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Movie"</span><span class="o">.</span><span class="s">"Film"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"tvepisode"</span><span class="o">.</span><span class="s">"TV episode"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nf">car</span><span class="nv">entry</span><span class="p">)</span><span class="o">,</span><span class="p">(</span><span class="nf">cdr</span><span class="nv">entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"author"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">0</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"title"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"date"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"year"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"url"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">2</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"abstract"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"keywords"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"language"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"version"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"rating"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"letterboxd"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"note"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"organization"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"eprintclass"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"primaryclass"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"eprinttype"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"archiveprefix"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"urldate"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nv">bibtex-biblatex-entry-alist</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">bibtex-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ebib-extras-open-file-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-/"</span><span class="o">.</span><span class="nv">ebib-extras-attach-most-recent-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">bibtex-set-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">bibtex-copy-entry-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">bibtex-yank</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">bibtex-kill-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-x"</span><span class="o">.</span><span class="nv">bibtex-copy-entry-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-c"</span><span class="o">.</span><span class="nv">bibtex-kill-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-a"</span><span class="o">.</span><span class="nv">bibtex-copy-field-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-H-f"</span><span class="o">.</span><span class="nv">bibtex-kill-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">bibtex-previous-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">bibtex-next-entry</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bibtex-extras"><code>bibtex-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/bibtex-extras.el">bibtex-extras</a> collects my extensions for<code>bibtex</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">bibtex-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">bibtex</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-maintain-sorted-entries</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">bibtex-extras-entry-sorter</span><span class="nv">bibtex-extras-lessp</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; Replace 'online' entry type</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-extras-replace-element-by-name</span></span></span><span class="line"><span class="cl"><span class="nv">bibtex-biblatex-entry-alist</span></span></span><span class="line"><span class="cl"><span class="s">"Online"</span><span class="o">'</span><span class="p">(</span><span class="s">"Online"</span><span class="s">"Online Resource"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"author"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">0</span><span class="p">)</span><span class="p">(</span><span class="s">"title"</span><span class="p">)</span><span class="p">(</span><span class="s">"journaltitle"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"date"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">1</span><span class="p">)</span><span class="p">(</span><span class="s">"year"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-1</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"doi"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">2</span><span class="p">)</span><span class="p">(</span><span class="s">"url"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">2</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"subtitle"</span><span class="p">)</span><span class="p">(</span><span class="s">"language"</span><span class="p">)</span><span class="p">(</span><span class="s">"version"</span><span class="p">)</span><span class="p">(</span><span class="s">"note"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"organization"</span><span class="p">)</span><span class="p">(</span><span class="s">"month"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"pubstate"</span><span class="p">)</span><span class="p">(</span><span class="s">"eprintclass"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">4</span><span class="p">)</span><span class="p">(</span><span class="s">"primaryclass"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"eprinttype"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">5</span><span class="p">)</span><span class="p">(</span><span class="s">"archiveprefix"</span><span class="no">nil</span><span class="no">nil</span><span class="mi">-5</span><span class="p">)</span><span class="p">(</span><span class="s">"urldate"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'bibtex-biblatex-entry-alist</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="s">"Performance"</span><span class="s">"A performance entry"</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"author"</span><span class="p">)</span><span class="p">(</span><span class="s">"title"</span><span class="p">)</span><span class="p">(</span><span class="s">"date"</span><span class="p">))</span><span class="c1">; Required fields</span></span></span><span class="line"><span class="cl"><span class="no">nil</span><span class="c1">; Crossref fields</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"venue"</span><span class="p">)</span><span class="p">(</span><span class="s">"location"</span><span class="p">)</span><span class="p">(</span><span class="s">"note"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">bibtex-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">bibtex-extras-set-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">bibtex-extras-url-to-pdf-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-h"</span><span class="o">.</span><span class="nv">bibtex-extras-url-to-html-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-i"</span><span class="o">.</span><span class="nv">bibtex-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">bibtex-extras-move-entry-to-tlon</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bibtex-completion"><code>bibtex-completion</code></h3><p><em><a href="https://github.com/tmalsburg/helm-bibtex">bibtex-completion</a> is a backend for searching and managing bibliographies in Emacs.</em></p><p>The package is required by org-roam-bibtex.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">bibtex-completion</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:version</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">_</span><span class="p">)</span><span class="s">"2.0.0"</span><span class="p">))</span><span class="c1">; github.com/progfolio/elpaca/issues/229</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">bibtex</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-completion-bibliography</span><span class="nv">paths-files-bibliography-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-completion-pdf-open-function</span><span class="ss">'find-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-completion-notes-path</span><span class="nv">paths-dir-bibliographic-notes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-completion-pdf-field</span><span class="s">"file"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-dialect</span><span class="ss">'biblatex</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex-completion-library-path</span><span class="nv">paths-dir-pdf-library</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'tlon</span><span class="p">))</span><span class="c1">; see explanatory note under ‘reference &amp; citation’</span></span></span></code></pre></div><h3 id="bibtex-completion-extras"><code>bibtex-completion-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/bibtex-completion-extras.el">bibtex-completion-extras</a> collects my extensions for<code>bibtex-completion</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">bibtex-completion-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">bibtex-completion</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-roam-bibtex"><code>org-roam-bibtex</code></h3><p><em><a href="https://github.com/org-roam/org-roam-bibtex">org-roam-bibtex</a> integrates org-roam and bibtex.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-roam-bibtex</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">bibtex-completion</span><span class="nv">org-roam</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orb-roam-ref-format</span><span class="ss">'org-cite</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orb-insert-interface</span><span class="ss">'citar-open-notes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orb-note-actions-interface</span><span class="ss">'default</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">orb-attached-file-extensions</span><span class="o">'</span><span class="p">(</span><span class="s">"pdf"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-capture-templates</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="s">"r"</span><span class="s">"bibliography reference"</span><span class="nv">plain</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="o">,</span><span class="nv">paths-file-orb-noter-template</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:if-new</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file</span><span class="o">,</span><span class="nv">paths-file-orb-capture-template</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:unnarrowed</span><span class="no">t</span><span class="nb">:immediate-finish</span><span class="no">t</span><span class="nb">:jump-to-captured</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">keyword</span><span class="o">'</span><span class="p">(</span><span class="s">"year"</span><span class="s">"title"</span><span class="s">"url"</span><span class="s">"keywords"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'orb-preformat-keywords</span><span class="nv">keyword</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-roam-bibtex-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/org-roam/org-roam/issues/2550#issuecomment-3451456331</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">org-roam-capture-new-node-hook</span><span class="no">nil</span><span class="p">))</span></span></span></code></pre></div><h3 id="citar"><code>citar</code></h3><p><em><a href="https://github.com/emacs-citar/citar">citar</a> is a package to quickly find and act on bibliographic references, and edit org, markdown, and latex academic documents.</em></p><p>We defer-load the package to activate the timer that in turn updates the bibliography files when Emacs is idle, like we do with<code>ebib</code> below.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">citar</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"emacs-citar/citar"</span></span></span><span class="line"><span class="cl"><span class="nb">:includes</span><span class="p">(</span><span class="nv">citar-org</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-bibliography</span><span class="nv">paths-files-bibliography-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-notes-paths</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">paths-dir-bibliographic-notes</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-at-point-function</span><span class="ss">'embark-act</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-symbol-separator</span><span class="s">" "</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-format-reference-function</span><span class="ss">'citar-citeproc-format-reference</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-templates</span><span class="o">'</span><span class="p">((</span><span class="nv">main</span><span class="o">.</span><span class="s">"${author editor:30%sn} ${date year issued:4} ${title:60} ${database:10}"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">suffix</span><span class="o">.</span><span class="s">" ${=key= id:25} ${=type=:12}"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">preview</span><span class="o">.</span><span class="s">"${author editor:%etal} (${year issued date}) ${title}, ${journal journaltitle publisher container-title collection-title}.\n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">note</span><span class="o">.</span><span class="s">"Notes on ${author editor:%etal}, ${title}"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-notes-source</span><span class="ss">'orb-citar-source</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'tlon</span><span class="p">)</span><span class="c1">; see explanatory note under ‘reference &amp; citation’</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'citar-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'citar-org-roam</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-register-notes-source</span></span></span><span class="line"><span class="cl"><span class="ss">'orb-citar-source</span><span class="p">(</span><span class="nf">list</span><span class="nb">:name</span><span class="s">"Org-Roam Notes"</span></span></span><span class="line"><span class="cl"><span class="nb">:category</span><span class="ss">'org-roam-node</span></span></span><span class="line"><span class="cl"><span class="nb">:items</span><span class="nf">#'</span><span class="nv">citar-org-roam--get-candidates</span></span></span><span class="line"><span class="cl"><span class="nb">:hasitems</span><span class="nf">#'</span><span class="nv">citar-org-roam-has-notes</span></span></span><span class="line"><span class="cl"><span class="nb">:open</span><span class="nf">#'</span><span class="nv">citar-org-roam-open-note</span></span></span><span class="line"><span class="cl"><span class="nb">:create</span><span class="nf">#'</span><span class="nv">orb-citar-edit-note</span></span></span><span class="line"><span class="cl"><span class="nb">:annotate</span><span class="nf">#'</span><span class="nv">citar-org-roam--annotate</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; allow invocation of `citar-insert-citation' in any buffer. Although it is</span></span></span><span class="line"><span class="cl"><span class="c1">;; not possible to insert citations in some modes, it is still useful to be</span></span></span><span class="line"><span class="cl"><span class="c1">;; able to run this command because of the `embark' integration</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'t</span><span class="nv">citar-major-mode-functions</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">cons</span><span class="o">'</span><span class="p">(</span><span class="nv">insert-citation</span><span class="o">.</span><span class="nv">citar-org-insert-citation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'t</span><span class="nv">citar-major-mode-functions</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-/"</span><span class="o">.</span><span class="nv">citar-insert-citation</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">citar-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">embark-copy-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"u"</span><span class="o">.</span><span class="nv">citar-open-links</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">ebib-extras-search-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">citar-extras-move-entry-to-tlon</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">citar-extras-goto-bibtex-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">citar-extras-open-in-ebib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">citar-citation-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">embark-copy-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"u"</span><span class="o">.</span><span class="nv">citar-open-links</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">ebib-extras-search-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">citar-extras-move-entry-to-tlon</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">citar-extras-goto-bibtex-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">citar-extras-open-in-ebib</span><span class="p">)))</span></span></span></code></pre></div><h3 id="citar-extras"><code>citar-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/citar-extras.el">citar-extras</a> collects my extensions for<code>citar</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">citar-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">citar</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; https://github.com/emacs-citar/citar/wiki/Indicators</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq</span><span class="nv">citar-indicators</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="nv">citar-extras-indicator-links-icons</span></span></span><span class="line"><span class="cl"><span class="nv">citar-extras-indicator-files-icons</span></span></span><span class="line"><span class="cl"><span class="nv">citar-extras-indicator-notes-icons</span></span></span><span class="line"><span class="cl"><span class="nv">citar-extras-indicator-cited-icons</span><span class="p">)))</span></span></span></code></pre></div><h3 id="citar-citeproc"><code>citar-citeproc</code></h3><p><em><a href="https://github.com/emacs-citar/citar/blob/main/citar-citeproc.el">citar-citeproc</a> provides Citeproc reference support for citar.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">citar-citeproc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">citar</span><span class="nv">citeproc</span><span class="nv">citar-extras</span><span class="nv">tlon</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-citeproc-csl-styles-dir</span><span class="nv">paths-dir-tlon-csl-styles</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-citeproc-csl-locales-dir</span><span class="nv">paths-dir-tlon-csl-locales</span><span class="p">))</span></span></span></code></pre></div><h3 id="citar-embark"><code>citar-embark</code></h3><p><em><a href="https://github.com/emacs-citar/citar/tree/9d7088c1fe82e9cfa508ead7ef7738c732556644#embark">citar-embark</a> adds contextual access actions in the minibuffer and at-point via the citar-embark-mode minor mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">citar-embark</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">citar</span><span class="nv">embark</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">citar-embark-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="citar-org-roam"><code>citar-org-roam</code></h3><p><em><a href="https://github.com/emacs-citar/citar-org-roam">citar-org-roam</a> provides integration between citar and org-roam.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">citar-org-roam</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"emacs-citar/citar-org-roam"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">citar</span><span class="nv">org-roam</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-ref"><code>org-ref</code></h3><p><em><a href="https://github.com/jkitchin/org-ref">org-ref</a> supports citations, cross-references, bibliographies in org-mode and useful bibtex tools.</em></p><p>I use this package only to run the cleanup function<code>org-ref-clean-bibtex-entry</code> after adding new entries to my bibliography and to occasionally call a few miscellaneous commands. I do not use any of its citation-related functionality, since I use<code>org-cite</code> for that.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-ref</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">zotra</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-ref-bibtex-pdf-download-dir</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-ref-insert-cite-function</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-cite-insert</span><span class="no">nil</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">fun</span><span class="o">'</span><span class="p">(</span><span class="nv">org-ref-replace-nonascii</span></span></span><span class="line"><span class="cl"><span class="nv">orcb-check-journal</span></span></span><span class="line"><span class="cl"><span class="nv">orcb-download-pdf</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">delete</span><span class="nv">fun</span><span class="nv">org-ref-clean-bibtex-entry-hook</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-ref-extras"><code>org-ref-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-ref-extras.el">org-ref-extras</a> collects my extensions for<code>org-ref</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-ref-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-ref</span><span class="p">)</span></span></span></code></pre></div><h3 id="ebib"><code>ebib</code></h3><p><em><a href="https://github.com/joostkremers/ebib">ebib</a> (<a href="http://joostkremers.github.io/ebib/">homepage</a>) is a BibTeX database manager for Emacs.</em></p><p>We defer-load the package to activate the timer that in turn updates the bibliography files when Emacs is idle, like we do with<code>citar</code> above.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ebib</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-preload-bib-files</span><span class="nv">paths-files-bibliography-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-notes-directory</span><span class="nv">paths-dir-bibliographic-notes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-notes-use-org-capture</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-notes-display-max-lines</span><span class="mi">9999</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-filename-separator</span><span class="s">";"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-file-associations</span><span class="no">nil</span><span class="p">)</span><span class="c1">; do not open any file types externally</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-layout</span><span class="ss">'index-only</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-bibtex-dialect</span><span class="ss">'biblatex</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-use-timestamp</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-timestamp-format</span><span class="s">"%Y-%m-%d %T (%Z)"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-default-entry-type</span><span class="s">"online"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-uniquify-keys</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-index-columns</span><span class="o">'</span><span class="p">((</span><span class="s">"Entry Key"</span><span class="mi">30</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Author/Editor"</span><span class="mi">25</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Year"</span><span class="mi">4</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Title"</span><span class="mi">50</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-extra-fields</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">biblatex</span><span class="s">"abstract"</span><span class="s">"keywords"</span><span class="s">"origdate"</span><span class="s">"langid"</span><span class="s">"translation"</span><span class="s">"narrator"</span><span class="s">"file"</span><span class="s">"timestamp"</span><span class="s">"wordcount"</span><span class="s">"rating"</span><span class="s">"crossref"</span><span class="s">"=key="</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bibtex</span><span class="s">"crossref"</span><span class="s">"annote"</span><span class="s">"abstract"</span><span class="s">"keywords"</span><span class="s">"file"</span><span class="s">"timestamp"</span><span class="s">"url"</span><span class="s">"doi"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'tlon</span><span class="p">)</span><span class="c1">; see explanatory note under ‘reference &amp; citation’</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-entry-mode-hook</span><span class="o">.</span><span class="nv">visual-line-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ebib-multiline-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">ebib-quit-multiline-buffer-and-save</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">ebib-edit-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A"</span><span class="o">.</span><span class="nv">ebib-add-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">ebib-delete-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-extras-ebib-view-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">ebib-prev-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">ebib-next-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s"</span><span class="o">.</span><span class="nv">ebib-save-current-database</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"K"</span><span class="o">.</span><span class="nv">ebib-copy-key-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Q"</span><span class="o">.</span><span class="nv">ebib-quit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"W"</span><span class="o">.</span><span class="nv">zotra-download-attachment</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"TAB"</span><span class="o">.</span><span class="nv">ebib-goto-next-set</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;backtab&gt;"</span><span class="o">.</span><span class="nv">ebib-goto-prev-set</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s"</span><span class="o">.</span><span class="nv">ebib-save-current-database</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-S"</span><span class="o">.</span><span class="nv">ebib-save-all-databases</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"!"</span><span class="o">.</span><span class="nv">ebib-generate-autokey</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A"</span><span class="o">.</span><span class="nv">ebib-add-field</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">ebib-copy-current-field-contents</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">ebib-delete-current-field-contents</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">ebib-edit-keyname</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s"</span><span class="o">.</span><span class="nv">ebib-save-current-database</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"K"</span><span class="o">.</span><span class="nv">ebib-copy-key-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Q"</span><span class="o">.</span><span class="nv">ebib-quit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"W"</span><span class="o">.</span><span class="nv">zotra-download-attachment</span><span class="p">)))</span></span></span></code></pre></div><p>The macro below generates the commands correctly. But attempting to define key bindings results in duplicate commands. I&rsquo;m not sure what&rsquo;s on; it seems to be related to<code>use-package</code>.</p><h3 id="ebib-utils"><code>ebib-utils</code></h3><p><em>ebib-utils provides internal utility functions for<a href="https://github.com/joostkremers/ebib">ebib</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ebib-utils</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ebib</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-hidden-fields</span><span class="c1">; unhide some fields</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">cl-remove-if</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">el</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">member</span><span class="nv">el</span><span class="o">'</span><span class="p">(</span><span class="s">"edition"</span><span class="s">"isbn"</span><span class="s">"timestamp"</span><span class="s">"titleaddon"</span><span class="s">"translator"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nv">ebib-hidden-fields</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'ebib-hidden-fields</span><span class="s">"year"</span><span class="p">))</span><span class="c1">; hide others</span></span></span></code></pre></div><h3 id="ebib-extras"><code>ebib-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/ebib-extras.el">ebib-extras</a> collects my extensions for<code>ebib</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">ebib-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'ebib-init</span><span class="nb">:after</span><span class="nf">#'</span><span class="nv">ebib-extras-auto-reload-databases</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-extras-attach-existing-file-action</span><span class="ss">'overwrite</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ebib-add-entry</span><span class="o">.</span><span class="nv">ebib-extras-create-list-of-existing-authors</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-i"</span><span class="o">.</span><span class="nv">ebib-extras-open-or-switch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">ebib-extras-prev-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">ebib-extras-next-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">ebib-extras-duplicate-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="o">.</span><span class="nv">ebib-extras-citar-open-notes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-&lt;tab&gt;"</span><span class="o">.</span><span class="nv">ebib-extras-end-of-index-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">ebib-extras-sort</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ebib-extras-open-file-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">ebib-extras-prev-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">ebib-extras-next-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">ebib-extras-duplicate-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="o">.</span><span class="nv">ebib-extras-citar-open-notes</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"SPC"</span><span class="o">.</span><span class="nv">ebib-extras-open-file-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"/"</span><span class="o">.</span><span class="nv">ebib-extras-attach-most-recent-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"?"</span><span class="o">.</span><span class="nv">ebib-extras-attach-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">ebib-extras-process-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">ebib-extras-search-amazon</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">ebib-extras-get-or-open-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g"</span><span class="o">.</span><span class="nv">ebib-extras-search-library-genesis</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"G"</span><span class="o">.</span><span class="nv">ebib-extras-search-goodreads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">ebib-extras-open-html-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H"</span><span class="o">.</span><span class="nv">ebib-extras-open-html-file-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"I"</span><span class="o">.</span><span class="nv">ebib-extras-set-id</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">ebib-extras-search-connected-papers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="o">.</span><span class="nv">ebib-extras-open-pdf-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"P"</span><span class="o">.</span><span class="nv">ebib-extras-open-pdf-file-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"R"</span><span class="o">.</span><span class="nv">ebib-extras-set-rating</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">ebib-extras-search-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"T"</span><span class="o">.</span><span class="nv">ebib-extras-no-translation-found</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"u"</span><span class="o">.</span><span class="nv">ebib-extras-browse-url-or-doi</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"V"</span><span class="o">.</span><span class="nv">ebib-extras-search-internet-archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">ebib-extras-search-university-of-toronto</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"y"</span><span class="o">.</span><span class="nv">ebib-extras-search-hathitrust</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">ebib-extras-search-google-scholar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">ebib-extras-url-to-pdf-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">ebib-extras-fetch-keywords</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-h"</span><span class="o">.</span><span class="nv">ebib-extras-url-to-html-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">ebib-extras-rename-files</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bib"><code>bib</code></h3><p><em><a href="https://github.com/benthamite/bib">bib</a> fetches bibliographic metadata from various APIs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">bib</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/bib"</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span><span class="c1">; clone entire repo, not just last commit</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ebib</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bib-isbndb-key</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"key"</span><span class="p">(</span><span class="nf">concat</span><span class="s">"tlon/babel/isbndb.com/"</span><span class="nv">tlon-email-shared</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bib-omdb-key</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"chrome/omdbapi.com"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bib-tmdb-key</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"key"</span><span class="s">"chrome/themoviedb.org/stafforini"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">bib-zotra-add-entry-from-title</span><span class="p">)))</span></span></span></code></pre></div><h3 id="zotra"><code>zotra</code></h3><p><em><a href="https://github.com/mpedramfar/zotra">zotra</a> provides functions to get bibliographic information from a URL via<a href="https://www.zotero.org/support/translators">Zotero translators</a>, but without relying on the Zotero client.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">zotra</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"mpedramfar/zotra"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-use-curl</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-url-retrieve-timeout</span><span class="mi">15</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-default-entry-format</span><span class="s">"biblatex"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-download-attachment-default-directory</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-backend</span><span class="ss">'zotra-server</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-local-server-directory</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-external-repos</span><span class="s">"zotra-server/"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="zotra-extras"><code>zotra-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/zotra-extras.el">zotra-extras</a> collects my extensions for<code>zotra</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">zotra-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">ebib</span><span class="nv">eww</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-extras-use-mullvad-p</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">zotra-after-get-bibtex-entry-hook</span><span class="o">.</span><span class="nv">zotra-extras-after-add-process-bibtex</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">ebib-index-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">zotra-extras-add-entry</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">zotra-extras-add-entry</span><span class="p">)))</span></span></span></code></pre></div><h3 id="annas-archive"><code>annas-archive</code></h3><p><em><a href="https://github.com/benthamite/annas-archive">annas-archive</a> provides rudimentary integration for Anna’s Archive, the largest existing search engine for shadow libraries.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">annas-archive</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/annas-archive"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'ebib</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="nv">ebib-entry-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">annas-archive-download</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'eww</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">annas-archive-download-file</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">annas-archive-secret-key</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"tlon/core/annas-archive"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">annas-archive-included-file-types</span><span class="o">'</span><span class="p">(</span><span class="s">"pdf"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">annas-archive-title-column-width</span><span class="mi">130</span><span class="p">))</span></span></span></code></pre></div><h2 id="email">email</h2><h3 id="simple"><code>simple</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/simple.el">simple</a> configures the mail user agent.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">simple</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mail-user-agent</span><span class="ss">'mu4e-user-agent</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">read-mail-command</span><span class="ss">'mu4e</span><span class="p">))</span></span></span></code></pre></div><h3 id="sendmail"><code>sendmail</code></h3><p><em><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Mail-Sending.html">sendmail</a> is a mode that provides mail-sending facilities from within Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">sendmail</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">:any</span><span class="nv">mu4e</span><span class="nv">org-msg</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">send-mail-function</span><span class="ss">'smtpmail-send-it</span><span class="p">))</span></span></span></code></pre></div><h3 id="smtpmail"><code>smtpmail</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/mail/smtpmail.el">smtpmail</a> provides SMTP mail sending support.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">smtpmail</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">:any</span><span class="nv">mu4e</span><span class="nv">org-msg</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-smtp-user</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_GMAIL"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-local-domain</span><span class="s">"gmail.com"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-default-smtp-server</span><span class="s">"smtp.gmail.com"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-smtp-server</span><span class="s">"smtp.gmail.com"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-smtp-service</span><span class="mi">465</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">smtpmail-stream-type</span><span class="ss">'ssl</span><span class="p">))</span></span></span></code></pre></div><h3 id="message"><code>message</code></h3><p><em><a href="https://www.gnu.org/software/emacs/manual/html_mono/message.html">message</a> is a message composition mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nf">message</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">:any</span><span class="nv">mu4e</span><span class="nv">org-msg</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-kill-buffer-on-exit</span><span class="no">t</span><span class="p">)</span><span class="c1">; make `message-send-and-exit' kill buffer, not bury it</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-send-mail-function</span><span class="ss">'smtpmail-send-it</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-elide-ellipsis</span><span class="s">"\n&gt; [... %l lines omitted]\n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-citation-line-function</span><span class="ss">'message-insert-formatted-citation-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-citation-line-format</span><span class="p">(</span><span class="nf">concat</span><span class="s">"&gt; From: %f\n"</span></span></span><span class="line"><span class="cl"><span class="s">"&gt; Date: %a, %e %b %Y %T %z\n"</span></span></span><span class="line"><span class="cl"><span class="s">"&gt;"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nv">message-ignored-cited-headers</span><span class="s">""</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">message-header-name</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-header-subject</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-header-to</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-header-other</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-header-cc</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-send-hook</span><span class="o">.</span><span class="nv">buffer-disable-undo</span><span class="p">)</span><span class="c1">; required to avoid an error</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">message-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">ml-attach-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">message-goto-body</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">message-send-and-exit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">message-goto-from</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">message-goto-subject</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">message-goto-to</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-b"</span><span class="o">.</span><span class="nv">message-goto-bcc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-c"</span><span class="o">.</span><span class="nv">message-goto-cc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-s"</span><span class="o">.</span><span class="nv">message-send</span><span class="p">)))</span></span></span></code></pre></div><h3 id="mml"><code>mml</code></h3><p><em><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs-mime/Composing.html">mml</a> is a library that parses a MML (MIME Meta Language) and generates MIME messages.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">mml</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="mu4e"><code>mu4e</code></h3><p><em><a href="https://github.com/djcb/mu">mu4e</a> is an an Emacs-based e-mail client.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">mu4e</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"mu4e/*.el"</span><span class="s">"build/mu4e/mu4e-meta.el"</span><span class="s">"build/mu4e/mu4e-config.el"</span><span class="s">"build/mu4e/mu4e.info"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"djcb/mu"</span></span></span><span class="line"><span class="cl"><span class="nb">:main</span><span class="s">"mu4e/mu4e.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:pre-build</span><span class="p">((</span><span class="s">"./autogen.sh"</span><span class="p">)</span><span class="p">(</span><span class="s">"ninja"</span><span class="s">"-C"</span><span class="s">"build"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-build-docs</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:ref</span><span class="s">"1a501281"</span><span class="c1">; v.1.12.13</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; uncomment thw two user options below when debugging</span></span></span><span class="line"><span class="cl"><span class="c1">;; (mu4e-debug t)</span></span></span><span class="line"><span class="cl"><span class="c1">;; (mu4e-index-update-error-warning )</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-split-view</span><span class="ss">'single-window</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-headers-show-target</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-get-mail-command</span><span class="s">"sh $HOME/bin/mbsync-parallel"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-update-interval</span><span class="p">(</span><span class="nf">*</span><span class="mi">5</span><span class="mi">60</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-drafts-folder</span><span class="s">"/Drafts"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-sent-folder</span><span class="s">"/Sent"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-refile-folder</span><span class="s">"/Refiled"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-trash-folder</span><span class="s">"/Trash"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-attachment-dir</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-change-filenames-when-moving</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; see also `mu4e-extras-set-shortcuts'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-maildir-shortcuts</span></span></span><span class="line"><span class="cl"><span class="o">`</span><span class="p">((</span><span class="nb">:maildir</span><span class="o">,</span><span class="nv">mu4e-drafts-folder</span><span class="nb">:key</span><span class="sc">?d</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:maildir</span><span class="o">,</span><span class="nv">mu4e-sent-folder</span><span class="nb">:key</span><span class="sc">?t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:maildir</span><span class="o">,</span><span class="nv">mu4e-refile-folder</span><span class="nb">:key</span><span class="sc">?r</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:maildir</span><span class="o">,</span><span class="nv">mu4e-trash-folder</span><span class="nb">:key</span><span class="sc">?x</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-compose-format-flowed</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-confirm-quit</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-headers-date-format</span><span class="s">"%Y-%m-%d %H:%M"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-search-include-related</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-search-results-limit</span><span class="mi">1000</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-headers-visible-lines</span><span class="mi">25</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-hide-index-messages</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-sent-messages-behavior</span><span class="ss">'delete</span><span class="p">)</span><span class="c1">; Gmail already keeps a copy</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; performance improvements (but with downsides)</span></span></span><span class="line"><span class="cl"><span class="c1">;; groups.google.com/g/mu-discuss/c/hRRNhM5mwr0</span></span></span><span class="line"><span class="cl"><span class="c1">;; djcbsoftware.nl/code/mu/mu4e/Retrieval-and-indexing.html</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-index-cleanup</span><span class="no">t</span><span class="p">)</span><span class="c1">; nil improves performance but causes stale index errors</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-index-lazy-check</span><span class="no">t</span><span class="p">)</span><span class="c1">; t improves performance</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-compose-context-policy</span><span class="ss">'ask</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-context-policy</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-modeline-support</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-headers-fields</span><span class="o">'</span><span class="p">((</span><span class="nb">:human-date</span><span class="o">.</span><span class="mi">16</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:from</span><span class="o">.</span><span class="mi">30</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:subject</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'mu4e-contrib</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setf</span><span class="p">(</span><span class="nv">alist-get</span><span class="ss">'trash</span><span class="nv">mu4e-marks</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nb">:char</span><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="s">"▼"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:prompt</span><span class="s">"dtrash"</span></span></span><span class="line"><span class="cl"><span class="nb">:dyn-target</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">target</span><span class="nv">msg</span><span class="p">)</span><span class="p">(</span><span class="nv">mu4e-get-trash-folder</span><span class="nv">msg</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="c1">;; Here's the main difference to the regular trash mark, no +T</span></span></span><span class="line"><span class="cl"><span class="c1">;; before -N so the message is not marked as IMAP-deleted:</span></span></span><span class="line"><span class="cl"><span class="nb">:action</span><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">docid</span><span class="nv">msg</span><span class="nv">target</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e--server-move</span><span class="nv">docid</span><span class="p">(</span><span class="nv">mu4e--mark-check-target</span><span class="nv">target</span><span class="p">)</span><span class="s">"+S-u-N"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'mu4e--search-hist</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="c1">;; do not override native `mu4e' completion with `org-contacts' completion</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'mu4e-compose-mode-hook</span><span class="ss">'org-contacts-setup-completion-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">mu4e-compose-separator-face</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-fixed-pitch-size</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-m"</span><span class="o">.</span><span class="nv">mu4e</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-main-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">mu4e-compose-new</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">mu4e-display-manual</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">mu4e-search-maildir</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"u"</span><span class="o">.</span><span class="nv">mu4e-update-mail-and-index</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-headers-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">mu4e-copy-message-path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;"</span><span class="o">.</span><span class="nv">mu4e-headers-split-view-shrink</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&gt;"</span><span class="o">.</span><span class="nv">mu4e-headers-split-view-grow</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">mu4e-compose-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">mu4e-select-other-view</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">mu4e-compose-new</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"*"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-all-unread-read</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-for-delete</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-extras-headers-view-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">mu4e-headers-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">mu4e-headers-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-for-something</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"R"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-for-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"V"</span><span class="o">.</span><span class="nv">mu4e-headers-mark-for-move</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">shr-heading-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">shr-heading-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">mu4e-copy-message-path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;"</span><span class="o">.</span><span class="nv">mu4e-headers-split-view-shrink</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&gt;"</span><span class="o">.</span><span class="nv">mu4e-headers-split-view-grow</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">mu4e-compose-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">mu4e-select-other-view</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">mu4e-compose-new</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">mu4e-view-headers-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">mu4e-view-headers-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">mu4e-view-mark-for-delete</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-extras-mu4e</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"L"</span><span class="o">.</span><span class="nv">mu4e-view-save-attachments</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">mu4e-view-mark-for-something</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-u"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">org-extras-eww-copy-for-org-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-compose-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-minibuffer-search-query-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-k"</span><span class="o">.</span><span class="nv">previous-history-element</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-l"</span><span class="o">.</span><span class="nv">next-history-element</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-search-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="mu4e-extras"><code>mu4e-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/mu4e-extras.el">mu4e-extras</a> collects my extensions for<code>mu4e</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">mu4e-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">mu4e</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-inbox-folder</span><span class="s">"/Inbox"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-daily-folder</span><span class="s">"/Daily"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-epoch-inbox-folder</span><span class="s">"/epoch/Inbox"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-epoch-sent-folder</span><span class="s">"/epoch/Sent"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-epoch-drafts-folder</span><span class="s">"/epoch/Drafts"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-epoch-refiled-folder</span><span class="s">"/epoch/Refiled"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-epoch-trash-folder</span><span class="s">"/epoch/Trash"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-wide-reply</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-set-shortcuts</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-set-bookmarks</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-set-contexts</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-extras-set-account-folders</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-mark-execute-pre-hook</span><span class="o">.</span><span class="nv">mu4e-extras-gmail-fix-flags</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-view-mode-hook</span><span class="o">.</span><span class="nv">mu4e-extras-set-face-locally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-update-pre-hook</span><span class="o">.</span><span class="nv">mu4e-extras-set-index-params</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mu4e-index-updated-hook</span><span class="o">.</span><span class="nv">mu4e-extras-reapply-read-status</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">message-sent-hook</span><span class="o">.</span><span class="nv">mu4e-extras-add-sent-to-mark-as-read-queue</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">mu4e-main-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g"</span><span class="o">.</span><span class="nv">mu4e-extras-compose-new-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">mu4e-extras-reindex-db</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-headers-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"$"</span><span class="o">.</span><span class="nv">mu4e-extras-copy-sum</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">mu4e-extras-headers-trash</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">mu4e-extras-headers-mark-read-and-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">mu4e-extras-mark-execute-all-no-confirm</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">mu4e-extras-headers-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">mu4e-extras-view-org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">mu4e-extras-compose-reply</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="nv">mu4e-extras-headers-move</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">mu4e-extras-open-gmail</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"$"</span><span class="o">.</span><span class="nv">mu4e-extras-copy-sum</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">mu4e-copy-message-path</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">mu4e-extras-view-trash</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">mu4e-extras-view-refile</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">mu4e-extras-view-org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">mu4e-extras-compose-reply</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="nv">mu4e-extras-view-move</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">mu4e-extras-view-in-gmail</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-msg"><code>org-msg</code></h3><p><em><a href="https://github.com/jeremy-compostella/org-msg">org-msg</a> is a global minor mode mixing up Org mode and Message mode to compose and reply to emails in a HTML-friendly style.</em></p><p>I use this package to compose messages and to reply to messages composed in HTML For plain-text messages, I use<code>message</code> (of which see above).</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-msg</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">mu4e-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-options</span><span class="s">"html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t tex:imagemagick"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-startup</span><span class="s">"hidestars indent inlineimages"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-recipient-names</span><span class="o">`</span><span class="p">((</span><span class="o">,</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_GMAIL"</span><span class="p">)</span><span class="o">.</span><span class="s">"Pablo"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-greeting-name-limit</span><span class="mi">3</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-default-alternatives</span><span class="o">'</span><span class="p">((</span><span class="nv">new</span><span class="o">.</span><span class="p">(</span><span class="nv">text</span><span class="nv">html</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">reply-to-html</span><span class="o">.</span><span class="p">(</span><span class="nv">text</span><span class="nv">html</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-convert-citation</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-enforce-css</span><span class="o">'</span><span class="p">((</span><span class="nv">del</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Georgia\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"grey"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">border-left</span><span class="o">.</span><span class="s">"none"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">text-decoration</span><span class="o">.</span><span class="s">"line-through"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"1.3"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">a</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">color</span><span class="o">.</span><span class="s">"#4078F2"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">a</span><span class="nv">reply-header</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">color</span><span class="o">.</span><span class="s">"black"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">text-decoration</span><span class="o">.</span><span class="s">"none"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">div</span><span class="nv">reply-header</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">padding</span><span class="o">.</span><span class="s">"3.0pt 0in 0in 0in"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">border-top</span><span class="o">.</span><span class="s">"solid #d5d5d5 1.0pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"20px"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">span</span><span class="nv">underline</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">text-decoration</span><span class="o">.</span><span class="s">"underline"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">li</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Georgia\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"1.3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"2px"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">nil</span><span class="nv">org-ul</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">list-style-type</span><span class="o">.</span><span class="s">"square"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">nil</span><span class="nv">org-ol</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Georgia\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"1.3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-left</span><span class="o">.</span><span class="s">"30px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">padding-top</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">padding-left</span><span class="o">.</span><span class="s">"5px"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="no">nil</span><span class="nv">signature</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Arial\", \"Helvetica\", sans-serif"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"20px"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">blockquote</span><span class="nv">quote0</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">padding-left</span><span class="o">.</span><span class="s">"5px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"0.9"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-left</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">background</span><span class="o">.</span><span class="s">"#f9f9f9"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">border-left</span><span class="o">.</span><span class="s">"3px solid #d5d5d5"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">blockquote</span><span class="nv">quote1</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">padding-left</span><span class="o">.</span><span class="s">"5px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"0.9"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-left</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">background</span><span class="o">.</span><span class="s">"#f9f9f9"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"#324e72"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">border-left</span><span class="o">.</span><span class="s">"3px solid #3c5d88"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">pre</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"1.3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">color</span><span class="o">.</span><span class="s">"#000000"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">background-color</span><span class="o">.</span><span class="s">"#f0f0f0"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"9pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"monospace"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">p</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">text-decoration</span><span class="o">.</span><span class="s">"none"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-bottom</span><span class="o">.</span><span class="s">"0px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">margin-top</span><span class="o">.</span><span class="s">"10px"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"1.3"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Georgia\""</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">div</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="nv">font-family</span><span class="o">.</span><span class="s">"\"Georgia\""</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">font-size</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">line-height</span><span class="o">.</span><span class="s">"11pt"</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'pass</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">auto-fill-mode</span><span class="mi">-1</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-msg-edit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-b"</span><span class="o">.</span><span class="nv">message-goto-bcc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-c"</span><span class="o">.</span><span class="nv">message-goto-cc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-s"</span><span class="o">.</span><span class="nv">message-send</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">org-msg-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-b"</span><span class="o">.</span><span class="nv">org-msg-extras-begin-compose</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">message-send-and-exit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">message-goto-from</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">org-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">message-goto-subject</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">message-goto-to</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-A-l"</span><span class="o">.</span><span class="nv">org-extras-url-dwim</span><span class="p">)))</span></span></span></code></pre></div><h3 id="org-msg-extras"><code>org-msg-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-msg-extras.el">org-msg-extras</a> collects my extensions for<code>org-msg</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-msg-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-msg</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">org-msg-edit-mode-hook</span><span class="o">.</span><span class="nv">org-msg-extras-fold-signature-blocks</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">org-msg-edit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">org-msg-extras-open-in-grammarly</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">org-msg-extras-kill-message</span><span class="p">)))</span></span></span></code></pre></div><h2 id="messaging">messaging</h2><h3 id="telega"><code>telega</code></h3><p><em><a href="https://github.com/zevlg/telega.el">telega</a> is an unofficial Emacs Telegram client.</em></p><p>To upgrade TDLib with homebrew, run<code>brew upgrade tdlib --fetch-HEAD</code> in a terminal, then<code>M-x telega-server-build</code>.</p><p>If you need to install an earlier version than<code>HEAD</code>, you’ll need to build from source:</p><ol><li>Clone the repo:<code>git clone https://github.com/tdlib/td.git</code></li><li>Navigate to the<code>td</code> directory:<code>cd td</code></li><li>Checkout the desired version:<code>git checkout &lt;version_tag&gt;</code></li><li>Create a build directory:<code>mkdir build &amp;&amp; cd build &amp;&amp; cmake ../</code></li><li>Build the library:<code>make -jN</code>, replacing<code>N</code> by the number of cores to be used for the compilation.</li><li>Install the library:<code>make install</code></li></ol><p>Then change the value of<code>telega-server-libs-prefix</code> from<code>/opt/homebrew</code> to<code>/usr/local/lib</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">telega</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">telega-server-libs-prefix</span><span class="s">"/opt/homebrew"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-chat-input-markups</span><span class="o">'</span><span class="p">(</span><span class="s">"org"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-use-images</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-emoji-font-family</span><span class="ss">'noto-emoji</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-emoji-use-images</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-filters-custom</span><span class="o">'</span><span class="p">((</span><span class="s">"Main"</span><span class="o">.</span><span class="nv">main</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Important"</span><span class="nb">or</span><span class="nv">mention</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">and</span><span class="nv">unread</span><span class="nv">unmuted</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Archive"</span><span class="o">.</span><span class="nv">archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Online"</span><span class="nb">and</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">not</span><span class="nv">saved-messages</span><span class="p">)</span><span class="p">(</span><span class="nv">user</span><span class="nv">is-online</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Groups"</span><span class="nv">type</span><span class="nv">basicgroup</span><span class="nv">supergroup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Channels"</span><span class="nv">type</span><span class="nv">channel</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-completing-read-function</span><span class="ss">'completing-read</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-webpage-history-max</span><span class="nv">most-positive-fixnum</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-root-fill-column</span><span class="mi">110</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-chat-fill-column</span><span class="mi">90</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-webpage-fill-column</span><span class="mi">110</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-photo-size-limits</span><span class="o">`</span><span class="p">(</span><span class="mi">8</span><span class="mi">3</span><span class="o">,</span><span class="p">(</span><span class="nf">*</span><span class="mi">55</span><span class="mf">1.5</span><span class="p">)</span><span class="o">,</span><span class="p">(</span><span class="nf">*</span><span class="mi">12</span><span class="mf">1.5</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-webpage-photo-size-limits</span><span class="o">`</span><span class="p">(</span><span class="mi">55</span><span class="mi">10</span><span class="o">,</span><span class="p">(</span><span class="nf">*</span><span class="mi">110</span><span class="mf">1.5</span><span class="p">)</span><span class="o">,</span><span class="p">(</span><span class="nf">*</span><span class="mi">20</span><span class="mf">1.5</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-mode-line-format</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-vvnote-play-speeds</span><span class="o">'</span><span class="p">(</span><span class="mi">1</span><span class="mf">1.5</span><span class="mi">2</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'telega-search-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-mode-line-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">telega-entity-type-code</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">face-attribute</span><span class="ss">'default</span><span class="nb">:height</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-chat-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nb">setq</span><span class="nv">default-directory</span><span class="nv">paths-dir-downloads</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">telega-chat-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-p"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S-&lt;return&gt;"</span><span class="o">.</span><span class="nv">newline</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-s-r"</span><span class="o">.</span><span class="nv">telega-chatbuf-next-unread-reaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">telega-msg-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">telega-msg-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">telega-extras-smart-enter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; if point is on a URL, `telega-msg-button-map' ceases to be</span></span></span><span class="line"><span class="cl"><span class="c1">;; active and `&lt;return&gt;' triggers `newline' rather than</span></span></span><span class="line"><span class="cl"><span class="c1">;; `push-button'. this seems to be a bug. as a workaround, we also</span></span></span><span class="line"><span class="cl"><span class="c1">;; bind `push-button' to `s-&lt;return&gt;' in `telega-chat-mode-map'.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-,"</span><span class="o">.</span><span class="nv">telega-chatbuf-goto-pinned-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">telega-chatbuf-attach</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">telega-mnz-chatbuf-attach-code</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">telega-chatbuf-goto-date</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">telega-chatbuf-filter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-k"</span><span class="o">.</span><span class="nv">org-insert-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-m"</span><span class="o">.</span><span class="nv">telega-chatbuf-attach-media</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-o"</span><span class="o">.</span><span class="nv">telega-chatbuf-filter-by-topic</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-r"</span><span class="o">.</span><span class="nv">telega-msg-add-reaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-s"</span><span class="o">.</span><span class="nv">telega-chatbuf-filter-search</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-t"</span><span class="o">.</span><span class="nv">telega-sticker-choose-favorite-or-recent</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-v"</span><span class="o">.</span><span class="nv">org-extras-paste-with-conversion</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-v"</span><span class="o">.</span><span class="nv">telega-chatbuf-attach-clipboard</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">telega-mnz-chatbuf-attach-code</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-e"</span><span class="o">.</span><span class="nv">telega-chatbuf-edit-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-v"</span><span class="o">.</span><span class="nv">telega-chatbuf-attach-clipboard</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">ace-link-org</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-msg-button-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">telega-button-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">telega-button-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">telega-extras-smart-enter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">telega-chatbuf-goto-pinned-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C"</span><span class="o">.</span><span class="nv">telega-msg-copy-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">telega-msg-delete-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"F"</span><span class="o">.</span><span class="nv">telega-msg-forward-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-org</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">telega-chatbuf-filter-search</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">telega-browse-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"W"</span><span class="o">.</span><span class="nv">telega-chatbuf-filter-cancel</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-chat-button-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-root-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">telega-button-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;up&gt;"</span><span class="o">.</span><span class="nv">telega-button-backward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">telega-button-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;down&gt;"</span><span class="o">.</span><span class="nv">telega-button-forward</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"SPC"</span><span class="o">.</span><span class="nv">telega-root-next-unread</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">telega-chat-with</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">telega-chat-toggle-archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-extras-telega-view-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">telega-chat-toggle-muted</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-webpage-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">telega-webpage-browse-url</span><span class="p">)))</span></span></span></code></pre></div><h3 id="telega-mnz"><code>telega-mnz</code></h3><p><em><a href="https://github.com/zevlg/telega.el/blob/master/contrib/telega-mnz.el">telega-mnz</a> displays syntax highlighting in Telega code blocks.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">telega-mnz</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">telega</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-mnz-use-language-detection</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-load-hook</span><span class="o">.</span><span class="nv">global-telega-mnz-mode</span><span class="p">))</span></span></span></code></pre></div><h3 id="telega-dired-dwim"><code>telega-dired-dwim</code></h3><p><em><a href="https://github.com/zevlg/telega.el/blob/master/contrib/telega-dired-dwim.el">telega-dired-dwim</a> enables Dired file attachments in Telega chat buffers.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">telega-dired-dwim</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">telega</span><span class="nv">dired</span><span class="p">)</span></span></span></code></pre></div><h3 id="telega-extras"><code>telega-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/telega-extras.el">telega-extras</a> collects my extensions for<code>telega</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">telega-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-load-hook</span><span class="o">.</span><span class="nv">telega-extras-reset-tab-bar</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">telega-chat-post-message-hook</span><span class="o">.</span><span class="nv">telega-extras-transcribe-audio</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-l"</span><span class="o">.</span><span class="nv">telega-extras-switch-to</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-msg-button-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">telega-extras-chat-org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">telega-extras-docs-change-open</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="nv">telega-extras-transcribe-audio</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">telega-extras-download-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"L"</span><span class="o">.</span><span class="nv">telega-extras-chat-org-capture-leo</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-chat-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-t"</span><span class="o">.</span><span class="nv">telega-extras-chatbuf-attach-most-recent-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">dired-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-s-a"</span><span class="o">.</span><span class="nv">telega-extras-dired-attach-send</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-root-view-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">telega-extras-view-archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"m"</span><span class="o">.</span><span class="nv">telega-extras-view-main</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">telega-root-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">telega-extras-chat-org-capture</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ol-telega"><code>ol-telega</code></h3><p><em><a href="https://github.com/zevlg/telega.el/blob/master/contrib/ol-telega.el">ol-telega</a> enables Org mode links to Telega chats and messages.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">ol-telega</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">telega</span><span class="p">)</span></span></span></code></pre></div><h3 id="sgn">sgn</h3><p><em><a href="https://github.com/benthamite/sgn">sgn</a> is an Emacs interface for Signal.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">sgn</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/sgn"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">sgn-account</span><span class="s">"+14246668293"</span><span class="p">))</span></span></span></code></pre></div><h3 id="wasabi"><code>wasabi</code></h3><p><em><a href="https://github.com/xenodium/wasabi/">wasabi</a> is a WhatsApp Emacs client powered by wuzapi and whatsmeow.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">wasabi</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"xenodium/wasabi"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ement"><code>ement</code></h3><p><em><a href="https://github.com/alphapapa/ement.el">ement</a> is a Matrix client for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ement</span></span></span><span class="line"><span class="cl"><span class="nb">:disabled</span><span class="p">)</span></span></span></code></pre></div><p>I installed<code>ement</code> in the hopes that I would be able to send Signal and WhatsApp messages from Emacs. I tried the<a href="https://github.com/alphapapa/ement.el/blob/6412c8aaae29ee79ccfb44582001c12d147cd5a6/e2ee.org#two-way-verification">two way verification</a> method but calling<code>panctl</code> results in a<code>dbus</code>-related error, and I was unable to make<code>dubs</code> work. Some discussion<a href="https://www.reddit.com/r/emacs/comments/1crerbh/comment/l40aszc/">here</a> (see also<a href="https://www.reddit.com/r/emacs/comments/1crerbh/comment/l40prh2/">this comment</a>).</p><h3 id="erc"><code>erc</code></h3><p><em><a href="https://www.gnu.org/software/emacs/manual/html_mono/erc.html">erc</a> is an IRC client for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">erc</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">auth-source-pass</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-server</span><span class="s">"irc.libera.chat"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-user-full-name</span><span class="nf">user-full-name</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-nick</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"user"</span><span class="s">"auth-sources/erc/libera"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-password</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="ss">'secret</span><span class="s">"auth-sources/erc/libera"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-prompt-for-nickserv-password</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; erc-track-shorten-start 8 ; characters to display in modeline</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-autojoin-channels-alist</span><span class="o">'</span><span class="p">((</span><span class="s">"irc.libera.chat"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-kill-buffer-on-part</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">erc-auto-query</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'erc-modules</span><span class="ss">'notifications</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'erc-modules</span><span class="ss">'spelling</span><span class="p">))</span></span></span></code></pre></div><h3 id="circe"><code>circe</code></h3><p><em><a href="https://github.com/emacs-circe/circe">circe</a> is another IRC client for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">circe</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="slack"><code>slack</code></h3><p><em><a href="https://github.com/yuya373/emacs-slack">slack</a> is a Slack client for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">slack</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/emacs-slack"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-file-dir</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-prefer-current-team</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-buffer-emojify</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-message-custom-notifier</span><span class="ss">'ignore</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'pass</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-register-team</span></span></span><span class="line"><span class="cl"><span class="nb">:name</span><span class="s">"Epoch AI"</span></span></span><span class="line"><span class="cl"><span class="nb">:token</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"token"</span><span class="s">"epoch/slack.com/epochai"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:cookie</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"cookie"</span><span class="s">"epoch/slack.com/epochai"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">slack-buffer-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">setopt</span><span class="nv">line-spacing</span><span class="no">nil</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-k"</span><span class="o">.</span><span class="nv">slack-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">slack-all-threads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">slack-channel-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">slack-group-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-m"</span><span class="o">.</span><span class="nv">slack-im-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-t"</span><span class="o">.</span><span class="nv">slack-change-current-team</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">slack-select-rooms</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-u"</span><span class="o">.</span><span class="nv">slack-select-unread-rooms</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-a"</span><span class="o">.</span><span class="nv">slack-all-threads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">slack-channel-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-g"</span><span class="o">.</span><span class="nv">slack-group-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-m"</span><span class="o">.</span><span class="nv">slack-im-select</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-t"</span><span class="o">.</span><span class="nv">slack-change-current-team</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-u"</span><span class="o">.</span><span class="nv">slack-select-rooms</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-u"</span><span class="o">.</span><span class="nv">slack-select-unread-rooms</span><span class="p">)</span><span class="c1">; `slack-all-unreads' not working</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-thread-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">slack-thread-show-or-create</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">slack-message-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">slack-chat-org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-other-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">slack-thread-reply</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"R"</span><span class="o">.</span><span class="nv">slack-message-add-reaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-activity-feed-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">slack-activity-feed-goto-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">slack-activity-feed-goto-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">slack-thread-show-or-create</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">slack-message-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">slack-feed-goto-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">slack-feed-goto-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">slack-thread-reply</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"R"</span><span class="o">.</span><span class="nv">slack-message-add-reaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">slack-buffer-goto-prev-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">slack-buffer-goto-next-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">slack-thread-show-or-create</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">slack-message-edit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">slack-buffer-goto-prev-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">slack-buffer-goto-next-message</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">slack-chat-org-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">slack-thread-reply</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"R"</span><span class="o">.</span><span class="nv">slack-message-add-reaction</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-z"</span><span class="o">.</span><span class="nv">slack-message-write-another-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-message-compose-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">slack-message-send-from-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">slack-message-select-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-m"</span><span class="o">.</span><span class="nv">slack-message-embed-mention</span><span class="p">)))</span></span></span></code></pre></div><h3 id="slack-extras"><code>slack-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/slack-extras.el">slack-extras</a> collects my extensions for<code>slack</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">slack-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">slack</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">slack-activity-feed-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">slack-extras-work-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">slack-extras-personal-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-thread-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">slack-extras-work-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">slack-extras-personal-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">slack-message-buffer-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">slack-extras-work-capture</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">slack-extras-personal-capture</span><span class="p">)))</span></span></span></code></pre></div><h3 id="ol-emacs-slack"><code>ol-emacs-slack</code></h3><p><em><a href="https://github.com/ag91/ol-emacs-slack">ol-emacs-slack</a> provides<code>org-store-link</code> support for<code>slack</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ol-emacs-slack</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/ol-emacs-slack"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">slack</span><span class="p">)</span></span></span></code></pre></div><h2 id="web">web</h2><ul><li><a href="http://www.howardism.org/Technical/Emacs/browsing-in-emacs.html">Emacs-focused Web Browsing</a></li><li><a href="https://protesilaos.com/codelog/2021-03-25-emacs-eww/">EWW and my extras (text-based Emacs web browser) | Protesilaos Stavrou</a></li></ul><h3 id="browse-url"><code>browse-url</code></h3><p><em>browse-url provides functions for browsing URLs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">browse-url</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">browse-url-browser-function</span><span class="ss">'eww-browse-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">browse-url-firefox-program</span><span class="s">"/Applications/Firefox.app/Contents/MacOS/firefox"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">browse-url-chrome-program</span><span class="s">"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"</span><span class="p">))</span></span></span></code></pre></div><h3 id="browse-url-extras"><code>browse-url-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/browse-url-extras.el">browse-url-extras</a> collects my extensions for<code>browse-url</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">browse-url-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'xwidget</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bind-keys</span><span class="nb">:map</span><span class="ss">'xwidget-webkit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">browse-extras-browse-url-externally</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">browse-url</span><span class="p">)</span></span></span></code></pre></div><h3 id="shr"><code>shr</code></h3><p><em>shr is a simple HTML renderer.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">shr</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">faces-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-bullet</span><span class="s">"• "</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-use-colors</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-use-fonts</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-image-animate</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-width</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-max-width</span><span class="mi">100</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-discard-aria-hidden</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-cookie-policy</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">faces-extras-set-and-store-face-attributes</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="nv">shr-text</span><span class="nb">:height</span><span class="mf">0.65</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; doesn’t seem to be working?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-h1</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">shr-h2</span><span class="nb">:family</span><span class="nv">faces-extras-fixed-pitch-font</span><span class="nb">:height</span><span class="nv">faces-extras-org-level-height</span><span class="p">))))</span></span></span></code></pre></div><h3 id="html"><code>html</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/textmodes/sgml-mode.el">html</a> provides a major mode for editing HTML files.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">html</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">html-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">eww-extras-browse-file</span><span class="p">)))</span></span></span></code></pre></div><h3 id="mhtml"><code>mhtml</code></h3><p><em>mhtml is an editing mode that handles CSS and JavaScript.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">mhtml</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">mhtml-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-x"</span><span class="o">.</span><span class="nv">browse-url-of-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-w"</span><span class="o">.</span><span class="nv">eww-extras-browse-file</span><span class="p">)))</span></span></span></code></pre></div><h3 id="shr-tag-pre-highlight"><code>shr-tag-pre-highlight</code></h3><p><em><a href="https://github.com/xuchunyang/shr-tag-pre-highlight.el">shr-tag-pre-highlight</a> adds syntax highlighting for code blocks in HTML rendered by<code>shr</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">shr-tag-pre-highlight</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="p">(</span><span class="nb">:any</span><span class="nv">eww</span><span class="nv">elfeed</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'shr-external-rendering-functions</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">pre</span><span class="o">.</span><span class="nv">shr-tag-pre-highlight</span><span class="p">)))</span></span></span></code></pre></div><h3 id="shr-heading"><code>shr-heading</code></h3><p><em><a href="https://github.com/oantolin/emacs-config/blob/master/my-lisp/shr-heading.el">shr-heading</a> supports heading navigation for shr-rendered buffers.</em></p><p>Discussion<a href="https://www.reddit.com/r/emacs/comments/u234pn/comment/i4i3gqg/?utm_source=share&amp;utm_medium=web2x&amp;context=3">here</a>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">shr-heading</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"oantolin/emacs-config"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"my-lisp/shr-heading.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">shr</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-mode-hook</span><span class="o">.</span><span class="nv">shr-heading-setup-imenu</span><span class="p">))</span></span></span></code></pre></div><h3 id="eww"><code>eww</code></h3><p><em>eww is a text-based web browser.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">eww</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">simple-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-search-prefix</span><span class="s">"https://duckduckgo.com/?t=h_&amp;q="</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-restore-desktop</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-desktop-remove-duplicates</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-header-line-format</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-download-directory</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-auto-rename-buffer</span><span class="ss">'title</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-suggest-uris</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="nv">eww-links-at-point</span></span></span><span class="line"><span class="cl"><span class="nv">thing-at-point-url-at-point</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-history-limit</span><span class="nv">most-positive-fixnum</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eww-browse-url-new-window-is-tab</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; make eww respect url handlers when following links in webpages</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nf">cons</span><span class="nv">browse-url-handlers</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">setopt</span><span class="nv">eww-use-browse-url</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="nv">eww-use-browse-url</span><span class="s">"\\|"</span><span class="p">(</span><span class="nf">car</span><span class="nf">cons</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">var</span><span class="o">'</span><span class="p">(</span><span class="nv">eww-history</span><span class="nv">eww-prompt-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="nv">var</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-w"</span><span class="o">.</span><span class="nv">eww</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">eww-follow-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S-&lt;return&gt;"</span><span class="o">.</span><span class="nv">eww-follow-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">shr-heading-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">shr-heading-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"["</span><span class="o">.</span><span class="nv">eww-previous-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"]"</span><span class="o">.</span><span class="nv">eww-next-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">eww-back-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">eww-forward-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">browse-url-extras-add-domain-to-open-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-eww</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"F"</span><span class="o">.</span><span class="nv">ace-link-extras-eww-new-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ace-link-extras-eww-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">eww-toggle-fonts</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"r"</span><span class="o">.</span><span class="nv">eww-reload</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; ":" (lambda! (eww-follow-link '(4)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"X"</span><span class="o">.</span><span class="nv">eww-browse-with-external-browser</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-c"</span><span class="o">.</span><span class="nv">org-extras-eww-copy-for-org-mode</span><span class="p">)))</span></span></span></code></pre></div><h3 id="eww-extras"><code>eww-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/eww-extras.el">eww-extras</a> collects my extensions for<code>eww</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">eww-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">eww</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'xwidget</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'eww</span><span class="nb">:before</span><span class="nf">#'</span><span class="nv">eww-extras-browse-youtube</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g e"</span><span class="o">.</span><span class="nv">eww-extras-edit-current-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g u"</span><span class="o">.</span><span class="nv">eww-extras-go-up-url-hierarchy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"g U"</span><span class="o">.</span><span class="nv">eww-extras-go-to-root-url-hierarchy</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; "p" 'eww-extras-open-with-recent-kill-ring</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"h"</span><span class="o">.</span><span class="nv">eww-extras-url-to-html</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"p"</span><span class="o">.</span><span class="nv">eww-extras-url-to-pdf</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">eww-extras-open-with-xwidget</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-d"</span><span class="o">.</span><span class="nv">eww-extras-url-to-pdf</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-h"</span><span class="o">.</span><span class="nv">eww-extras-url-to-html</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">xwidget-webkit-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">eww-extras-open-with-eww</span><span class="p">)))</span></span></span></code></pre></div><h3 id="prot-eww"><code>prot-eww</code></h3><p><em>[[<a href="https://github.com/protesilaos/dotfiles/blob/master/emacs">https://github.com/protesilaos/dotfiles/blob/master/emacs</a></em>.emacs.d/prot-lisp/prot-eww.el][prot-eww]] is a set of<code>eww</code> extensions from Protesilaos Stavrou&rsquo;s personal configuration._</p><p>Note Prot&rsquo;s clarification:</p><blockquote><p>Remember that every piece of Elisp that I write is for my own educational and recreational purposes. I am not a programmer and I do not recommend that you copy any of this if you are not certain of what it does.</p></blockquote><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">prot-eww</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"protesilaos/dotfiles"</span></span></span><span class="line"><span class="cl"><span class="nb">:local-repo</span><span class="s">"prot-eww"</span></span></span><span class="line"><span class="cl"><span class="nb">:main</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-eww.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-check-version</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"emacs/.emacs.d/prot-lisp/prot-eww.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">eww</span><span class="nv">prot-common</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-f"</span><span class="o">.</span><span class="nv">prot-eww-visit-url-on-page</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-f"</span><span class="o">.</span><span class="nv">prot-eww-jump-to-url-on-page</span><span class="p">)))</span></span></span></code></pre></div><h3 id="w3m"><code>w3m</code></h3><p><em><a href="https://github.com/emacs-w3m/emacs-w3m">w3m</a> is an Emacs interface to w3m.</em></p><p>I only use<code>w3m</code> to browse HTML email messages with<code>mu4e</code>. For web browsing, I use<code>eww</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">w3m</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">simple</span><span class="nv">mu4e</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">w3m-minor-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;left&gt;"</span><span class="o">.</span><span class="nv">left-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;right&gt;"</span><span class="o">.</span><span class="nv">right-char</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;up&gt;"</span><span class="o">.</span><span class="nv">previous-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;down&gt;"</span><span class="o">.</span><span class="nv">next-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">w3m-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-&lt;return&gt;"</span><span class="o">.</span><span class="nv">w3m-view-url-with-browse-url</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">mu4e-view-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">w3m-view-url-with-browse-url</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elfeed"><code>elfeed</code></h3><p><em><a href="https://github.com/skeeto/elfeed">elfeed</a> is a web feeds client.</em></p><p>If the lines are breaking at the wrong places, set<code>shr-width</code> to the right value.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elfeed</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/elfeed"</span></span></span><span class="line"><span class="cl"><span class="nb">:branch</span><span class="s">"debounce-search-update"</span><span class="p">)</span><span class="c1">; https://github.com/skeeto/elfeed/pull/558</span></span></span><span class="line"><span class="cl"><span class="nb">:init</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">5</span><span class="mi">60</span><span class="p">)</span><span class="no">t</span><span class="nf">#'</span><span class="nv">elfeed-extras-update</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-curl-timeout</span><span class="mi">5</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-curl-max-connections</span><span class="mi">4</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-search-remain-on-entry</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">setq-default</span><span class="nv">elfeed-search-filter</span><span class="s">"@15-days-ago +unread"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-show-mode-hook</span><span class="o">.</span><span class="nv">visual-line-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-search-mode-hook</span><span class="o">.</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Disable undo in ‘*elfeed-search*’ buffer to avoid warnings."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">buffer-disable-undo</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-f"</span><span class="o">.</span><span class="nv">elfeed</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">eww-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">elfeed-kill-link-url-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">elfeed-search-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"U"</span><span class="o">.</span><span class="nv">elfeed-search-tag-all-unread</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"d"</span><span class="o">.</span><span class="nv">elfeed-update</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">avy-extras-elfeed-search-show-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">elfeed-unjam</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"o"</span><span class="o">.</span><span class="nv">elfeed-org</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s"</span><span class="o">.</span><span class="nv">elfeed-search-live-filter</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">elfeed-show-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;return&gt;"</span><span class="o">.</span><span class="nv">eww-follow-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">","</span><span class="o">.</span><span class="nv">shr-heading-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">shr-heading-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"F"</span><span class="o">.</span><span class="nv">ace-link-extras-eww-new-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"S-&lt;return&gt;"</span><span class="o">.</span><span class="nv">eww-follow-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">zotra-extras-add-entry</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"b"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-eww</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">elfeed-show-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="nv">files-extras-kill-this-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"q"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"s-f"</span><span class="o">.</span><span class="nv">ace-link-extras-eww-externally</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"x"</span><span class="o">.</span><span class="nv">elfeed-show-visit</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elfeed-extras"><code>elfeed-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/elfeed-extras.el">elfeed-extras</a> collects my extensions for<code>elfeed</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">elfeed-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">elfeed</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-show-entry-switch</span><span class="nf">#'</span><span class="nv">elfeed-extras-display-buffer</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-search-mode-hook</span><span class="o">.</span><span class="nv">elfeed-extras-disable-undo</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">elfeed-search-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A"</span><span class="o">.</span><span class="nv">elfeed-extras-mark-all-as-read</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"e"</span><span class="o">.</span><span class="nv">elfeed-extras-toggle-read-entries</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">elfeed-extras-follow-previous</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">elfeed-extras-follow-next</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">elfeed-extras-toggle-wiki-entries</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"&lt;tab&gt;"</span><span class="o">.</span><span class="nv">elfeed-extras-jump-to-next-link</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"i"</span><span class="o">.</span><span class="nv">elfeed-extras-toggle-fixed-pitch</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"w"</span><span class="o">.</span><span class="nv">elfeed-extras-kill-link-url-of-entry</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elfeed-org"><code>elfeed-org</code></h3><p><em><a href="https://github.com/remyhonig/elfeed-org">elfeed-org</a> supports defining the feeds used by elfeed in an org-mode file.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elfeed-org</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">elfeed</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">rmh-elfeed-org-files</span><span class="p">(</span><span class="nf">list</span><span class="nv">paths-file-feeds-pablo</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-org</span><span class="p">))</span></span></span></code></pre></div><h3 id="elfeed-tube"><code>elfeed-tube</code></h3><p><em><a href="https://github.com/karthink/elfeed-tube">elfeed-tube</a> integrates<code>elfeed</code> with YouTube.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elfeed-tube</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">elfeed</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-tube-auto-save-p</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">push</span><span class="o">'</span><span class="p">(</span><span class="nv">text</span><span class="o">.</span><span class="nv">shr-text</span><span class="p">)</span><span class="nv">elfeed-tube-captions-faces</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-tube-setup</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">elfeed-show-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"v"</span><span class="o">.</span><span class="nv">elfeed-tube-mpv</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"F"</span><span class="o">.</span><span class="nv">elfeed-tube-mpv-follow-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"."</span><span class="o">.</span><span class="nv">elfeed-tube-mpv-where</span><span class="p">)))</span></span></span></code></pre></div><h3 id="elfeed-tube-mpv"><code>elfeed-tube-mpv</code></h3><p><em><a href="https://github.com/karthink/elfeed-tube">elfeed-tube-mpv</a> integrates<code>elfeed-tube</code> with<code>mpv</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elfeed-tube-mpv</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">elfeed-tube</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-tube-save-indicator</span><span class="no">t</span><span class="p">))</span></span></span></code></pre></div><h3 id="elfeed-ai"><code>elfeed-ai</code></h3><p><em><a href="https://github.com/benthamite/elfeed-ai/">elfeed-ai</a> provides AI-powered content curation for<code>elfeed</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">elfeed-ai</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/elfeed-ai"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">elfeed</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-ai-model</span><span class="ss">'gemini-flash-lite-latest</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-ai-interest-profile</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-notes</span><span class="s">"my-reading-taste-profile-summary.org"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">elfeed-ai-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">elfeed-search-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"a"</span><span class="o">.</span><span class="nv">elfeed-ai-menu</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"t"</span><span class="o">.</span><span class="nv">elfeed-ai-toggle-sort</span><span class="p">)))</span></span></span></code></pre></div><h3 id="engine-mode"><code>engine-mode</code></h3><p><em><a href="https://github.com/hrs/engine-mode">engine-mode</a> is a minor mode for defining and querying search engines through Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">engine-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">engine/browser-function</span><span class="nv">browse-url-browser-function</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">engine/set-keymap-prefix</span><span class="p">(</span><span class="nv">kbd</span><span class="s">"H-g"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AllMusic</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.allmusic.com/search/all/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Alignment-Forum</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.alignmentforum.org/search?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AlternativeTo</span></span></span><span class="line"><span class="cl"><span class="s">"http://alternativeto.net/SearchResult.aspx?profile=all&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a t"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-DE</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.amazon.de/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-ES</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.amazon.es/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-FR</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.amazon.fr/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">TheresAnAIForThat</span></span></span><span class="line"><span class="cl"><span class="s">"https://theresanaiforthat.com/s/%s/"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-MX</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.amazon.com.mx/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a x"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-UK</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.amazon.co.uk/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a k"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Amazon-US</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.amazon.com/s?k=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a a"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AnkiWeb</span></span></span><span class="line"><span class="cl"><span class="s">"https://ankiweb.net/shared/decks/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AstralCodexTen</span></span></span><span class="line"><span class="cl"><span class="s">"https://substack.com/search/%s?focusedPublicationId=89120"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a c"</span></span></span><span class="line"><span class="cl"><span class="c1">;; individual Substack posts render nicely in eww, but for other pages we need a modern browser</span></span></span><span class="line"><span class="cl"><span class="nb">:browser</span><span class="ss">'browse-url-default-browser</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Audible</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.audible.com/search/ref=a_hp_tseft?advsearchKeywords=%s&amp;filterby=field-keywords&amp;x=13&amp;y=11"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a u"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AudioBookBay</span></span></span><span class="line"><span class="cl"><span class="s">"https://audiobookbay.lu/?s=%s&amp;tt=1"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"a b"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">EABlogs</span></span></span><span class="line"><span class="cl"><span class="s">"https://cse.google.com/cse?cx=013594344773078830993:k3igzr2se6y&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"b b"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">BookFinder</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.bookfinder.com/search/?keywords=%s&amp;st=xl&amp;ac=qr&amp;src=opensearch"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"b f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Bing</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.bing.com/search?q=%s&amp;PC=U316&amp;FORM=CHROMN"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"b i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">UCBerkeleyLibrary</span><span class="s">"https://search.library.berkeley.edu/discovery/search?query=any,contains,%s&amp;tab=Default_UCLibrarySearch&amp;search_scope=DN_and_CI&amp;vid=01UCS_BER:UCB&amp;offset=0"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"b l"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">MercadoLibre</span></span></span><span class="line"><span class="cl"><span class="s">"https://listado.mercadolibre.com.ar/%s#D[A:qwer]"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">CRSocietyForums</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.crsociety.org/search/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Calendly</span></span></span><span class="line"><span class="cl"><span class="s">"https://calendly.com/app/login?email=%s&amp;lang=en"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c l"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">ChromeExtensions</span></span></span><span class="line"><span class="cl"><span class="s">"https://chrome.google.com/webstore/search/%s?_category=extensions"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Crossref</span></span></span><span class="line"><span class="cl"><span class="s">"https://search.crossref.org/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">MercadoLibreUsed</span></span></span><span class="line"><span class="cl"><span class="s">"https://listado.mercadolibre.com.ar/%s_ITEM*CONDITION_2230581_NoIndex_True#applied_filter_id%3DITEM_CONDITION%26applied_filter_name%3DCondici%C3%B3n%26applied_filter_order%3D10%26applied_value_id%3D2230581%26applied_value_name%3DUsado%26applied_value_order%3D2%26applied_value_results%3D9%26is_custom%3Dfalse"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"c r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">DOI</span></span></span><span class="line"><span class="cl"><span class="s">"https://doi.org/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"d o"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">DuckDuckGo</span></span></span><span class="line"><span class="cl"><span class="s">"https://duckduckgo.com/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"d d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Diccionario-Panhispánico-de-Dudas</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.rae.es/dpd/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"d p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">EAForum</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s+site:forum.effectivealtruism.org"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"f f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Ebay-UK</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.ebay.co.uk/sch/i.html?_from=R40&amp;_trksid=p2380057.m570.l1313&amp;_nkw=%s&amp;_sacat=0"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"e k"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Ebay-US</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.ebay.com/sch/i.html?_from=R40&amp;_trksid=p2380057.m570.l1313&amp;_nkw=%s&amp;_sacat=0"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"e b"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Ebay-DE</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.ebay.de/sch/i.html?_from=R40&amp;_trksid=p2380057.m570.l1313&amp;_nkw=%s&amp;_sacat=0"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"e d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Fundeu</span></span></span><span class="line"><span class="cl"><span class="s">"https://cse.google.com/cse?cx=005053095451413799011:alg8dd3pluq&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"f f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Flickr</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.flickr.com/search/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"f l"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Financial-Times</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.ft.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"f t"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">GitHub</span></span></span><span class="line"><span class="cl"><span class="s">"https://github.com/search?q=%s&amp;type=code"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g h"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Goodreads</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.goodreads.com/search/search?search_type=books&amp;search[query]=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g g"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Books</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s&amp;btnG=Search+Books&amp;tbm=bks&amp;tbo=1&amp;gws_rd=ssl"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g k"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Custom-Search</span></span></span><span class="line"><span class="cl"><span class="s">"https://cse.google.com/cse?cx=013594344773078830993:bg9mrnfwe30&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Domains</span></span></span><span class="line"><span class="cl"><span class="s">"https://domains.google.com/registrar?s=%s&amp;hl=en"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Drive</span></span></span><span class="line"><span class="cl"><span class="s">"https://drive.google.com/drive/u/0/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Trends</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.google.com/trends/explore#q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Images</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?tbm=isch&amp;source=hp&amp;biw=1920&amp;bih=1006&amp;ei=2PlgWp_OEcHF6QTo2b2ACQ&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Maps</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/maps/search/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-News</span></span></span><span class="line"><span class="cl"><span class="s">"https://news.google.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Podcasts</span></span></span><span class="line"><span class="cl"><span class="s">"https://podcasts.google.com/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g o"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Photos</span></span></span><span class="line"><span class="cl"><span class="s">"https://photos.google.com/search/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Scholar</span></span></span><span class="line"><span class="cl"><span class="s">"https://scholar.google.com/scholar?hl=en&amp;as_sdt=1%2C5&amp;q=%s&amp;btnG=&amp;lr="</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s s"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Translate</span></span></span><span class="line"><span class="cl"><span class="s">"https://translate.google.com/#auto/en/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g t"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Video</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s&amp;tbm=vid"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g v"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">GiveWell</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.givewell.org/search/ss360/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Play</span></span></span><span class="line"><span class="cl"><span class="s">"https://play.google.com/store/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g y"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Google-Scholar-Spanish</span></span></span><span class="line"><span class="cl"><span class="s">"https://scholar.google.com/scholar?hl=en&amp;as_sdt=1%2C5&amp;q=%s&amp;btnG="</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s x"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Gwern</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s+site:gwern.net"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"g w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">IMDb</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.imdb.com/find/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">IMDb-Actor</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.imdb.com/filmosearch?explore=title_type&amp;role=%s&amp;ref_=filmo_ref_job_typ&amp;sort=user_rating"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i a"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">IMDb-Director</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.imdb.com/filmosearch?explore=title_type&amp;role=%s&amp;ref_=filmo_ref_job_typ&amp;sort=user_rating"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">IMDb-Composer</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.imdb.com/filmosearch?explore=title_type&amp;role=%s&amp;ref_=filmo_ref_job_typ&amp;sort=user_rating"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">IberLibroArgentina</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.iberlibro.com/servlet/SearchResults?bi=0&amp;bx=off&amp;cm_sp=SearchF-_-Advs-_-Result&amp;cty=ar&amp;ds=20&amp;kn=%s&amp;prc=USD&amp;recentlyadded=all&amp;rgn=ww&amp;rollup=on&amp;sortby=20&amp;xdesc=off&amp;xpod=off"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Internet-Archive</span></span></span><span class="line"><span class="cl"><span class="s">"https://archive.org/search.php?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"v v"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Internet-Archive-Scholar</span></span></span><span class="line"><span class="cl"><span class="s">"https://scholar.archive.org/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"v s"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">JustWatch</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.justwatch.com/us/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"j w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">KAYAK</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.kayak.co.uk/sherlock/opensearch/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"k k"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Keyboard-Maestro</span></span></span><span class="line"><span class="cl"><span class="s">"https://forum.keyboardmaestro.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"k m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Lastfm</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.last.fm/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"f m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">LessWrong</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s+site:lesswrong.com"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"l w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">LessWrongWiki</span></span></span><span class="line"><span class="cl"><span class="s">"https://wiki.lesswrong.com/index.php?title=Special:Search&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"l i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">LibraryGenesis</span></span></span><span class="line"><span class="cl"><span class="s">"http://libgen.li/index.php?req=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"l l"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Librivox</span></span></span><span class="line"><span class="cl"><span class="s">"https://librivox.org/search?q=%s&amp;search_form=advanced"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"l v"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">LinkedIn</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.linkedin.com/vsearch/f?type=all&amp;keywords=%s&amp;orig=GLHD&amp;rsid=&amp;pageKey=member-home&amp;search=Search"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"i n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Linguee</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.linguee.com/english-spanish/search?source=auto&amp;query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"l i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Marginal-Revolution</span></span></span><span class="line"><span class="cl"><span class="s">"https://marginalrevolution.com/?s=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">MediaCenter</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s+site:yabb.jriver.com"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Medium</span></span></span><span class="line"><span class="cl"><span class="s">"https://medium.com/search?q=%s&amp;ref=opensearch"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Melpa</span></span></span><span class="line"><span class="cl"><span class="s">"https://melpa.org/#/?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">MetaFilter</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.metafilter.com/contribute/search.mefi?site=mefi&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Metaculus</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.metaculus.com/questions/?order_by=-activity&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Metaforecast</span></span></span><span class="line"><span class="cl"><span class="s">"https://metaforecast.org/?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Movielens</span></span></span><span class="line"><span class="cl"><span class="s">"https://movielens.org/explore?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"m l"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Netflix</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.netflix.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"n n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">New-York-Times</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.nytimes.com/search?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"n y"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Notatu-Dignum</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.stafforini.com/quotes/index.php?s=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"q q"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">OddsChecker</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.oddschecker.com/search?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"o c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Open-Philanthropy</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.google.com/search?q=%s+site:openphilanthropy.org"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"o p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Overcoming-Bias</span></span></span><span class="line"><span class="cl"><span class="s">"https://substack.com/search/%s?focusedPublicationId=1245641"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"o b"</span></span></span><span class="line"><span class="cl"><span class="nb">:browser</span><span class="ss">'browse-url-default-browser</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">OxfordReference</span></span></span><span class="line"><span class="cl"><span class="s">"https://www-oxfordreference-com.myaccess.library.utoronto.ca/search?btog=chap&amp;q0=%22%s%22"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"o r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">OxfordReferenceDOI</span></span></span><span class="line"><span class="cl"><span class="s">"https://www-oxfordreference-com.myaccess.library.utoronto.ca/view/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"o d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">PhilPapers</span></span></span><span class="line"><span class="cl"><span class="s">"http://philpapers.org/s/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"p p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">AnnasArchive</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'annas-archive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="nv">annas-archive-home-url</span><span class="s">"search?index=&amp;page=1&amp;q=%s&amp;ext=pdf&amp;sort="</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"r r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">ReducingSuffering</span></span></span><span class="line"><span class="cl"><span class="s">"http://reducing-suffering.org/?s=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"r s"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Reference</span></span></span><span class="line"><span class="cl"><span class="s">"https://cse.google.com/cse?cx=013594344773078830993:bg9mrnfwe30&amp;q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"r f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">sci-hub</span></span></span><span class="line"><span class="cl"><span class="s">"https://sci-hub.se/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"u u"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">ScienceDirectencyclopedias</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.sciencedirect.com/search?qs=%s&amp;articleTypes=EN"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">SlateStarCodex</span></span></span><span class="line"><span class="cl"><span class="s">"http://slatestarcodex.com/?s=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">StackSnippet</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.stacksnippet.com/#gsc.tab=0&amp;gsc.q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s n"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Stanford-Encyclopedia-of-Philosophy</span></span></span><span class="line"><span class="cl"><span class="s">"https://plato.stanford.edu/search/searcher.py?query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"s p"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Tango-DJ</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.tango-dj.at/database/?tango-db-search=%s&amp;search=Search"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"d j"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">TangoDJ-Yahoo-Group</span></span></span><span class="line"><span class="cl"><span class="s">"http://groups.yahoo.com/group/TangoDJ/msearch?query=%s&amp;submit=Search&amp;charset=ISO-8859-1"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"t y"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">TasteDive</span></span></span><span class="line"><span class="cl"><span class="s">"https://tastedive.com/like/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"t d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">ThreadReader</span></span></span><span class="line"><span class="cl"><span class="s">"https://threadreaderapp.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"t r"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Twitter</span></span></span><span class="line"><span class="cl"><span class="s">"https://twitter.com/search?q=%s&amp;src=typed_query"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"t w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Vimeo</span></span></span><span class="line"><span class="cl"><span class="s">"http://vimeo.com/search?q=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"v m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">WaybackMachine</span></span></span><span class="line"><span class="cl"><span class="s">"http://web.archive.org/web/*/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w b"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-Deutsch</span></span></span><span class="line"><span class="cl"><span class="s">"https://de.wikipedia.org/w/index.php?title=Spezial:Suche&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w d"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-English</span></span></span><span class="line"><span class="cl"><span class="s">"http://en.wikipedia.org/w/index.php?title=Special:Search&amp;profile=default&amp;search=%s&amp;fulltext=Search"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w w"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-French</span></span></span><span class="line"><span class="cl"><span class="s">"http://fr.wikipedia.org/w/index.php?title=Spécial:Recherche&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-Italiano</span></span></span><span class="line"><span class="cl"><span class="s">"http://it.wikipedia.org/w/index.php?title=Speciale:Ricerca&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w i"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-Spanish</span></span></span><span class="line"><span class="cl"><span class="s">"https://es.wikipedia.org/w/index.php?search=%s&amp;title=Especial:Buscar&amp;ns0=1&amp;ns11=1&amp;ns100=1"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w e"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wikipedia-Swedish</span></span></span><span class="line"><span class="cl"><span class="s">"http://sv.wikipedia.org/w/index.php?title=Special:S%C3%B6k&amp;search=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w s"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">Wirecutter</span></span></span><span class="line"><span class="cl"><span class="s">"https://thewirecutter.com/search/?s=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w t"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">WorldCat</span></span></span><span class="line"><span class="cl"><span class="s">"http://www.worldcat.org/search?q=%s&amp;qt=results_page"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"w c"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">YahooFinance</span></span></span><span class="line"><span class="cl"><span class="s">"https://finance.yahoo.com/company/%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"y f"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">YouTube</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.youtube.com/results?search_query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"y t"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">defengine</span><span class="nv">YouTubemovies</span></span></span><span class="line"><span class="cl"><span class="s">"https://www.youtube.com/results?lclk=long&amp;filters=hd%2Clong&amp;search_query=%s"</span></span></span><span class="line"><span class="cl"><span class="nb">:keybinding</span><span class="s">"y m"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:hook</span><span class="nv">minibuffer-setup-hook</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-download"><code>org-download</code></h3><p><em><a href="https://github.com/abo-abo/org-download">org-download</a> supports drag and drop images to org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-download</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"H-s-v"</span><span class="o">.</span><span class="nv">org-download-clipboard</span><span class="p">))</span></span></span></code></pre></div><h3 id="org-web-tools"><code>org-web-tools</code></h3><p><em><a href="https://github.com/alphapapa/org-web-tools">org-web-tools</a> supports viewing, capturing, and archiving web pages in org-mode.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">org-web-tools</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="org-web-tools-extras"><code>org-web-tools-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/org-web-tools-extras.el">org-web-tools-extras</a> collects my extensions for<code>org-web-tools</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">org-web-tools-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">org-web-tools</span><span class="p">)</span></span></span></code></pre></div><h3 id="request"><code>request</code></h3><p><em><a href="https://github.com/tkf/emacs-request">request</a> provides HTTP request for Emacs Lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">request</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="deferred"><code>deferred</code></h3><p><em><a href="https://github.com/kiwanami/emacs-deferred">deferred</a> provides simple asynchronous functions for emacs lisp.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">deferred</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="graphql-mode"><code>graphql-mode</code></h3><p><em><a href="https://github.com/davazp/graphql-mode">graphql-mode</a> is a major mode for GraphQL.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">graphql-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="mullvad"><code>mullvad</code></h3><p><em><a href="https://github.com/benthamite/mullvad">mullvad</a> provides a few functions for interfacing with Mullvad, a VPN service.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">mullvad</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nv">mullvad</span></span></span><span class="line"><span class="cl"><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/mullvad"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mullvad-durations</span><span class="o">'</span><span class="p">(</span><span class="mi">1</span><span class="mi">5</span><span class="mi">10</span><span class="mi">30</span><span class="mi">60</span><span class="mi">120</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mullvad-cities-and-servers</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"London"</span><span class="o">.</span><span class="s">"gb-lon-ovpn-005"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Madrid"</span><span class="o">.</span><span class="s">"es-mad-ovpn-202"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Malmö"</span><span class="o">.</span><span class="s">"se-sto-wg-005"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Frankfurt"</span><span class="o">.</span><span class="s">"de-fra-wg-005"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"New York"</span><span class="o">.</span><span class="s">"us-nyc-wg-504"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"San José"</span><span class="o">.</span><span class="s">"us-sjc-wg-101"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"São Paulo"</span><span class="o">.</span><span class="s">"br-sao-wg-202"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mullvad-websites-and-cities</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"Betfair"</span><span class="o">.</span><span class="s">"London"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Criterion Channel"</span><span class="o">.</span><span class="s">"New York"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Gemini"</span><span class="o">.</span><span class="s">"New York"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"HathiTrust"</span><span class="o">.</span><span class="s">"San José"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"IMDb"</span><span class="o">.</span><span class="s">"New York"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Library Genesis"</span><span class="o">.</span><span class="s">"Malmö"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Pirate Bay"</span><span class="o">.</span><span class="s">"Malmö"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"UC Berkeley"</span><span class="o">.</span><span class="s">"San José"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"Wise"</span><span class="o">.</span><span class="s">"Madrid"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-a"</span><span class="o">.</span><span class="nv">mullvad</span><span class="p">))</span></span></span></code></pre></div><h2 id="multimedia">multimedia</h2><h3 id="emms"><code>EMMS</code></h3><p><em><a href="https://www.gnu.org/software/emms/">EMMS</a> (Emacs MultiMedia System) is media player software for Emacs.</em></p><p>EMMS is not powerful enough for my use case (tango DJ with a collection of over 70,000 tracks). But I&rsquo;m exploring whether I can use it for specific purposes, such as batch-tagging.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">emms</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:disabled</span><span class="no">t</span><span class="c1">; temporarily because server is down</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-player-list</span><span class="o">'</span><span class="p">(</span><span class="nv">emms-player-mpv</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-source-file-default-directory</span><span class="nv">paths-dir-music-tango</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-playlist-buffer-name</span><span class="s">"*Music*"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-info-functions</span><span class="o">'</span><span class="p">(</span><span class="nv">emms-info-libtag</span><span class="p">))</span><span class="c1">; make sure libtag is the only thing delivering metadata</span></span></span><span class="line"><span class="cl"><span class="c1">;; ~1 order of magnitude fzaster; requires GNU find: `brew install findutils'</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-source-file-directory-tree-function</span><span class="ss">'emms-source-file-directory-tree-find</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-setup</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-player-simple</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-source-file</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-source-playlist</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-info-native</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; emms-print-metadata binary must be present; see emacs.stackexchange.com/a/22431/32089</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-info-libtag</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-mode-line</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-mode-line-icon</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'emms-playing-time</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-all</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-default-players</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'emms-info-functions</span><span class="ss">'emms-info-libtag</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-mode-line-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">emms-playing-time</span><span class="mi">1</span><span class="p">))</span></span></span></code></pre></div><h3 id="empv"><code>empv</code></h3><p><em><a href="https://github.com/isamert/empv.el">empv</a> is a media player based on<a href="https://mpv.io/">mpv</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">empv</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"isamert/empv.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">empv-audio-dir</span><span class="nv">paths-dir-music-tango</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">empv-invidious-instance</span><span class="s">"https://invidious.fdn.fr/api/v1"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'empv-mpv-args</span><span class="s">"--ytdl-format=best"</span><span class="p">))</span><span class="c1">; github.com/isamert/empv.el#viewing-youtube-videos</span></span></span></code></pre></div><h3 id="tangodb"><code>tangodb</code></h3><p><em><a href="https://github.com/benthamite/tangodb.el">tangodb</a> is a package for browsing and editing a tango encyclopaedia.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">tangodb</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/tangodb.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="trx"><code>trx</code></h3><p><em><a href="https://github.com/benthamite/trx">trx</a> is an Emacs interface for the<a href="https://transmissionbt.com/">Transmission</a> BitTorrent client.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">trx</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/trx"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="ytdl"><code>ytdl</code></h3><p><em><a href="https://gitlab.com/tuedachu/ytdl">ytdl</a> is an Emacs interface for<a href="https://youtube-dl.org/">youtube-dl</a>.</em></p><p>Note that this package also works with<a href="https://github.com/yt-dlp/yt-dlp">yt-dlp</a>, a<code>youtube-dl</code> fork.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">ytdl</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ytdl-command</span><span class="s">"yt-dlp"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ytdl-video-folder</span><span class="nv">paths-dir-downloads</span></span></span><span class="line"><span class="cl"><span class="nv">ytdl-music-folder</span><span class="nv">paths-dir-downloads</span></span></span><span class="line"><span class="cl"><span class="nv">ytdl-download-folder</span><span class="nv">paths-dir-downloads</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">ytdl-video-extra-args</span><span class="o">.</span><span class="p">(</span><span class="s">"--write-sub"</span><span class="s">"--write-auto-sub"</span><span class="s">"--sub-lang"</span><span class="s">"en,es,it,fr,pt"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-M-y"</span><span class="o">.</span><span class="nv">ytdl-download</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">ytdl--dl-list-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"RET"</span><span class="o">.</span><span class="nv">ytdl--open-item-at-point</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">ytdl--delete-item-at-point</span><span class="p">)))</span></span></span></code></pre></div><h3 id="esi-dictate"><code>esi-dictate</code></h3><p><em><a href="https://git.sr.ht/~lepisma/emacs-speech-input">esi-dictate</a> is a set of packages for speech and voice inputs in Emacs.</em></p><p><strong>Setup</strong>:</p><ol><li>Install Python dependencies:<code>pip install 'deepgram-sdk&gt;=3.0,&lt;4.0' pyaudio</code>. Note: the<code>dg.py</code> script requires SDK v3.x; v5.x has a completely different API and will not work.</li><li>Download<code>dg.py</code> from the repo and place it in your PATH (e.g.,<code>~/.local/bin/dg.py</code>), then make it executable:<code>chmod +x ~/.local/bin/dg.py</code></li></ol><p><strong>Usage</strong>:<code>M-x esi-dictate-start</code> to begin dictation,<code>C-g</code> to stop.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">esi-dictate</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">sourcehut</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"lepisma/emacs-speech-input"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">llm</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">esi-dictate-llm-provider</span><span class="p">(</span><span class="nv">make-llm-openai</span></span></span><span class="line"><span class="cl"><span class="nb">:key</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"gptel"</span><span class="p">(</span><span class="nf">concat</span><span class="s">"tlon/core/openai.com/"</span><span class="nv">tlon-email-shared</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:chat-model</span><span class="s">"gpt-4o-mini"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">esi-dictate-dg-api-key</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"key"</span><span class="p">(</span><span class="nf">concat</span><span class="s">"chrome/deepgram.com/"</span><span class="p">(</span><span class="nv">getenv</span><span class="s">"PERSONAL_EMAIL"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">((</span><span class="s">"A-h"</span><span class="o">.</span><span class="nv">esi-dictate-start</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">esi-dictate-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-g"</span><span class="o">.</span><span class="nv">esi-dictate-stop</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">esi-dictate-speech-final</span><span class="o">.</span><span class="nv">esi-dictate-fix-context</span><span class="p">))</span></span></span></code></pre></div><h3 id="read-aloud"><code>read-aloud</code></h3><p><em><a href="https://github.com/gromnitsky/read-aloud.el">read-aloud</a> is an Emacs interface to TTS (text-to-speech) engines.</em></p><ul><li>To give Emacs access to the microphone on MacOS, clone<code>https://github.com/DocSystem/tccutil</code> and from the cloned repo, run<code>sudo python3 tccutil.py -p /opt/homebrew/Cellar/emacs-plus@30/30.0.60/Emacs.app/ --microphone -e</code> (some discussion<a href="https://scsynth.org/t/emacs-scsynth-and-microphone-permissions/3253">here</a>).</li><li>To read with macOS directly,<code>b-n</code>. In turn,<code>b-h</code> starts dictation. (These are system-wide shortcuts defined with Karabiner rather than bindings specific to Emacs. See the &ldquo;b-mode&rdquo; section in my Karabiner configuration.)</li></ul><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">read-aloud</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">read-aloud-engine</span><span class="s">"say"</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-H-r"</span><span class="o">.</span><span class="nv">read-aloud-this</span><span class="p">))</span></span></span></code></pre></div><h3 id="read-aloud-extras"><code>read-aloud-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/read-aloud-extras.el">read-aloud-extras</a> collects my extensions for<code>read-aloud</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">read-aloud-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">read-aloud</span><span class="p">)</span></span></span></code></pre></div><h3 id="subed"><code>subed</code></h3><p><em><a href="https://github.com/sachac/subed">subed</a> is a subtitle editor for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">subed</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"sachac/subed"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"subed/*.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">subed-export-transcript</span><span class="p">()</span></span></span><span class="line"><span class="cl"><span class="s">"Export a clean transcript of the current subtitle buffer to a file.</span></span></span><span class="line"><span class="cl"><span class="s">This function retrieves all subtitle text, strips any HTML-like tags (such</span></span></span><span class="line"><span class="cl"><span class="s">as WebVTT timing or style tags within the text lines), and then saves the</span></span></span><span class="line"><span class="cl"><span class="s">result to a user-specified file."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">interactive</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">subtitles</span><span class="p">(</span><span class="nv">subed-subtitle-list</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">raw-text</span><span class="p">(</span><span class="nb">if</span><span class="nv">subtitles</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">subed-subtitle-list-text</span><span class="nv">subtitles</span><span class="no">nil</span><span class="p">)</span><span class="c1">; nil = do not include comments</span></span></span><span class="line"><span class="cl"><span class="s">""</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">cleaned-text</span><span class="p">(</span><span class="nb">if</span><span class="p">(</span><span class="nv">string-empty-p</span><span class="nv">raw-text</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">""</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">let*</span><span class="p">((</span><span class="nv">lines</span><span class="p">(</span><span class="nv">split-string</span><span class="nv">raw-text</span><span class="s">"\n"</span><span class="no">t</span><span class="p">))</span><span class="c1">; OMIT-NULLS is t</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">stripped-lines</span><span class="p">(</span><span class="nf">mapcar</span><span class="nf">#'</span><span class="nv">subed--strip-tags</span><span class="nv">lines</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">unique-lines</span><span class="p">(</span><span class="nv">seq-uniq</span><span class="nv">stripped-lines</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">mapconcat</span><span class="nf">#'identity</span><span class="nv">unique-lines</span><span class="s">"\n"</span><span class="p">))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">buffer-filename</span><span class="p">(</span><span class="nf">buffer-file-name</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">default-output-name</span><span class="p">(</span><span class="nb">if</span><span class="nv">buffer-filename</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">concat</span><span class="p">(</span><span class="nv">file-name-sans-extension</span><span class="nv">buffer-filename</span><span class="p">)</span><span class="s">".txt"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"transcript.txt"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">output-file</span><span class="p">(</span><span class="nv">read-file-name</span><span class="s">"Export clean transcript to: "</span><span class="no">nil</span><span class="nv">default-output-name</span><span class="no">t</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="nv">output-file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-temp-file</span><span class="nv">output-file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">insert</span><span class="nv">cleaned-text</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"Transcript exported to %s"</span><span class="nv">output-file</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">message</span><span class="s">"Transcript export cancelled"</span><span class="p">)))))</span></span></span></code></pre></div><h3 id="spofy"><code>spofy</code></h3><p><em><a href="https://github.com/benthamite/spofy">spofy</a> is a Spotify player for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">spofy</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/spofy"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-client-id</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"spofy-id"</span><span class="s">"chrome/accounts.spotify.com"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-client-secret</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"spofy-secret"</span><span class="s">"chrome/accounts.spotify.com"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-tab-bar-max-length</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-tab-bar-alignment</span><span class="ss">'right</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-enable-tab-bar</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">spofy-consult-columns</span><span class="o">'</span><span class="p">((</span><span class="nv">track</span><span class="mi">50</span><span class="mi">40</span><span class="mi">40</span><span class="p">)</span><span class="p">(</span><span class="nv">album</span><span class="mi">50</span><span class="mi">40</span><span class="mi">6</span><span class="p">)</span><span class="p">(</span><span class="nv">artist</span><span class="mi">50</span><span class="mi">45</span><span class="p">)</span><span class="p">(</span><span class="nv">playlist</span><span class="mi">50</span><span class="mi">35</span><span class="p">)</span><span class="p">(</span><span class="nv">device</span><span class="mi">45</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">((</span><span class="s">"A-y"</span><span class="o">.</span><span class="nv">spofy-menu</span><span class="p">)))</span></span></span></code></pre></div><h2 id="misc">misc</h2><h3 id="epoch"><code>epoch</code></h3><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">epoch</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/epoch.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:demand</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"H-l"</span><span class="o">.</span><span class="nv">epoch-menu</span><span class="p">)))</span></span></span></code></pre></div><h3 id="calc"><code>calc</code></h3><p><em>calc is the Emacs calculator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">calc</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'savehist</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'savehist-additional-variables</span><span class="ss">'calc-quick-calc-history</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-c"</span><span class="o">.</span><span class="nv">calc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-M-c"</span><span class="o">.</span><span class="nv">quick-calc</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">calc-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="calc-ext"><code>calc-ext</code></h3><p><em>calc-ext provides various extension functions for calc.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">calc-ext</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">cal</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">calc-alg-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="alert"><code>alert</code></h3><p><em><a href="https://github.com/jwiegley/alert">alert</a> is a Growl-like alerts notifier for Emacs.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">alert</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="c1">;; the settings below are not working; is it because `alert-default-style' is set to `notifier'?</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-fade-time</span><span class="mi">2</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-persist-idle-time</span><span class="mi">60</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-default-style</span><span class="ss">'osx-notifier</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; This function has to be loaded manually, for some reason.</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span><span class="nv">alert-osx-notifier-notify</span><span class="p">(</span><span class="nv">info</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nf">#'call-process</span><span class="s">"osascript"</span><span class="no">nil</span><span class="no">nil</span><span class="no">nil</span><span class="s">"-e"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nf">format</span><span class="s">"display notification %S with title %S"</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-encode-string</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">info</span><span class="nb">:message</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-encode-string</span><span class="p">(</span><span class="nf">plist-get</span><span class="nv">info</span><span class="nb">:title</span><span class="p">)))))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">alert-message-notify</span><span class="nv">info</span><span class="p">)))</span></span></span></code></pre></div><h3 id="midnight"><code>midnight</code></h3><p><em>midnight runs custom processes every night.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">midnight</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">clean-buffer-list-kill-never-buffer-names</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="s">"*mu4e-headers*"</span></span></span><span class="line"><span class="cl"><span class="s">" *mu4e-update*"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">clean-buffer-list-kill-never-regexps</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">(</span><span class="s">"\\` \\*Minibuf-.*\\*\\'"</span></span></span><span class="line"><span class="cl"><span class="s">"^untitled.*"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">clean-buffer-list-delay-general</span><span class="mi">2</span><span class="p">)</span><span class="c1">; kill buffers unused for more than three days</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">midnight-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="c1">;; setting the delay causes midnight to run immediately, so we set it via a timer</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">run-with-idle-timer</span><span class="p">(</span><span class="nf">*</span><span class="mi">3</span><span class="mi">60</span><span class="mi">60</span><span class="p">)</span><span class="no">nil</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">midnight-delay-set</span><span class="ss">'midnight-delay</span><span class="s">"5:00am"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">dolist</span><span class="p">(</span><span class="nv">fun</span><span class="p">(</span><span class="nf">nreverse</span><span class="o">'</span><span class="p">(</span><span class="nv">files-extras-save-all-buffers</span></span></span><span class="line"><span class="cl"><span class="nv">clean-buffer-list</span></span></span><span class="line"><span class="cl"><span class="nv">ledger-mode-extras-update-coin-prices</span></span></span><span class="line"><span class="cl"><span class="nv">ledger-mode-extras-update-commodities</span></span></span><span class="line"><span class="cl"><span class="nv">magit-extras-stage-commit-and-push-all-repos</span></span></span><span class="line"><span class="cl"><span class="nv">org-roam-db-sync</span></span></span><span class="line"><span class="cl"><span class="nv">org-extras-id-update-id-locations</span></span></span><span class="line"><span class="cl"><span class="nv">el-patch-validate-all</span></span></span><span class="line"><span class="cl"><span class="nv">org-extras-agenda-switch-to-agenda-current-day</span></span></span><span class="line"><span class="cl"><span class="nv">mu4e-extras-update-all-mail-and-index</span></span></span><span class="line"><span class="cl"><span class="nv">org-gcal-sync</span></span></span><span class="line"><span class="cl"><span class="nv">elfeed-update</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'midnight-hook</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">apply-partially</span><span class="nf">#'</span><span class="nv">simple-extras-call-verbosely</span></span></span><span class="line"><span class="cl"><span class="nv">fun</span><span class="s">"Midnight hook now calling</span><span class="ss">`%s'</span><span class="s">..."</span><span class="p">))))</span></span></span></code></pre></div><h3 id="bbdb"><code>bbdb</code></h3><p><em><a href="https://elpa.gnu.org/packages/bbdb.html">bbdb</a> is a contact management package.</em></p><p>A tutorial for this undocumented package may be found<a href="https://github.com/andycowl/bbdb3-manual/blob/master/tutorial.rst">here</a>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">bbdb</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/bbdb"</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="nb">:defaults</span><span class="s">"lisp/*.el"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:depth</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="nb">:pre-build</span><span class="p">((</span><span class="s">"./autogen.sh"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"./configure"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"make"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:build</span><span class="p">(</span><span class="nb">:not</span><span class="nv">elpaca-build-docs</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bbdb-file</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-bbdb</span><span class="s">"bbdn.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bbdb-image-path</span><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-bbdb</span><span class="s">"media/"</span><span class="p">))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bbdb-initialize</span><span class="ss">'anniv</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"A-b"</span><span class="o">.</span><span class="nv">bbdb</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:map</span><span class="nv">bbdb-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-r"</span><span class="o">.</span><span class="nv">bbdb-prev-record</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"A-C-s-f"</span><span class="o">.</span><span class="nv">bbdb-next-record</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"c"</span><span class="o">.</span><span class="nv">bbdb-copy-fields-as-kill</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-k"</span><span class="o">.</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"M-d"</span><span class="o">.</span><span class="no">nil</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bbdb-extras"><code>bbdb-extras</code></h3><p><em><a href="https://github.com/benthamite/dotfiles/blob/main/emacs/extras/bbdb-extras.el">bbdb-extras</a> collects my extensions for<code>bbdb</code>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-personal-package</span><span class="nv">bbdb-extras</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span><span class="p">(</span><span class="nb">:map</span><span class="nv">bbdb-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"D"</span><span class="o">.</span><span class="nv">bbdb-extras-delete-field-or-record-no-confirm</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"E"</span><span class="o">.</span><span class="nv">bbdb-extras-export-vcard</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"n"</span><span class="o">.</span><span class="nv">bbdb-extras-create-quick</span><span class="p">)))</span></span></span></code></pre></div><h3 id="bbdb-vcard"><code>bbdb-vcard</code></h3><p><em><a href="https://github.com/tohojo/bbdb-vcard">bbdb-vcard</a> supports import and export for BBDB.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">bbdb-vcard</span></span></span><span class="line"><span class="cl"><span class="nb">:after</span><span class="nv">bbdb</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bbdb-vcard-directory</span><span class="nv">paths-dir-bbdb</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">bbdb-vcard-media-directory</span><span class="s">"media"</span><span class="p">))</span></span></span></code></pre></div><h3 id="macos"><code>macos</code></h3><p><em><a href="https://github.com/benthamite/macos">macos</a> is a simple package I developed that provides a few macOS-specific functions.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">macos</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/macos"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">macos-bluetooth-device-list</span></span></span><span class="line"><span class="cl"><span class="o">'</span><span class="p">((</span><span class="s">"Sonny WH-1000XM5"</span><span class="o">.</span><span class="s">"ac-80-0a-37-41-1e"</span><span class="p">)))</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">((</span><span class="s">"C-M-s-c"</span><span class="o">.</span><span class="nv">macos-bluetooth-device-dwim</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"C-M-s-g"</span><span class="o">.</span><span class="nv">macos-set-dication-language</span><span class="p">)))</span></span></span></code></pre></div><h3 id="keycast"><code>keycast</code></h3><p><em><a href="https://github.com/tarsius/keycast">keycast</a> shows the current command and its key in the mode line.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">keycast</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="c1">;; support for doom modeline (github.com/tarsius/keycast/issues/7)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">with-eval-after-load</span><span class="ss">'keycast</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">define-minor-mode</span><span class="nv">keycast-mode</span></span></span><span class="line"><span class="cl"><span class="s">"Show current command and its key binding in the mode line."</span></span></span><span class="line"><span class="cl"><span class="nb">:global</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">if</span><span class="nv">keycast-mode</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span><span class="ss">'pre-command-hook</span><span class="ss">'keycast--update</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">remove-hook</span><span class="ss">'pre-command-hook</span><span class="ss">'keycast--update</span><span class="p">)))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-to-list</span><span class="ss">'global-mode-string</span><span class="o">'</span><span class="p">(</span><span class="s">""</span><span class="nv">keycast-mode-line</span><span class="p">))))</span></span></span></code></pre></div><h3 id="activity-watch-mode"><code>activity-watch-mode</code></h3><p><em><a href="https://github.com/wakatime/wakatime-mode">activity-watch-mode</a> is an Emacs watcher for<a href="https://activitywatch.net/">ActivityWatch</a>.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">activity-watch-mode</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="mi">30</span></span></span><span class="line"><span class="cl"><span class="nb">:config</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">require</span><span class="ss">'magit</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-activity-watch-mode</span><span class="p">)</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">advice-add</span><span class="ss">'activity-watch--save</span><span class="nb">:around</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">lambda</span><span class="p">(</span><span class="nv">fn</span><span class="kp">&amp;rest</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="s">"Ignore errors from activity-watch (e.g. missing directories)."</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">condition-case</span><span class="no">nil</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">apply</span><span class="nv">fn</span><span class="nv">args</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="ne">error</span><span class="no">nil</span><span class="p">)))))</span></span></span></code></pre></div><h3 id="custom"><code>custom</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/custom.el">custom</a> provides the Customize interface for user options and themes.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">custom</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">custom-safe-themes</span><span class="no">t</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">custom-file</span><span class="p">(</span><span class="nv">make-temp-file</span><span class="s">"gone-baby-gone"</span><span class="p">))</span><span class="c1">; move unintended customizations to a garbage file</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">custom-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"f"</span><span class="o">.</span><span class="nv">ace-link-custom</span><span class="p">)))</span></span></span></code></pre></div><h3 id="mercado-libre"><code>mercado-libre</code></h3><p><em><a href="https://github.com/benthamite/mercado-libre">mercado-libre</a> is a package for querying MercadoLibre, a popular Latin American e-commerce platform.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">mercado-libre</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/mercado-libre"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mercado-libre-client-id</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"app-id"</span><span class="s">"chrome/mercadolibre.com/benthamite"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mercado-libre-client-key</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"app-key"</span><span class="s">"chrome/mercadolibre.com/benthamite"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mercado-libre-new-results-limit</span><span class="no">nil</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">mercado-libre-listings-db-file</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">file-name-concat</span><span class="nv">paths-dir-dropbox</span><span class="s">"Apps/Mercado Libre/mercado-libre-listings.el"</span><span class="p">)))</span></span></span></code></pre></div><h3 id="polymarket"><code>polymarket</code></h3><p><em><a href="https://github.com/benthamite/polymarket">polymarket</a> is a package to fetch and place trades on Polymarket, a popular prediction market.</em></p><p>(This package is not currently public.)</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">polymarket</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/polymarket"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span><span class="p">)</span></span></span></code></pre></div><h3 id="kelly"><code>kelly</code></h3><p><em><a href="https://github.com/benthamite/kelly">kelly</a> is a Kelly criterion calculator.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">kelly</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:repo</span><span class="s">"benthamite/kelly"</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="nb">:defer</span><span class="no">t</span></span></span><span class="line"><span class="cl"/></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">kelly-b-parameter-type</span><span class="ss">'probability</span><span class="p">))</span></span></span></code></pre></div><h3 id="fatebook"><code>fatebook</code></h3><p><em><a href="https://github.com/sonofhypnos/fatebook.el">fatebook</a> is an Emacs package to create predictions on Fatebook.</em></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span><span class="nv">fatebook</span></span></span><span class="line"><span class="cl"><span class="nb">:ensure</span><span class="p">(</span><span class="nb">:repo</span><span class="s">"sonofhypnos/fatebook.el"</span></span></span><span class="line"><span class="cl"><span class="nb">:host</span><span class="nv">github</span></span></span><span class="line"><span class="cl"><span class="nb">:files</span><span class="p">(</span><span class="s">"fatebook.el"</span><span class="p">))</span></span></span><span class="line"><span class="cl"><span class="nb">:commands</span><span class="nv">fatebook-create-question</span></span></span><span class="line"><span class="cl"><span class="nb">:custom</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">fatebook-api-key-function</span><span class="p">(</span><span class="nb">lambda</span><span class="p">()</span><span class="p">(</span><span class="nv">auth-source-pass-get</span><span class="s">"api"</span><span class="s">"chrome/fatebook.io"</span><span class="p">))))</span></span></span></code></pre></div><h3 id="keyboard-maestro"><code>keyboard-maestro</code></h3><p><em>Keybindings for triggering Emacs commands from<a href="https://www.keyboardmaestro.com/">Keyboard Maestro</a>.</em></p><p>These bindings allow Keyboard Maestro to trigger various Emacs processes.</p><p>Note to self: The pattern for KM shortcuts is<code>C-H-&lt;capital-letter&gt;</code>. This corresponds to<code>⇧⌘⌃&lt;letter&gt;</code> in macOS.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-set-key</span><span class="p">(</span><span class="nv">kbd</span><span class="s">"C-H-Z"</span><span class="p">)</span><span class="ss">'zotra-extras-add-entry</span><span class="p">)</span></span></span></code></pre></div><h3 id="tetris"><code>tetris</code></h3><p><em><a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/play/tetris.el">tetris</a> is an implementation of the classic Tetris game for Emacs.</em></p><p>And finally, the section you&rsquo;ve all been waiting for.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">use-feature</span><span class="nv">tetris</span></span></span><span class="line"><span class="cl"><span class="nb">:bind</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">:map</span><span class="nv">tetris-mode-map</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"k"</span><span class="o">.</span><span class="nv">tetris-rotate-prev</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"l"</span><span class="o">.</span><span class="nv">tetris-move-down</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">"j"</span><span class="o">.</span><span class="nv">tetris-move-left</span><span class="p">)</span></span></span><span class="line"><span class="cl"><span class="p">(</span><span class="s">";"</span><span class="o">.</span><span class="nv">tetris-move-right</span><span class="p">)))</span></span></span></code></pre></div><h2 id="appendices">appendices</h2><h3 id="key-bindings">key bindings</h3><p>Emacs has five native<a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Modifier-Keys.html">modifier keys</a>:<code>Control</code> (<code>C</code>),<code>Meta</code> (<code>M</code>),<code>Super</code> (<code>s</code>),<code>Hyper</code> (<code>H</code>), and<code>Alt</code> (<code>A</code>). (The letter abbreviation for the<code>Super</code> modifier is<code>s</code> because<code>S</code> is assigned to the<code>Shift</code> key.) I use<a href="https://karabiner-elements.pqrs.org/">Karabiner-Elements</a>, in combination with a<a href="https://www.zsa.io/moonlander/">Moonlander keyboard</a>, to generate several additional &ldquo;pseudo modifiers&rdquo;, or mappings between individual keys and combinations of two or more Emacs modifiers:</p><figure><a href="/ox-hugo/moonlander-emacs.png" target="_blank" rel="noopener"><img src="/ox-hugo/moonlander-emacs.png" alt=""/></figure><p>So when you see a monstrous key binding such as<code>C-H-M-s-d</code>, remember that everything that precedes the final key (in this case,<code>d</code>) represents a single key press (in this case,<code>l</code>). For details, see my Karabiner config file, specifically the &ldquo;Key associations&rdquo; section.</p><p>I set key bindings in the following ways:</p><ul><li>With the<code>:bind</code> keyword of<code>use-package</code>.<ul><li>For commands provided by the package or feature being loaded in that block.</li><li>For commands provided by other packages or features, when these are being set in a keymap provided by the feature being loaded in that block. This approach is appropriate when one wants to bind a key to a command in a keymap and wants this binding to be active even before the feature providing the command is loaded. Example:</li></ul></li><li>With<code>bind-keys</code> within the<code>:init</code> section of<code>use-package</code>.<ul><li>For commands provided by the feature being loaded in that block that are bound in a keymap provided by another feature. This is appropriate when the feature providing the keymap may load after the feature providing the command. In these cases, using<code>:bind</code> is not possible since Emacs will throw an error. Example: binding the command<code>scroll-down-command</code>, which is provided by<code>window</code>, to the key<code>y</code> in<code>elfeed-show-mode-map</code>, which is provided by<code>elfeed</code>. Note that if the command is not natively autoloaded, an autoload must be set, e.g.<code>(autoload #'=scroll-down-command "window" nil t)</code>. [confirm that this is so: it’s possible<code>bind-keys</code> automatically creates autoloads, just like the<code>:bind</code> keyword does]</li><li>For commands provided by the feature being loaded in that block that are bound globally and should be available even before the feature is configured. (Note that I distinguish between the loading of a feature and its configuration. A key binding specified via the<code>:bind</code> keyword of<code>use-package</code> will be available before the package is loaded but only after it is configured. If, for example, the block includes the<code>:after</code> keyword, the package will only be configured after that condition is satisfied.) Example:<code>ebib-extras-open-or-switch</code>, which is provided by<code>ebib-extras</code> and will be configured after<code>ebib</code> is loaded, yet we want it to be available even before<code>ebib</code> is loaded.</li></ul></li></ul><h3 id="profiling">profiling</h3><ul><li>If you use<code>use-package</code>, the command<code>use-package-report</code> displays a table showing the impact of each package on load times.</li></ul><h3 id="installation">installation</h3><p>For personal reference, these are the most recent Emacs installations (in reverse chronological order).</p><p>(After installing, you may need to create a symlink to the<code>Emacs.app</code> folder in<code>/opt/homebrew/Cellar/emacs-plus@30/30.1/Emacs.app</code>, replacing<code>30.1</code> with the actual version number.)</p><p><span class="timestamp-wrapper"><span class="timestamp">[2025-06-27 Fri]</span></span>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@30 --with-dbus --with-debug --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><p><span class="timestamp-wrapper"><span class="timestamp">[2024-10-09 Wed]</span></span>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@30 --with-dbus --with-debug --with-native-comp --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><p><span class="timestamp-wrapper"><span class="timestamp">[2024-03-18 Mon]</span></span>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@29 --with-dbus --with-debug --with-native-comp --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><p>???:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@30 --with-dbus --with-debug --with-native-comp --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><p><span class="timestamp-wrapper"><span class="timestamp">[2023-02-23 Thu 02:10]</span></span></p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@28 --with-dbus --with-no-titlebar --with-native-comp --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><ul><li>Very slow.</li><li>Theme broke for some reason.</li><li>Some functions (e.g.<code>keymap-unset</code>) not available).</li><li>Telega doesn&rsquo;t show profile pics</li></ul><p><span class="timestamp-wrapper"><span class="timestamp">[2023-02-14 Tue 20:07]</span></span>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew tap d12frosted/emacs-plus</span></span><span class="line"><span class="cl">brew install emacs-plus@30 --with-dbus --with-debug --with-native-comp --with-xwidgets --with-imagemagick --with-spacemacs-icon</span></span></code></pre></div><p><span class="timestamp-wrapper"><span class="timestamp">[2023-02-07 Tue 21:52]</span></span>:</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew install emacs-mac --with-dbus --with-starter --with-natural-title-bar --with-native-comp --with-mac-metal --with-xwidgets --with-imagemagick --with-librsvg --with-spacemacs-icon</span></span></code></pre></div><h3 id="other-config-files">other config files</h3><p>The below is a link dump for config files and other related links I have found useful in the past or may want to check out for ideas at some point in the future.</p><ul><li><a href="https://github.com/emacs-tw/awesome-emacs">Awesome Emacs</a>: A list of useful Emacs packages.</li><li><a href="https://sam217pa.github.io/2016/09/02/how-to-build-your-own-spacemacs/">How to build your own spacemacs · Samuel Barreto</a></li><li><a href="https://www.reddit.com/r/emacs/comments/3lt3c6/using_spacemacs_modeline_in_vanilla_emacs/">Using SpaceMacs mode-line in vanilla Emacs : emacs</a></li><li><a href="https://github.com/hlissner/doom-emacs/blob/develop/docs/faq.org#how-does-doom-start-up-so-quickly">How does Emacs Doom start so quickly?</a> Might be useful for ideas on how to speed up config file.</li><li><a href="https://prelude.emacsredux.com/en/latest/">Emacs Prelude</a>. I&rsquo;ve seen this recommended. Might want to check it out.</li><li><a href="https://www.reddit.com/r/emacs/comments/ehjcu2/screenshot_polishing_my_emacs_who_said_an_old/">Polishing my Emacs &ndash; who said an old tool can&rsquo;t look modern</a><a href="https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el">.emacs.d-oldv2/init-keymaps.el at master · mbriggs/.emacs.d-oldv2</a>. Lots of key bindings.</li></ul><p>Literate configuration</p><ul><li><a href="https://commonplace.doubleloop.net/setting-up-a-spacemacs-literate-config-file">Setting up a spacemacs literate config file</a></li><li><a href="https://www.reddit.com/r/spacemacs/comments/atuzd9/does_anyone_have_their_dotfile_redone_in_literate/">Does anyone have their dotfile redone in literate programming with babel? : spacemacs</a></li><li>Diego Zamboni,<em><a href="https://leanpub.com/lit-config">Literate configuration</a></em></li><li><a href="https://emacs.sjtackexchange.com/questions/3143/can-i-use-org-mode-to-structure-my-emacs-or-other-el-configuration-file">elisp - Can I use org-mode to structure my .emacs or other .el configuration file? - Emacs Stack Exchange</a></li></ul><p>Some useful config files:</p><ul><li><a href="https://github.com/stsquad/my-emacs-stuff">Alex Bennée</a>.</li><li><a href="https://zzamboni.org/post/my-emacs-configuration-with-commentary/">Diego Zamboni</a></li><li><a href="https://jamiecollinson.com/blog/my-emacs-config/">Jamie Collinson</a></li><li><a href="https://github.com/jethrokuan/dots/blob/master/.doom.d/config.el">Jethro Kuan</a>. Creator or<code>org-roam</code> and author of some great posts on note-taking. Not literal.</li><li><a href="https://github.com/joodie/emacs-literal-config/blob/master/emacs.org">Joost Diepenmat</a></li><li><a href="https://github.com/gjstein/emacs.d">Gregory Stein</a>. Author of the excellent<a href="http://cachestocaches.com/">Caches to Caches</a> blog.</li><li><a href="https://luca.cambiaghi.me/vanilla-emacs/readme.html">Luca Cambiaghi</a></li><li><a href="https://config.phundrak.com/emacs">Lucien Cartier-Tilet</a> (Spacemacs)</li><li><a href="https://github.com/isamert/dotfiles/blob/master/emacs/index.org">Isa Mert Gurbuz</a><ul><li>Has a cool<a href="https://isamert.net/index.html">blog</a> about org mode and other topics.</li></ul></li><li><a href="https://www.mfoot.com/blog/2015/11/22/literate-emacs-configuration-with-org-mode/">Martin Foot</a><ul><li>Has a very simple init file.</li><li><a href="https://github.com/mfoo/dotfiles/blob/master/.emacs.d/config.org">.org file</a></li></ul></li><li><a href="https://github.com/mpereira/.emacs.d">Murilo Pereira</a>.<ul><li>Very well organized. The author has also written some excellent blog posts about Emacs.</li></ul></li><li><a href="https://out-of-cheese-error.netlify.app/spacemacs-config">OutOfCheeseError</a></li><li><a href="https://protesilaos.com/dotemacs/">Protesilaos Stavrou</a><ul><li><a href="https://gitlab.com/protesilaos/dotfiles/-/blob/350ca3144c5ee868056619b9d6351fca0d6b131e/emacs/.emacs.d/emacs-init.org">here</a> is the last commit before he abandoned<code>use-package</code> and<code>straight</code></li></ul></li><li><a href="https://pages.sachachua.com/.emacs.d/Sacha.html">Sacha Chua</a>. A legend in the Emacs community.</li><li><a href="https://github.com/novoid/dot-emacs/blob/master/config.org">Karl Voit</a>.<ul><li>Author of<code>Memacs</code>, prolific blogger.</li></ul></li><li><a href="https://github.com/sriramkswamy/dotemacs">Sriram Krishnaswamy</a> (<a href="https://sriramkswamy.github.io/">website</a>)<ul><li><a href="https://sriramkswamy.github.io/dotemacs/">.org file</a></li></ul></li><li><a href="https://github.com/sfromm/emacs.d#twitter">Stephen Fromm</a>. Has an extended list of config files<a href="https://github.com/sfromm/emacs.d#inspiration">here</a>.</li><li><a href="https://tecosaur.github.io/emacs-config/config.html">Tecosaur</a></li><li><a href="https://www.tquelch.com/posts/emacs-config/#languages">Tim Quelch</a></li><li><a href="http://irfu.cea.fr/Pisp/vianney.lebouteiller/emacs.html#orgbcdc8b2">Vianney Lebouteiller</a></li><li><a href="https://github.com/bixuanzju/emacs.d/blob/master/emacs-init.org#meta">Xuan Bi</a>.</li><li><a href="https://github.com/turbana/emacs-config">GitHub - turbana/emacs-config: My personal emac&rsquo;s configuration</a>. Some potentially useful stuff on native comp, debugging, etc.</li><li><a href="https://github.com/creichert/dotfiles/blob/master/emacs/.emacs">dotfiles/.emacs at master · creichert/dotfiles · GitHub</a>. Has detailed Gnus, Slack config.</li><li><a href="https://github.com/ianpan870102/yay-evil-emacs">yay-evil-emacs</a>. slick design.</li><li><a href="https://github.com/rememberYou/.emacs.d">GitHub - rememberYou/.emacs.d: 🎉 Personal GNU Emacs configuration</a>. Has a bunch of Reddit posts explaining how he uses the different packages.</li><li><a href="https://github.com/nkicg6/emacs-config/blob/master/config.org">emacs-config/config.org at master · nkicg6/emacs-config · GitHub</a>. Found it while searching for org-ref.</li><li><a href="https://github.com/yiufung/dot-emacs/blob/master/init.el">dot-emacs/init.el at master · yiufung/dot-emacs · GitHub</a>. Not literal. Lots of packages. Gnus, notmuch, Slack, etc. Author has great post on Anki.</li><li><a href="https://github.com/tshu-w/.emacs.d">GitHub - tshu-w/.emacs.d: My personal Emacs config, based on Spacemacs</a>. Has nice note-taking config, with org-roam, org-ref, Zotero, etc (see<a href="https://github.com/tshu-w/.emacs.d/blob/master/lisp/lang-org.el">here</a>).</li><li><a href="https://github.com/raxod502/radian/blob/e3aad124c8e0cc870ed09da8b3a4905d01e49769/emacs/radian.el">Radon Rosborough</a>. Author of<code>straight</code> package manager.</li><li><a href="https://github.com/weirdNox/dotfiles/blob/master/config/.config/emacs/config.org">Gonçalo Santos</a>. Author of<code>org-noter</code>.</li><li><a href="https://github.com/tonyaldon/emacs.d/blob/master/init.el">Tony Aldon</a>. Has some slick<a href="https://www.youtube.com/channel/UCQCrbWOFRmFYqoeou0Qv3Kg">videos</a> on<code>org-table</code>. Optimized key bindings.</li><li><a href="https://github.com/progfolio/.emacs.d/blob/master/init.org">Nicholas Vollmer</a>. Maitantainer of<code>elpaca</code>. I copied his<code>org-habits</code> config. Haven&rsquo;t yet looked at the rest but looks like there&rsquo;s plenty of valuable material.</li><li><a href="https://github.com/yantar92/emacs-config/blob/master/config.org">emacs-config/config.org at master · yantar92/emacs-config · GitHub</a>. Focus on knowledge management with org. Lots of good stuff.</li><li><a href="https://github.com/xenodium/dotsies/blob/main/dots.org">Álvaro Ramírez</a>. Also users Karabiner.</li><li><a href="https://github.com/karthink/.emacs.d">Karthik Chikmagalur</a>. Has excellent blog posts on<code>avy</code>,<code>eshell</code>,<code>re-builder</code>, etc.</li><li><a href="https://github.com/iqbalansari/dotEmacs">Iqbal Ansari</a>.</li><li><a href="https://www.danielclemente.com/emacs/confi.html">Daniel Clemente</a>.</li><li><a href="https://github.com/patrl">Patrick Elliott</a></li></ul>
]]></description></item><item><title>My keyboard setup</title><link>https://stafforini.com/notes/my-keyboard-setup/</link><pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/my-keyboard-setup/</guid><description>&lt;![CDATA[<p>This is a<a href="https://en.wikipedia.org/wiki/Literate_programming">literate</a> configuration for my keyboard setup: a pair of split mechanical keyboards combined with an extensive software remapping layer on macOS. The system gives me access to symbols, diacritics, navigation, deletion commands, app launching, media controls, and more—all without leaving the home row.</p><p>The configuration has two layers:</p><ol><li><strong>Keyboard firmware</strong> (QMK): maps the thumb keys to specific modifier keycodes (see<a href="#firmware-configuration">firmware configuration</a>). Everything else on the keyboard stays as standard QWERTY.</li><li><strong>Karabiner + Goku</strong>: handles all the complex behavior—dual-function keys (tap vs. hold), simlayers, app-specific rules, Unicode character input, and deep Emacs integration.</li></ol><p>This separation keeps the firmware simple and portable: the same Karabiner configuration works with both of my keyboards, and could work with any keyboard that sends the right modifier keycodes from its thumb keys.</p><h2 id="hardware">Hardware</h2><p>I alternate between two split keyboards:</p><ul><li><strong><a href="https://github.com/foostan/crkbd">Corne</a></strong> (crkbd): a 3x5+3 split keyboard—three rows of five keys per side, plus three thumb keys per side. 36 keys total.</li><li><strong><a href="https://www.zsa.io/moonlander">ZSA Moonlander</a></strong>: a larger split keyboard with a full alpha block, number row, and a thumb cluster. I use only the alpha keys and thumb cluster; the rest is inert.</li></ul><p>Both run<a href="https://qmk.fm/">QMK</a> firmware. The Corne uses the<code>corne_rotated</code> variant with the<code>LAYOUT_split_3x5_3</code> matrix.</p><p>I use the same layout on the built-in MacBook keyboard. The six keys on the bottom row—left control, left option, left command, space, right command, and right option—correspond to the six thumb keys from left to right. No firmware configuration is needed: these keys already send the expected keycodes natively.</p><h2 id="firmware-configuration">Firmware configuration</h2><p>The firmware does almost nothing. The alpha keys are standard QWERTY, and the six thumb keys send modifier keycodes:</p><table><thead><tr><th>Position</th><th>Keycode</th><th>VIA name</th><th>QMK equivalent</th></tr></thead><tbody><tr><td>Left outer</td><td><code>left_control</code></td><td>Left Ctrl</td><td><code>KC_LCTL</code></td></tr><tr><td>Left middle</td><td><code>left_option</code></td><td>Left Alt</td><td><code>KC_LALT</code></td></tr><tr><td>Left inner</td><td><code>left_command</code></td><td>Left Win</td><td><code>KC_LGUI</code></td></tr><tr><td>Right inner</td><td><code>spacebar</code></td><td>Space</td><td><code>KC_SPC</code></td></tr><tr><td>Right middle</td><td><code>right_command</code></td><td>Right Win</td><td><code>KC_RGUI</code></td></tr><tr><td>Right outer</td><td><code>right_option</code></td><td>Right Alt</td><td><code>KC_RALT</code></td></tr></tbody></table><p>These keycodes don&rsquo;t do what their names suggest. They&rsquo;re just handles for Karabiner to intercept and redefine. The actual behavior of each key is determined entirely in software (see<a href="#individual-bindings">individual bindings</a>).</p><h2 id="setup-steps">Setup steps</h2><h3 id="step-1-configure-the-keyboard-firmware">Step 1: configure the keyboard firmware</h3><p>If you have a normal keyboard (no programmable thumb keys), skip to step 2. The MacBook&rsquo;s built-in keyboard already sends the right keycodes from its bottom-row modifier keys, so no firmware step is needed.</p><p>If you have a split or ergonomic keyboard with programmable thumb keys, use the keyboard&rsquo;s firmware to map the thumb keys as follows. The alpha keys should remain standard QWERTY; only the thumb keys need to be changed.</p><table><thead><tr><th>position</th><th>keycode to send</th><th>VIA name</th><th>QMK equivalent</th></tr></thead><tbody><tr><td>left outer</td><td><code>left_control</code></td><td>Left Ctrl</td><td><code>KC_LCTL</code></td></tr><tr><td>left middle</td><td><code>left_option</code></td><td>Left Alt</td><td><code>KC_LALT</code></td></tr><tr><td>left inner</td><td><code>left_command</code></td><td>Left Win</td><td><code>KC_LGUI</code></td></tr><tr><td>right inner</td><td><code>spacebar</code></td><td>Space</td><td><code>KC_SPC</code></td></tr><tr><td>right middle</td><td><code>right_command</code></td><td>Right Win</td><td><code>KC_RGUI</code></td></tr><tr><td>right outer</td><td><code>right_option</code></td><td>Right Alt</td><td><code>KC_RALT</code></td></tr></tbody></table><p><strong>Option A: VIA</strong> (easiest, no install required):</p><ol><li>Open<a href="https://usevia.app">usevia.app</a> in Chrome (requires WebHID support).</li><li>Plug in the keyboard via USB. It should auto-detect; if not, your keyboard may need VIA support enabled in its firmware, or you may need to load a JSON definition file from the manufacturer.</li><li>Click on each thumb key and assign the keycodes shown above. In VIA&rsquo;s keycode picker, they are labeled Left Ctrl, Left Alt, Left Win, Space, Right Win, and Right Alt.</li><li>Changes take effect immediately—no compiling or flashing needed.</li><li>For split keyboards, only one half needs to be connected via USB; the other half communicates via the TRRS cable.</li></ol><p><strong>Option B: QMK Configurator</strong> (if VIA is not supported):</p><ol><li>Go to<a href="https://config.qmk.fm">QMK Configurator</a> and select your keyboard.</li><li>Set the alpha keys to standard QWERTY and the thumb keys as shown above (QMK uses PC naming: Alt = Option, GUI = Command).</li><li>You do not need any firmware layers—Karabiner handles everything.</li><li>Click &ldquo;Compile&rdquo;, then &ldquo;Download firmware&rdquo; to get the<code>.hex</code> file.</li><li>Install<a href="https://github.com/qmk/qmk_toolbox">QMK Toolbox</a> (<code>brew install --cask qmk-toolbox</code>).</li><li>Open QMK Toolbox, load the<code>.hex</code> file, and enable &ldquo;Auto-Flash&rdquo;.</li><li>Put the keyboard into bootloader mode (typically by double-tapping the reset button on the controller). QMK Toolbox should print &ldquo;Caterina device connected&rdquo; (for Pro Micro) or &ldquo;DFU device connected&rdquo; (for Elite-C) and begin flashing automatically.</li><li>For split keyboards,<strong>flash each half separately</strong>: connect USB to one half at a time (without the TRRS cable), flash it, then do the same for the other half. Only one half should be connected to the computer via USB during normal use; the two halves communicate via the TRRS cable.</li></ol><p>Once configured, verify the keyboard appears in Karabiner-Elements &gt; Devices and that its vendor ID matches the<code>:devices</code> section of this config.</p><h3 id="step-2-install-karabiner-and-goku">Step 2: install Karabiner and Goku</h3><ol><li>Install<a href="https://karabiner-elements.pqrs.org/">Karabiner-Elements</a>.</li><li>Install<a href="https://github.com/yqrashawn/GokuRakuJoudo">Goku</a>.</li><li>Clone this repo and load the config in<code>dotfiles/karabiner/karabiner.edn</code>.</li></ol><h2 id="individual-bindings">Individual bindings</h2><p>Every thumb key has two roles: one when tapped, another when held. These roles change depending on whether the active application is Emacs.</p><h4 id="in-emacs">In Emacs</h4><table><thead><tr><th>Thumb key</th><th>Tap</th><th>Hold</th><th>Emacs modifier</th></tr></thead><tbody><tr><td><code>left_control</code></td><td><code>C-g</code> (quit)</td><td><code>M-</code></td><td>Meta</td></tr><tr><td><code>left_option</code></td><td><code>RET</code></td><td><code>S-</code></td><td>Shift</td></tr><tr><td><code>left_command</code></td><td><code>C-H-0</code> (toggle windows)</td><td><code>H-</code></td><td>Hyper</td></tr><tr><td><code>spacebar</code></td><td><code>⌘Tab</code> (toggle apps)</td><td><code>C-</code></td><td>Control</td></tr><tr><td><code>right_command</code></td><td><code>SPC</code></td><td><code>A-</code></td><td>Alt (in combos)</td></tr><tr><td><code>right_option</code></td><td><code>TAB</code></td><td><code>s-</code></td><td>Super</td></tr></tbody></table><p>The<code>right_command</code> key is special: on its own it always sends spacebar (both tapped and held), but when held simultaneously with another thumb key, it activates the<code>A-</code> (Alt) modifier in Emacs. The five combinations are:</p><table><thead><tr><th>Combination</th><th>Emacs modifier</th></tr></thead><tbody><tr><td><code>right_command</code> +<code>left_command</code></td><td><code>A-H-</code></td></tr><tr><td><code>right_command</code> +<code>left_option</code></td><td><code>A-</code></td></tr><tr><td><code>right_command</code> +<code>spacebar</code></td><td><code>A-C-</code></td></tr><tr><td><code>right_command</code> +<code>left_control</code></td><td><code>A-M-</code></td></tr><tr><td><code>right_command</code> +<code>right_option</code></td><td><code>A-s-</code></td></tr></tbody></table><p>With six independent Emacs modifiers (<code>A-</code>,<code>C-</code>,<code>H-</code>,<code>M-</code>,<code>S-</code>,<code>s-</code>), I have a vast keybinding space. Multi-modifier combinations like<code>A-C-H-M-s-</code> (all five non-Shift modifiers at once) are possible and used in practice, giving me access to thousands of unique Emacs bindings from a 36-key keyboard.</p><p>The simlayers extend this further. Each simlayer key, when held, maps to a specific multi-modifier combination in Emacs. For example, holding<code>,</code> activates the<code>A-H-M-</code> prefix, so<code>,</code> +<code>s</code> sends<code>A-H-M-s</code> (bound to<code>simple-extras-transpose-chars-backward</code>). This turns each simlayer into a dedicated command palette:</p><table><thead><tr><th>Simlayer key</th><th>Emacs modifier</th><th>Function</th></tr></thead><tbody><tr><td><code>b</code></td><td><code>C-H-</code></td><td>Window sizing</td></tr><tr><td><code>j</code></td><td><code>C-H-M-</code></td><td>Deletion</td></tr><tr><td><code>x</code></td><td><code>C-H-s-</code></td><td>Avy jump</td></tr><tr><td><code>z</code></td><td><code>A-C-s-</code></td><td>Cursor movement</td></tr><tr><td><code>,</code></td><td><code>A-H-M-</code></td><td>Transposition</td></tr><tr><td><code>.</code></td><td><code>A-C-H-</code></td><td>Text manipulation</td></tr><tr><td><code>/</code></td><td><code>C-H-M-s-</code></td><td>Org-mode commands</td></tr></tbody></table><p>The remaining simlayers (<code>k</code>,<code>m</code>,<code>p</code>,<code>q</code>,<code>v</code>,<code>y</code>,<code>;</code>) don&rsquo;t use Emacs modifier prefixes—they insert characters directly or control the mouse.</p><h4 id="outside-emacs">Outside Emacs</h4><table><thead><tr><th>Thumb key</th><th>Tap</th><th>Hold</th></tr></thead><tbody><tr><td><code>left_control</code></td><td><code>Escape</code></td><td><code>⌥</code></td></tr><tr><td><code>left_option</code></td><td><code>Enter</code></td><td><code>⇧</code></td></tr><tr><td><code>left_command</code></td><td><code>⌘⌃0</code> (toggle tabs)</td><td><code>⌘</code></td></tr><tr><td><code>spacebar</code></td><td><code>⌘Tab</code> (toggle apps)</td><td><code>⌃</code></td></tr><tr><td><code>right_command</code></td><td><code>Spacebar</code></td><td>&mdash;</td></tr><tr><td><code>right_option</code></td><td><code>Tab</code></td><td><code>⌥</code></td></tr></tbody></table><p>The<code>spacebar</code> key also has a combination effect outside Emacs: pressing<code>left_command</code> +<code>spacebar</code> triggers<code>⌘`</code> (move focus to next window of the current app—e.g. the next browser window if more than one window is open).</p><h3 id="left-control"><code>left_control</code></h3><p>Tapped:<code>C-g</code> (quit) in Emacs,<code>Escape</code> outside. Held:<code>M-</code> (Meta) in Emacs,<code>Option</code> outside. Two special rules intercept<code>⌘h</code> and<code>⌘⌥h</code> (which macOS normally uses to hide windows) and remap them to Emacs-compatible modifier chords.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"left_control → C-g/Escape (alone) | M-/⌥ (held)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:!Ch</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-s-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:!CQh</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-s-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_control</span><span class="ss">:M-</span><span class="p">[</span><span class="ss">:!steam</span><span class="ss">:emacs</span><span class="p">]</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_control</span><span class="err">:⌥</span><span class="p">[</span><span class="ss">:!steam</span><span class="ss">:!emacs</span><span class="p">]</span><span class="p">{</span><span class="ss">:alone</span><span class="ss">:escape</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="left-option"><code>left_option</code></h3><p>Tapped:<code>return</code> (which I bind to toggling between recent windows or tabs). Held:<code>S-</code> (Shift) in Emacs,<code>Shift</code> outside. Since this key now serves double duty as both Shift and Return, the combination<code>Shift+Return</code> is no longer directly available. A workaround binds<code>left_option</code> +<code>right_command</code> (i.e. Shift + spacebar) to<code>Shift+Enter</code>.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"left_option → RET (alone) | S-/⇧ (held)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_option</span><span class="ss">:S-</span><span class="ss">:emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="ss">:return_or_enter</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_option</span><span class="err">:⇧</span><span class="ss">:!emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="ss">:return_or_enter</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:!Sright_command</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧</span><span class="ss">:key</span><span class="ss">:return_or_enter</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="left-command"><code>left_command</code></h3><p>When tapped, toggles between the two most recent windows (in Emacs) or tabs (in a browser). In Emacs,<code>C-H-0</code> is bound to<code>window-extras-switch-to-last-window</code>. In Chrome and Firefox, I use the<a href="https://chrome.google.com/webstore/detail/clut-cycle-last-used-tabs/cobieddmkhhnbeldhncnfcgcaccmehgn">CLUT</a> and<a href="https://addons.mozilla.org/en-US/firefox/addon/last-tab/?utm_source=addons.mozilla.org&amp;utm_medium=referral&amp;utm_content=search">Last Tab</a> extensions with<code>⌘⌃0</code> as the shortcut.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"left_command → other window/tab (alone) | H-/⌘ (held)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_command</span><span class="ss">:H-</span><span class="ss">:emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-</span><span class="ss">:key</span><span class="ss">:0</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">left_command</span><span class="err">:⌘</span><span class="ss">:!emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘⌃</span><span class="ss">:key</span><span class="ss">:0</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="spacebar"><code>spacebar</code></h3><p>Tapped:<code>⌘Tab</code> (switch apps). Held:<code>C-</code> (Control) in Emacs,<code>⌃</code> outside. When tapped while the command key is held, toggles between buffers (in Emacs) or moves focus to the next window (outside Emacs).</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"spacebar → ⌘Tab (alone) | C-/⌃ (held)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:!Cspacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-s-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">spacebar</span><span class="ss">:C-</span><span class="ss">:emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:!Cspacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:grave_accent_and_tilde</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">spacebar</span><span class="err">:⌃</span><span class="ss">:!emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="right-command"><code>right_command</code></h3><p>On its own,<code>right_command</code> always sends spacebar&mdash;both tapped and held, both in and outside Emacs. Its special role is as a modifier<em>combiner</em>: when held simultaneously with another thumb key in Emacs, it activates the<code>A-</code> (Alt) modifier, creating two-modifier chords. This is what gives me access to the sixth Emacs modifier without a dedicated physical key for it.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"right_command modifier combinations"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="ss">:right_command</span><span class="ss">:left_command</span><span class="p">]</span><span class="ss">:A-H-</span><span class="ss">:emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="ss">:right_command</span><span class="ss">:left_option</span><span class="p">]</span><span class="ss">:A-</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="ss">:right_command</span><span class="ss">:spacebar</span><span class="p">]</span><span class="ss">:A-C-</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="ss">:right_command</span><span class="ss">:left_control</span><span class="p">]</span><span class="ss">:A-M-</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="ss">:right_command</span><span class="ss">:right_option</span><span class="p">]</span><span class="ss">:A-s-</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"right_command → spacebar"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">right_command</span><span class="ss">:spacebar</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="right-option"><code>right_option</code></h3><p>Tapped:<code>Tab</code>. Held:<code>s-</code> (Super) in Emacs,<code>Option</code> outside.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"right_option → Tab (alone) | s-/⌥ (held)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">right_option</span><span class="ss">:s-</span><span class="ss">:emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="ss">:tab</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">right_option</span><span class="err">:⌥</span><span class="ss">:!emacs</span><span class="p">{</span><span class="ss">:alone</span><span class="ss">:tab</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="mouse">mouse</h3><p>My Logitech MX Anywhere 3S mouse does not have a<a href="https://computer.howstuffworks.com/mouse11.htm">tilting wheel</a>, so I remap the side buttons to trigger the relevant tab navigation shortcuts when pressed while the shift key is held.</p><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"left_shift + side mouse buttons → navigate open tabs"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span></span></span><span class="line"><span class="cl"><span class="p">[{</span><span class="ss">:pkey</span><span class="ss">:button4</span><span class="ss">:modi</span><span class="ss">:left_shift</span><span class="p">}</span><span class="ss">:!COleft_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[{</span><span class="ss">:pkey</span><span class="ss">:button5</span><span class="ss">:modi</span><span class="ss">:left_shift</span><span class="p">}</span><span class="ss">:!COright_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><p>Note that for these “extra” mouse buttons to be detected by Karabiner, you may need to enable the relevant device in the “Devices” section.</p><h2 id="layers">Layers</h2><p>Simlayers are the most distinctive feature of this setup. A simlayer activates when you hold down a specific key and press another key simultaneously. Unlike traditional layers that require a dedicated layer-switch key, simlayers let any regular typing key double as a layer trigger—the key still types its letter on a normal tap, but holding it down and pressing a second key activates the layer.</p><p>I have 14 simlayers, each triggered by a different home-row or common key. The letter keys used as triggers are chosen from the least frequent letters in English, minimizing accidental activations during normal typing:</p><table><thead><tr><th>Key</th><th>Frequency</th><th>Function</th></tr></thead><tbody><tr><td><code>z</code></td><td>0.074%</td><td>Navigation</td></tr><tr><td><code>q</code></td><td>0.095%</td><td>App launcher</td></tr><tr><td><code>x</code></td><td>0.15%</td><td>Avy jump</td></tr><tr><td><code>j</code></td><td>0.15%</td><td>Deletion</td></tr><tr><td><code>k</code></td><td>0.77%</td><td>Special chars</td></tr><tr><td><code>v</code></td><td>0.98%</td><td>Numbers</td></tr><tr><td><code>b</code></td><td>1.5%</td><td>Media/windows</td></tr><tr><td><code>p</code></td><td>1.9%</td><td>Diacritics</td></tr><tr><td><code>y</code></td><td>2.0%</td><td>Mouse/screenshots</td></tr><tr><td><code>m</code></td><td>2.4%</td><td>Math symbols</td></tr></tbody></table><p>(Source:<a href="https://en.wikipedia.org/wiki/Letter_frequency">English letter frequency on Wikipedia</a>.)</p><p>The remaining four simlayers use punctuation keys:<code>,</code> (transposition),<code>.</code> (text manipulation),<code>;</code> (symbols), and<code>/</code> (Org-mode).</p><figure><a href="/images/keyboard/base.svg" target="_blank" rel="noopener"><img src="/images/keyboard/base.svg" alt=""/></figure><h3 id="b-mode-media-windows"><code>b-mode</code>: media/windows</h3><p>Hold<code>b</code> for media controls and window sizing. The right-hand top row keys control window placement (via Emacs Lisp commands in Emacs, or via<a href="https://github.com/rxhanson/Rectangle">Rectangle</a> otherwise), the home row keys control playback, and the bottom row keys control volume.<code>h</code> and<code>n</code> control dictation and narration, respectively (the keyboard shortcuts need to be set under Settings &gt; Keyboard &gt; Dictation &gt; Shortcut for dictation, and Settings &gt; Accessibility &gt; Spoken content &gt; Speak selection for narration).</p><figure><a href="/images/keyboard/b-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/b-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"b-mode (media controls, window sizing)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:b-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="ss">:rewind</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌃</span><span class="ss">:key</span><span class="ss">:3</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="ss">:play_or_pause</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="ss">:fast_forward</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="ss">:volume_increment</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="ss">:volume_decrement</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="ss">:mute</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-M-s-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-M-s-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:0</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌥⌃</span><span class="ss">:key</span><span class="ss">:1</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="k-mode-special-characters"><code>k-mode</code>: special characters</h3><p>Hold<code>k</code> to type characters from various European languages and typographic symbols (eth, thorn, sharp s, guillemets, interrobang, etc.).</p><figure><a href="/images/keyboard/k-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/k-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"k-mode (special chars)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:k-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="ss">:ð</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="err">:…</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="err">:¿</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"⸘"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"‽"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="ss">:ø</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="err">:£</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="ss">:œ</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="err">:€</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="ss">:ß</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="ss">:þ</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="err">:•</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="err">:¡</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="err">:«</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="err">:»</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="j-mode-deletion"><code>j-mode</code>: deletion</h3><p>Hold<code>j</code> for deletion commands. Outside Emacs, the keys map to standard macOS editing shortcuts (e.g.<code>s</code> for backspace,<code>d</code> for delete forward,<code>q</code> for delete word backward,<code>w</code> for delete to line start,<code>e</code> for delete to line end). In Emacs, each key triggers a dedicated deletion function via the<code>C-H-M-</code> modifier prefix, covering characters, words, sentences, sexps, and more.</p><figure><a href="/images/keyboard/j-mode-emacs.svg" target="_blank" rel="noopener"><img src="/images/keyboard/j-mode-emacs.svg" alt=""/></figure><figure><a href="/images/keyboard/j-mode-macos.svg" target="_blank" rel="noopener"><img src="/images/keyboard/j-mode-macos.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"j-mode (deletion)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:j-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:a</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="ss">:delete_or_backspace</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="ss">:delete_forward</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:q</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:delete_or_backspace</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:delete_or_backspace</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌃</span><span class="ss">:key</span><span class="ss">:k</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:delete_forward</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:z</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:delete_or_backspace</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:x</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘⌥</span><span class="ss">:key</span><span class="ss">:left_arrow</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘⌥</span><span class="ss">:key</span><span class="ss">:right_arrow</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:delete_forward</span><span class="p">}</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="ss">:home</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="ss">:end</span><span class="ss">:!emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="m-mode-math-symbols"><code>m-mode</code>: math symbols</h3><p>Hold<code>m</code> for mathematical operators. Some of these characters have native Option+key shortcuts on the ABC Extended input source. The rest are inserted via a shell command that copies the character to the clipboard and pastes it with<code>⌘V</code>. This means that using them will overwrite whatever is currently on the clipboard.</p><figure><a href="/images/keyboard/m-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/m-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"m-mode (math symbols)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:m-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="ss">:=</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="ss">:+</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="err">:≠</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="err">:÷</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="err">:±</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"×"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="err">:≤</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="err">:≥</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"≈"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"∞"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"−"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="err">:·</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="err">:°</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"√"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">[</span><span class="ss">:insert</span><span class="s">"π"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="p-mode-diacritics"><code>p-mode</code>: diacritics</h3><p>Hold<code>p</code> to add a diacritical mark to the next character you type. This uses macOS&rsquo;s &ldquo;ABC - Extended&rdquo; input source. For example, typing<code>p</code> +<code>e</code> then<code>e</code> produces é; typing<code>p</code> +<code>u</code> then<code>o</code> produces ö.</p><figure><a href="/images/keyboard/p-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/p-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"p-mode (diacritics)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:p-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="ss">:macron</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="ss">:breve</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="ss">:cedilla</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="ss">:accute_accent</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="ss">:undercomma</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="ss">:underbar</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="ss">:horn</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="ss">:double_acute_accent</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="ss">:overring</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="ss">:stroke</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="ss">:ogonek</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="ss">:tilde_accent</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="ss">:grave_accent</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="ss">:umlaut</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="ss">:caron</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="ss">:underdot</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="ss">:overdot</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="ss">:circumflex</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="ss">:hook</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="q-mode-apps"><code>q-mode</code>: apps</h3><p>Hold<code>q</code> to open an application. 20+ applications are mapped. The letter choices are mnemonic where possible (e.g.<code>e</code> for Emacs,<code>f</code> for Firefox,<code>t</code> for Terminal).</p><figure><a href="/images/keyboard/q-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/q-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"q-mode (apps)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:q-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/qBitTorrent.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Audacity.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/System/Library/CoreServices/Finder.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Emacs.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Firefox.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/GoldenDict-ng.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Google Chrome.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Anki.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/System/Applications/System Settings.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/DeepL.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Media Center 29.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/zoom.us.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Beeper Desktop.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Karabiner-Elements.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Slack.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/System/Applications/Utilities/Terminal.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/mpv.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/HoudahSpot.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Plex Media Server.app/"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Spotify.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Home Assistant.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Tor Browser.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="p">[</span><span class="ss">:open</span><span class="s">"/Applications/Safari.app"</span><span class="p">]]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="v-mode-numbers"><code>v-mode</code>: numbers</h3><p>Hold<code>v</code> to turn the right hand into a numpad. This is one of the most-used simlayers—on a 36-key keyboard with no number row, this is how I type numbers.</p><figure><a href="/images/keyboard/v-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/v-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"v-mode (numbers)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:v-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="ss">:8</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">i</span><span class="err">:</span><span class="o">##</span><span class="mi">8</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="ss">:4</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">j</span><span class="ss">:4</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="ss">:5</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">k</span><span class="ss">:5</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="ss">:6</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">l</span><span class="ss">:6</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="ss">:1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">m</span><span class="ss">:1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="ss">:9</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">o</span><span class="ss">:9</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="ss">:7</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">u</span><span class="ss">:7</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="ss">:2</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">comma</span><span class="ss">:2</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="ss">:3</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">period</span><span class="ss">:3</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="ss">:0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">p</span><span class="ss">:0</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="ss">:period</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">semicolon</span><span class="ss">:period</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="x-mode-avy"><code>x-mode</code>: avy</h3><p>Hold<code>x</code> to trigger<a href="https://github.com/abo-abo/avy">Avy</a> jump commands in Emacs (this simlayer is Emacs-only). Each key maps to a unique Avy command via the<code>C-H-s-</code> modifier prefix, providing instant, keyboard-driven navigation to any visible position in the buffer.</p><figure><a href="/images/keyboard/x-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/x-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"x-mode (avy)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:x-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:a</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:j</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:k</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:l</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:m</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:q</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:y</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:z</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:semicolon</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:comma</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:period</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:slash</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:return_or_enter</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:return_or_enter</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:tab</span><span class="p">[{</span><span class="ss">:modi</span><span class="ss">:C-H-s-</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}]]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="y-mode-mouse-screenshots"><code>y-mode</code>: mouse/screenshots</h3><p>Hold<code>y</code> to move the mouse cursor with the keyboard (<code>a</code> and<code>f</code> for left/right,<code>s</code> and<code>d</code> for up/down,<code>q</code> and<code>r</code> and<code>w</code> and<code>e</code> for larger jumps) or take screenshots (<code>z</code> for full screen,<code>c</code> for selected area,<code>v</code> to copy selected area to clipboard).<code>Enter</code> and<code>Space</code> act as left and right click.</p><figure><a href="/images/keyboard/y-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/y-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"y-mode (mouse, screenshots)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:y-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘</span><span class="ss">:key</span><span class="ss">:5</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘</span><span class="ss">:key</span><span class="ss">:4</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:y</span><span class="mi">1500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:y</span><span class="mi">4500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:x</span><span class="mi">-1500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:x</span><span class="mi">1500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:x</span><span class="mi">-4500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:x</span><span class="mi">4500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:y</span><span class="mi">-1500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘⌃</span><span class="ss">:key</span><span class="ss">:4</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:mkey</span><span class="p">{</span><span class="ss">:y</span><span class="mi">-4500</span><span class="p">}}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⇧⌘</span><span class="ss">:key</span><span class="ss">:3</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:right_command</span><span class="ss">:button2</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:return_or_enter</span><span class="ss">:button1</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="z-mode-navigation"><code>z-mode</code>: navigation</h3><p>Hold<code>z</code> for cursor movement. The four arrow keys sit on the home row:<code>j</code> (left),<code>k</code> (up),<code>l</code> (down),<code>;</code> (right). This is inspired by Vim&rsquo;s<code>h-j-k-l</code>, with two modifications. First, the cluster is shifted one key to the right so that it aligns with the natural resting position of the four fingers. Second, up and down are swapped:<code>k</code> is up and<code>l</code> is down, placing up next to left and down next to right. This grouping works better for movement commands that can be conceptualized as either horizontal or vertical—for example, &ldquo;sentence backward&rdquo; is both &ldquo;up&rdquo; and &ldquo;left,&rdquo; while &ldquo;sentence forward&rdquo; is both &ldquo;down&rdquo; and &ldquo;right.&rdquo;</p><p>Beyond the arrow keys,<code>y</code> and<code>h</code> provide page up/down and<code>m</code> and<code>/</code> provide home/end. In Emacs, the keys trigger custom navigation commands via the<code>A-C-s-</code> modifier prefix, enabling more granular movement (by paragraph, sentence, defun, etc.). The<code>##</code> prefix on some keys allows shift to be held for selection.</p><figure><a href="/images/keyboard/z-mode-emacs.svg" target="_blank" rel="noopener"><img src="/images/keyboard/z-mode-emacs.svg" alt=""/></figure><figure><a href="/images/keyboard/z-mode-macos.svg" target="_blank" rel="noopener"><img src="/images/keyboard/z-mode-macos.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"z-mode (navigation)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:z-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-s-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">[{</span><span class="ss">:modi</span><span class="err">:⌘⌃</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘⌃</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}]</span><span class="ss">:chrome</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">h</span><span class="ss">:page_down</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">i</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:up_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="ss">:left_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">j</span><span class="ss">:left_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="ss">:up_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">k</span><span class="ss">:up_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="ss">:down_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">l</span><span class="ss">:down_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:m</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">m</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:left_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">o</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:down_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">p</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:right_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">[{</span><span class="ss">:modi</span><span class="err">:⌘⌃</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘⌃</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}]</span><span class="ss">:chrome</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">u</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌥</span><span class="ss">:key</span><span class="ss">:left_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:x</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:y</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">y</span><span class="ss">:page_up</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:up_arrow</span><span class="p">}</span><span class="ss">:chrome</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="ss">:home</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:comma</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">comma</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:up_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:period</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">period</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:down_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:right_command</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:right_command</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:down_arrow</span><span class="p">}</span><span class="ss">:chrome</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:right_command</span><span class="ss">:end</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="ss">:right_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">semicolon</span><span class="ss">:right_arrow</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:slash</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">slash</span><span class="p">{</span><span class="ss">:modi</span><span class="err">:⌘</span><span class="ss">:key</span><span class="ss">:right_arrow</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:tab</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-s-</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="c1">;; [:##tab :home]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="mode-transposition"><code>,-mode</code>: transposition</h3><p>Hold<code>,</code> to trigger transposition commands in Emacs (transpose characters, words, lines, sentences, paragraphs, sexps, etc.) via the<code>A-H-M-</code> modifier prefix. This simlayer is Emacs-only.</p><figure><a href="/images/keyboard/comma-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/comma-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"comma-mode (transposition)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:comma-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:a</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:j</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:l</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:q</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:x</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:y</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:z</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:semicolon</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:period</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:slash</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:return_or_enter</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:return_or_enter</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:tab</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-</span><span class="ss">:key</span><span class="ss">:tab</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="dot-mode-text-manipulation"><code>.-mode</code>: text manipulation</h3><p>Hold<code>.</code> to trigger text manipulation commands (sorting, aligning, casing, commenting, etc.) via the<code>A-C-H-</code> modifier prefix.</p><figure><a href="/images/keyboard/period-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/period-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"period-mode (manipulation)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:period-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:a</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:j</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:k</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:k</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:l</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:l</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:m</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-H-M-s-</span><span class="ss">:key</span><span class="ss">:9</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:x</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:y</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:z</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:semicolon</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:semicolon</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:comma</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:comma</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:slash</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:slash</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:spacebar</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:spacebar</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:return_or_enter</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:A-C-H-</span><span class="ss">:key</span><span class="ss">:return_or_enter</span><span class="p">}]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="mode-symbols"><code>;-mode</code>: symbols</h3><p>Hold<code>;</code> for symbols that would normally require Shift + number row (e.g.<code>!@#$%^&amp;*</code>), as well as brackets, braces, quotes, backtick, tilde, en-dash, and em-dash. This eliminates the need for a number row to access these characters.</p><figure><a href="/images/keyboard/semicolon-mode.svg" target="_blank" rel="noopener"><img src="/images/keyboard/semicolon-mode.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"semicolon (symbols)"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:semicolon-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">a</span><span class="ss">:percent_sign</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">b</span><span class="ss">:grave_accent_and_tilde</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">c</span><span class="ss">:open_bracket</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">d</span><span class="ss">:close_parenthesis</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">e</span><span class="ss">:number_sign</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">f</span><span class="ss">:asterisk</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">g</span><span class="ss">:caret</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">h</span><span class="ss">:ampersand</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">i</span><span class="ss">:open_single_quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">j</span><span class="ss">:double_quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">k</span><span class="ss">:open_double_quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">l</span><span class="ss">:close_double_quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">m</span><span class="ss">:hyphen</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">n</span><span class="ss">:tilde</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">o</span><span class="ss">:close_single_quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">q</span><span class="ss">:exclamation_mark</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">r</span><span class="ss">:dollar_sign</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">s</span><span class="ss">:open_parenthesis</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">t</span><span class="ss">:backslash</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">u</span><span class="ss">:quote</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">v</span><span class="ss">:close_bracket</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">w</span><span class="ss">:at_sign</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">x</span><span class="ss">:close_brace</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">y</span><span class="ss">:vertical_bar</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">z</span><span class="ss">:open_brace</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">comma</span><span class="ss">:en_dash</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">period</span><span class="ss">:em_dash</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">:</span><span class="o">##</span><span class="nv">right_command</span><span class="ss">:underscore</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h3 id="mode-org-mode"><code>/-mode</code>: org-mode</h3><p>Hold<code>/</code> in Emacs to access org-mode commands via the<code>C-H-M-s-</code> modifier prefix.</p><figure><a href="/images/keyboard/slash-mode-emacs.svg" target="_blank" rel="noopener"><img src="/images/keyboard/slash-mode-emacs.svg" alt=""/></figure><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:des</span><span class="s">"slash simlayer → org-mode"</span></span></span><span class="line"><span class="cl"><span class="ss">:rules</span><span class="p">[</span><span class="ss">:slash-mode</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:a</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:a</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:b</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:b</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:c</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:c</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:d</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:d</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:e</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:e</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:f</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:f</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:g</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:g</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:h</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:h</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:i</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:i</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:j</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:j</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:m</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:m</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:n</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:n</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:o</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:o</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:p</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:p</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:q</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:q</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:r</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:r</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:s</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:s</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:t</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:t</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:u</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:u</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:v</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:v</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:w</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:w</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:z</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:z</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:x</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:x</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:y</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:y</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">[</span><span class="ss">:period</span><span class="p">{</span><span class="ss">:modi</span><span class="ss">:C-H-M-s-</span><span class="ss">:key</span><span class="ss">:period</span><span class="p">}</span><span class="ss">:emacs</span><span class="p">]</span></span></span><span class="line"><span class="cl"><span class="p">]}</span></span></span></code></pre></div><h2 id="summary">Summary</h2><p>This setup trades a steep learning curve for an extremely compact and efficient input system. The key design decisions are:</p><ul><li><strong>Minimal firmware, maximal software.</strong> The keyboard firmware is nearly a no-op. All intelligence lives in Karabiner/Goku, which is easier to iterate on and works across keyboards.</li><li><strong>Simlayers over firmware layers.</strong> Instead of dedicated layer-switch keys, every letter can be a layer trigger. This is only possible because Karabiner&rsquo;s simlayer mechanism is time-based, distinguishing a quick tap from a held key.</li><li><strong>Context-aware behavior.</strong> The same physical key does different things in Emacs vs. other apps. This lets me have Emacs-native deletion, navigation, and transposition commands alongside standard macOS shortcuts.</li><li><strong>Six Emacs modifiers from six thumb keys.</strong> By mapping all six Emacs modifier keys to physical keys, I have a keybinding space large enough to support thousands of unique commands.</li></ul>
]]></description></item><item><title>Paul Christiano on cause prioritization</title><link>https://stafforini.com/notes/paul-christiano-on-cause-prioritization/</link><pubDate>Mon, 24 Mar 2014 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/paul-christiano-on-cause-prioritization/</guid><description>&lt;![CDATA[<p>Paul Christiano is a graduate student in computer science at UC Berkeley. His academic research interests include algorithms and quantum computing. Outside academia, he<a href="http://rationalaltruist.com/">has written</a> about various topics of interest to effective altruists, with a focus on the far future.  Christiano holds a BA in mathematics from MIT and has represented the United States at the International Mathematical Olympiad. He is a Research Associate at the<a href="http://intelligence.org/">Machine Intelligence Research Institute</a> and a Research Advisor at<a href="http://80000hours.org/">80,000 Hours</a>.</p><hr><p><strong>Pablo</strong>: To get us started, could you explain what you mean by &lsquo;cause prioritization&rsquo;, and briefly discuss the various types of cause prioritization research that are currently being conducted?</p><p><strong>Paul</strong>: I mean research that helps determine which broad areas of investment are likely to have the largest impact on the things we ultimately care about. Of course a huge amount of research bears on this question, but I&rsquo;m most interested in research that addresses its distinctive characteristics. In particular, I&rsquo;m most interested in:</p><ol><li>Research that draws on what is known about different areas in order to actually make these comparisons. I think<a href="http://www.givewell.org/givewell-labs">GiveWell Labs</a> and the<a href="http://www.copenhagenconsensus.com/">Copenhagen Consensus Center</a> are the two most salient examples of this work, though they have quite different approaches. I understand that the<a href="http://centreforeffectivealtruism.org/">Centre for Effective Altruism</a> (CEA) is beginning to invest in this area as well. I think this is an area where people will be able to get a lot of traction (and have already done pretty well for the amount of investment I&rsquo;m aware of) and I think it will probably go a very long way towards facilitating issue-agnostic giving.</li><li>Research that aims to understand and compare the long-term impacts of the short-term changes which our investments can directly bring about. For example, research that clarifies and compares the long-term impact of poverty alleviation, technological progress, or environmental preservation, and how important that long-term impact is. This is an area where answers are much harder to come by, but even slight improvements in our understanding would have significant importance for a very broad range of decisions. It appears that high-quality work in this area is pretty rare, though it&rsquo;s a bit hard to tell if this is due to very little investment or if this is merely evidence that making progress on these problems is too difficult. I tend to lean towards the former, because (a) we see very little public discussion of process and failed attempts for high-quality research on these issues, which you should expect to see even if they are quite challenging, and (b) this is not an area that I expect to receive a lot of investment except by cause-agnostic altruists who are looking quite far ahead. I think the most convincing example to date is Nick Bostrom&rsquo;s<a href="http://intelligence.org/files/AstronomicalWaste.pdf">astronomical waste argument</a> and Nick Beckstead&rsquo;s<a href="https://docs.google.com/viewer?a=v&amp;pid=sites&amp;srcid=ZGVmYXVsdGRvbWFpbnxuYmVja3N0ZWFkfGd4OjExNDBjZTcwNjMxMzRmZGE">more extensive discussion of the importance of the far future</a>, which seem to take a small but reasonably robust step towards improving our understanding of what to do.</li></ol><p>There are certainly other relevant research areas, but they tend to be less interesting as cause prioritization per se. For example, there is a lot of work that tries to better understand the impact of particular interventions. I think this is comparably important to (1) or (2), but that it currently receives quite a lot more attention at the moment and it&rsquo;s not clear that a cause-agnostic philanthropist would want to change how this is being done. More tangentially, efforts to improve forecasts more broadly have significant relevance for philanthropic investment, though they are even more important in other domains so prima facie it would be a bit surprising if these efforts ought to be a priority by virtue of their impact on improving philanthropic decision-making.</p><p><strong>Pablo</strong>: In public talks and private conversation, you have argued that instead of supporting any of the object-level interventions that look most promising on the evidence currently available, we should on the current margin invest in research on understanding which of those opportunities are most effective.  Could you give us an outline of this argument?</p><p><strong>Paul</strong>: It seems very likely to me that more research will lead to a much clearer picture of the relative merits of different opportunities, so I suspect in the future we will be much better equipped to pick winners. I would not be at all surprised if supporting my best guess charity ten years from now was several times more impactful than supporting my best guess charity now.</p><p>If you are this optimistic about learning more, then it is generally better to donate to your best guess charity in a decade, rather than donating to your current best guess. But if you think there is room for more funding to help accelerate that learning process, then that might be an even better idea. I think this is the case at the moment: the learning process is mostly driven by people doing prioritization research and exploratory philanthropy, and total investment in that area is not very large.</p><p>Of course, giving to object level interventions may be an important part of learning more, and so I would be hesitant to say that we should avoid investment in object-level problems. However, I think that investment should really be focused on learning and exploring (in a way that can help other people make these decisions as well, not just the individual donor) rather than for a direct positive impact.  So for example I&rsquo;m not very interested in scaling up successful global health interventions.</p><p>The most salient motivation to do good now, rather than learning or waiting, is a discount rate that is much steeper than market rates of return.</p><p>For example, you might give now if you thought your philanthropic investments would earn very high effective rates of return. I think this is unlikely for the kinds of object-level investments most philanthropists consider&ndash;I think most of these investments compound roughly in line with the global growth rate (which is smaller than market rates of return).</p><p>You might also have a high discount rate if you thought that the future was likely to have much worse philanthropic opportunities; but as far as I can tell a philanthropist today has just as many problems to solve as a philanthropist 20 years ago, and frankly I can see a lot of possible problems on the horizon for a philanthropist to invest in, so I find this compelling.</p><p>Sometimes “movement-building” is offered as an example of an activity with very high rates of returns. At the moment I am somewhat skeptical of these claims, and my suspicion is that it is more important for the “effective altruism” movement to have a fundamentally good product and to generally have our act together than for it to grow more rapidly, and I think one could also give a strong justification for prioritization research even if you were primarily interested in movement-building. But that is a much longer discussion.</p><p><strong>Pablo</strong>: I think it would be interesting to examine more closely the object-level causes supported by EAs or proto-EAs in the past (over, say, the last decade), and use that examination to inform our estimates about the degree to which the value of future EA-supported causes will exceed that of causes that EAs support today.  Off the top of my head, the EAs I can think of who have donation records long enough to draw meaningful conclusions all have in the past supported causes that they would now regard as being significantly worse than those they currently favour.  So this would provide further evidence for one of the premises in your argument: that cause prioritization research can uncover interventions of high impact relative to our current best guesses.</p><p>The other premise in your argument, as I understand it, is that the value of the interventions we should expect cause prioritization research to uncover is high relative to the opportunity cost of current spending. Can you elaborate on the considerations that are, in your opinion, relevant for assessing this premise?</p><p><strong>Paul</strong>: Sorry, this is going to be a bit of a long and technical response. I see three compelling reasons to prefer giving today to giving in the future. But altogether they don&rsquo;t seem to be a big deal compared to how much more we would expect to know in the future. Again, I think that using giving as an opportunity to learn stands out as an exception here&ndash;because in that case we can say with much more confidence that we will need to learn more at some point, and so the investment today is not much of a lost cause.</p><ol><li>The actual good you do in the world compounds over time, so it is better to do good sooner than later.</li><li>There are problems today that won&rsquo;t exist in the future, so money in the future may be substantially less valuable than money today.</li><li>In the future there will be a larger pool of “smart money” that finds the best charitable opportunities, so there will be fewer opportunities to do good.</li></ol><p>Regarding (1), I think that the vast majority of charitable activities people engage in simply do not compound that quickly. To illustrate, you might consider the case of a cash transfer to a poor family. Initially such a cash transfer earns a very high rate of return, but over time the positive impact diffuses over a broader and broader group of people. As it diffuses to a broader group, the returns approach the general rate of growth in the world, which is substantially smaller than the interest rate. Most other forms of good experience a very similar pattern. So if this were the only reason to give sooner, then I think that you would actually be better served by saving and earning prevailing interest rates for an extra year, and then donating a year later&ndash;even if you didn&rsquo;t expect to learn anything new.</p><p>A mistake I sometimes see people make is using the initial rates of return on an investment to judge its urgency. But those returns last for a brief period before spreading out into the broader world, so you should really think of the investment as giving you a fixed multiplier on your dollar before spreading out and having a long-term returns that go like growth rates. It doesn&rsquo;t matter whether that multiplier accrues instantaneously or over a period of a few years during which you enjoy excess returns. In either case the magnitude of the multiplier is not relevant to the urgency of giving, just whether the multiplier is going up or down.</p><p>A category of good which is plausibly exceptional here is creating additional resources that will flexibly pursue good opportunities in the future. I&rsquo;m aware that some folks around CEA assign very high rates of return, in excess of 30% / year, to investment in movement-building and outreach. I think this is an epistemic error, but that would probably be a longer discussion so it might be easier to restrict attention to object-level interventions vs. focusing on learning.</p><p>Regarding (2), I don&rsquo;t really see the evidence for this position. From my perspective the problems the world faces today seem more important&ndash;in particular, they have more significant long-term consequences&ndash;than the problems the world faced 200 years ago. It looks to me like this trend is likely to continue, and there is a good chance that further technological development will continue to introduce problems with an unprecedented potential impact on the future. So with respect to object-level work I&rsquo;d prefer to address the problems of today than the problems of 200 years ago, and I think I&rsquo;d probably be even happier addressing the problems we face 50 years.</p><p>Regarding (3), I do see this as a fairly compelling reason to move sooner rather than later. I think the question is one of magnitudes: how long do you expect it will take before the pool of “smart money” is twice as large? 10 times larger? I think it&rsquo;s very easy to overestimate the extent to which this group is growing. It is only at extremely exceptional points in history that this pool can grow 20% faster than economic growth. For example, if you are starting from a baseline of 0.1% of total philanthropic spending, that can only go up 20% per year for 40 years or so before you get to 100% of spending. On the flip side, I think it is pretty easy to look around at what is going on locally and mistakenly conclude that the world must be changing pretty rapidly.</p><p>I think most of what we are seeing isn&rsquo;t a changing balance between smart money and ordinary folk, it&rsquo;s continuously increasing sophistication on the part donors collectively&ndash;this is a process that can go on for a very long time. In this case, it&rsquo;s not so clear why you would want to give earlier when you are one of many unsophisticated donors rather than giving later when you are one of many sophisticated donors, even if you were only learning as fast as everyone else in the world. The thing that drives the discount rate earlier was the belief that other donors were getting sophisticated faster than we are, so that our relative importance was shrinking. And that no longer seems to apply when you look at it as a community increasing in sophistication.</p><p>So overall, I see the reasons for urgency in giving to be relatively weak, and I think the question of whether to give or save would be ambiguous (setting aside psychological motivations, the desire to learn more, and social effects of giving now) even if we weren&rsquo;t learning more.</p><p><strong>Pablo</strong>: Recently, a few EAs have questioned that charities vary in cost-effectiveness to the degree that is usually claimed within the EA community.  Brian Tomasik, for instance, argues that<a href="http://utilitarian-essays.com/why-charities-do-not-differ-astronomically.html">charities differ by at most 10 to 100 times</a> (and much less so within a given field). Do you think that arguments of this sort could weaken the case for supporting research into cause prioritization, or change the type of cause prioritization research that EAs should support?</p><p><strong>Paul</strong>: I think there are two conceptually distinct issues here which should be discussed separately, at least in this context.</p><p>One is the observation that a small group looking for good buys may not have as large an influence as it seems, if they will just end up slightly crowding out a much larger pool of thoughtful money. The bar for “thoughtful” isn&rsquo;t that high, it just needs to be sensitive to diminishing returns in the area that is funded. There are two big reasons why this is not so troubling:</p><ul><li>Money that is smart enough to be sensitive to diminishing marginal returns&ndash;and moreover which is sufficiently cause-agnostic to move between different fields on the basis of efficiency considerations&ndash;is also likely to be smart enough to respond to significant changes in the evidence and arguments for a particular intervention. So I think doing research publicly and contributing to a stock of public knowledge about different causes is not subject to such severe problems.</li><li>The number of possible giving opportunities is really quite large compared to the number of charitable organizations. If you are looking for the best opportunities, in the long-term you are probably going to be contributing to the existence of new organizations working in areas which would not otherwise exist. This is especially true if we expect to use early investigations to help direct our focus in later investigations. This is very closely related to the last point.</li></ul><p>This issue is most severe when we consider trying to pursue idiosyncratic interests, like an unusually large degree of concern for the far future. So this consideration does make me a bit less enthusiastic about that, which is something I&rsquo;ve written about before. Nevertheless, I think in that space there are many possible opportunities which are simply not going to get any support from people who aren&rsquo;t thinking about the far future, so there still seems to be a lot of good to do by improving our understanding.</p><p>A second issue is that broad social improvements will tend to have a positive effect on society&rsquo;s ability to resolve many different problems. So if there is any exceptionally impactful thing for society to do, then that will also multiply the impact of many different interventions. I don&rsquo;t think this consideration says too much about the desirability of prioritization: quite large differences are very consistent with this observation, these differences can be substantially compounded by uncertainty about whether the indirect effects of an intervention are good and bad, and there is substantial variation even in very broad measures of the impact of different interventions. This consideration does suggest that you should pay more attention to very high-impact interventions even if the long-term significance of that impact is at first ambiguous.</p><p><strong>Pablo</strong>: Finally, what do you think is the most effective way to promote cause prioritization research?  If an effective altruist reading this interview is persuaded by your arguments, what should this person do?</p><p><strong>Paul</strong>: One conclusion is that it would be premature to settle on an area that currently looks particularly attractive and simply scale up the best-looking program in that area. For example, I would be hesitant to support an intervention in global health (or indeed in most areas) unless I thought that supporting that intervention was a cost-effective way to improve our understanding of global health more broadly. That could be because executing the intervention would provide useful information and understanding that could be publicly shared, or because supporting it would help strengthen the involvement of EA&rsquo;s in the space and so help EA&rsquo;s in particular improve their understanding. One could say the same thing about more speculative causes: investments that don&rsquo;t provide much feedback or help us understand the space better are probably not at the top of my priority list.</p><p>Relatedly, I think that global health receives a lot of attention because it is a particularly straightforward area to do good in; I think that&rsquo;s quite important if you want your dollar to do as much good directly as possible, but that it is much less important (and important in a different way) if you are paying appropriate attention to the value of learning and information.</p><p>Another takeaway is that it may be worth actively supporting this research, either by supporting organizations that do it or by giving on the basis of early research. I think Good Ventures and GiveWell Labs are currently the most credible effort in this space (largely by virtue of having done much more research in this space than any other comparably EA-aligned organization), and so providing support for them to scale up that research is probably the most straightforward way to directly support cause prioritization. There are some concerns about GiveWell Labs capturing only half of marginal funding, or about substituting with Good Ventures&rsquo; funding; that would again be a longer and much more complicated discussion. My view would be that those issues are worth thinking about but probably not deal-breakers.</p><p>I hear that CEA may be looking to invest more in this area going forward, and so supporting CEA is also a possible approach. To date they have not spent much time in this area and so it is difficult to predict what the output will look like. To the extent that this kind of chicken-and-egg problem is a substantial impediment to trying new things faster and you have confidence in CEA as an organization, providing funding to help plausible-looking experiments get going might be quite cost-effective.</p><p>A final takeaway is that the balance between money and human capital looks quite different for philanthropic research than for many object-level interventions. If an EA is interested in scaling up proven interventions, it&rsquo;s very likely that their comparative advantage is elsewhere and they are better served by<a href="http://www.effective-altruism.com/category/earning-to-give/">earning money and distributing it to charities doing the work they are most excited about</a>. But if you think that increasing philanthropic capacity is very important, it becomes more plausible that the best use of time for a motivated EA is to work directly on related problems. That might mean working for an “EA” organization, working within the philanthropy sector more broadly, or pursuing a career somewhere else entirely. Once we are talking about applying human capital rather than money, ability and enthusiasm for a particular project becomes a very large consideration (though the kinds of considerations we&rsquo;ve discussed in this interview can be another important input).</p>
]]></description></item><item><title>How can doctors do the most good? An interview with Dr Gregory Lewis</title><link>https://stafforini.com/notes/how-can-doctors-do-the-most-good-an-interview-with-dr-gregory-lewis/</link><pubDate>Fri, 28 Aug 2015 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/how-can-doctors-do-the-most-good-an-interview-with-dr-gregory-lewis/</guid><description>&lt;![CDATA[<p>Gregory Lewis is a public health doctor training in the east of England. He studied medicine at Cambridge, where he volunteered for Giving What We Can and 80000 hours. He blogs at<a href="http://www.thepolemicalmedic.com/">The Polemical Medic</a>. This interview was conducted as part of the research I did for Will MacAskill&rsquo;s book,<em><a href="http://www.effectivealtruism.com/">Doing Good Better: How Effective Altruism Can Help You Make a Difference</a></em>. Greg&rsquo;s inspiring story is discussed in chapters 4 and 5 of that book.</p><hr><p><strong>Pablo Stafforini</strong>: To get us started, can you tell us a bit about your background, and in particular about your reasons for deciding to become a doctor?</p><p><strong>Gregory Lewis</strong>: Sure. I guess I found myself at the age of 14 or so being fairly good at science and not really having any idea of what to do with myself. I had some sort of vague idea of trying to want to make the world a better place, in some slightly naive way. So I sort of thought, “What am I going to do with myself?” And my thoughts were pretty much<em>verbatim</em>, “Well, I&rsquo;m good at science and want to do good. Doctors are good at science and they want to do good. Therefore, I want to be a doctor.” So based on that simple argument, I applied to medical school, got in, spent the following six years of my life in medical school qualifying as a doctor, and here I am today.</p><p><strong>Pablo</strong>: I suppose that at some point between the age of fourteen and the present you changed your mind to some degree about the kind and amount of good that doctors could do. Can you elaborate on that?</p><p><strong>Greg</strong>: Yes. One of my interests outside medicine was philosophy &ndash; I almost studied philosophy at university, but I thought I could do more good as a doctor. It was through this I read Peter Unger&rsquo;s book<em><a href="http://www.amazon.com/Living-High-Letting-Die-Innocence/dp/0195108590/ref=sr_1_1?ie=UTF8&amp;qid=1439333672&amp;sr=8-1&amp;keywords=living+high+and+letting+die&amp;tag=s4charity-20">Living High and Letting Die</a></em>. This book opened my eyes to the importance and moral significance of giving substantially to charity, and I took this message to heart. But I didn&rsquo;t really link it up with what I&rsquo;d planned in my career: I thought I would heal the sick (if you&rsquo;ll excuse the expression) in my day job, and the good I would do by giving a lot to charity would be an added bonus.</p><p>It took a couple of years, and coming into contact with people like Toby Ord and Will McAskill, to begin to put these things together, and look again at my plans to be a doctor. How much good did doctors really do and (more importantly) how did it stack up in comparison with all the other things I could do instead? So I began to look at this question and found (somewhat to my disappointment) that working as a doctor doesn&rsquo;t fare well in this sort of comparison.</p><p><strong>Pablo</strong>: You mention Unger&rsquo;s book, and I recall that in that book the argument for earning to give is<a href="http://www.jefftk.com/p/history-of-earning-to-give">briefly sketched</a>. Did you notice that argument when reading the book, or did you just focus on the message that you should be donating a big chunk of the money you&rsquo;d expect to earn in your current career (as opposed to switching to an even more lucrative career)?</p><p><strong>Greg</strong>: Yes, I remember reading those couple of paragraphs where he suggests that philosophers should consider moving out of academia into corporate law or more lucrative fields, so that they would have more money to give away. That sounded right to me back then, but I didn&rsquo;t really see medicine at the time as an ‘earning to give&rsquo; career—I thought the direct impacts of medicine were substantial, so a medical career got the ‘best of both worlds&rsquo;, and the money I would give away would be an ‘added bonus&rsquo; to the direct work as a medical doctor. It took getting more involved with the effective altruism community to think I should try and combine these two worlds, and that I should try and weigh up how much good doctors do versus how much good donations do, and plan my career accordingly.</p><p><strong>Pablo</strong>: So when you started to think more systematically about the amount of good that doctors could do, do you think you encountered any internal resistance to the possible conclusion that this amount might not be as high as you had assumed initially?</p><p><strong>Greg</strong>: The seeds of scepticism were sown fairly early in my training. Doctors themselves generally are fairly cynical of the good they do, and when they talk about ‘healing the sick&rsquo;, it is with tongue firmly in cheek. One conversation I remember clearly (and with retrospect I wish I paid attention to more) was talking to a doctor in paediatrics, who said something along the lines of, “I don&rsquo;t ever feel like I&rsquo;m saving lives or making a big difference, because although I might be the guy giving the life-saving treatments, if I wasn&rsquo;t there they would have called the doctor just down the hall, who would have done exactly the same as I.”</p><p>I gradually internalized this more realistic view on how much good I could do as a doctor. This was somewhat disappointing to me, but I wasn&rsquo;t that phased by it. Maybe the world is just set up that it&rsquo;s really hard to make a big difference, and if the best I could hope for was to make a more modest contribution, that is still definitely ‘worth it&rsquo;, and (like many other doctors) I decided my prior zeal to heal the sick and save the world was quixotic, immature, and naive: “The mark of an immature man is the desire to die nobly for a cause, whilst the mark of the mature man is the desire to live humbly for one.” I flirted with the idea of working for Médecins Sans Frontières (MSF) or abroad, but I wasn&rsquo;t thinking systematically.</p><p>So one of the major upsides of reading<em>Living High and Letting Die</em> was finding out my 17 year old self wasn&rsquo;t so unrealistic in hoping to save hundreds or thousands of lives—things that good are within our reach. The downside was this would happen through a very different channel. Rather than 17-year-old me&rsquo;s vainglorious visage of (thousands of times over!) striding in, white coat billowing, and saving some stricken patient with my cleverness, it would be me posting a cheque or clicking a bank transfer: I&rsquo;d know abstractly that this would do so much good, but I wouldn&rsquo;t be able to point to the person it was that I helped. As it turns out, that&rsquo;s no big deal—especially compared to the sheer magnitude of good done.</p><p><strong>Pablo</strong>: Your conclusion that you wouldn&rsquo;t in your capacity as a doctor be doing as much good as alternative paths to impact appears to involve both a premise about the amount of good doctors typically do and a premise about the amount of good that such people can do in other ways. That is, you seem to be claiming that doctors do less good directly than people assume, but also that people, including doctors, can do much more good than they think by donating to the right causes. Is that correct?</p><p><strong>Greg</strong>: Yes. The major upshot of the work I&rsquo;ve done into how much good a doctor does is that the average doctor probably saves around a handful of lives over their career. So that&rsquo;s bad news for medics. By contrast, giving fairly small amounts to charity can save hundreds of lives (or maybe more) over your working life, and that&rsquo;s good news for everyone!</p><p><strong>Pablo</strong>: Let&rsquo;s zoom in on your work about the good doctors do. Insofar as it&rsquo;s possible to discuss these issues in an informal interview, without having all the relevant figures in front of us, can you sketch the argument for the conclusion that a doctor saves about 200 DALYs over the course of his or her career?</p><p><strong>Greg</strong>: Sure. I started looking at the research literature expecting there would be a lot of work done on the ‘return&rsquo; of having more doctors—I figured this would be important to running a health system, or something more introspective members of the profession would have wanted to find out. As it happened, there was basically no work looking at the question: “How much good does a doctor do?”</p><p>The closest is<a href="http://ije.oxfordjournals.org/content/30/6/1260.full">work by an epidemiologist called John Bunker</a>: he and colleagues were looking at the question of how much of the dramatic gains in health and life expectancy in the western world could be attributed to medical treatment. Their strategy was to look at the few hundred or so commonest medical interventions: fixing broken bones, treating heart attacks, stuff like that. For each of these, they looked at clinical trials to see how much good each of those things did, and, by adding them together, work out how much good medicine as a whole does. You can extrapolate from their figures to many healthy life years (a measure of length and quality of life&mdash;you can think of 30 health years as ‘one life saved&rsquo;) are added to the population by the medical profession, and then divide by the number of doctors to get the ‘years added per doctor&rsquo; This is about 2250 health-years saved per medical career&mdash;that&rsquo;s pretty good, about 80 lives.</p><p>There are several reasons to suspect this is an overestimate. One of the big ones is that the difference of a doctor should be<em>on the margin</em>. Although the first few doctors should be able to make a massive difference, subsequent doctors (like being the 170001st in the UK) should make a smaller difference, as all the easy ways to make people live longer and healthier should already be being done. If I were removed from my post, there wouldn&rsquo;t be a ‘Greg shaped hole&rsquo; in the hospital where all my patients are not treated. Rather the remaining doctors will reallocate their tasks so only the least important things don&rsquo;t get done.</p><p>So I began to attack this problem from the ‘top down&rsquo; rather than from the ‘bottom up&rsquo;. Instead of compiling an inventory of medical treatment, I looked at aggregate measures of health and physician density, and looked at the relationship between them: looking at all the countries in the globe, did having more doctors per capita correspond to lower burdens of death and disability? The answer was ‘yes&rsquo;, but there were diminishing returns. What I then did was fit a best line to this curve, and work out, if you were in the UK and you added one more doctor to the population, how much further along the curve do you go, and how much does disability fall? This figure is smaller, of the order of 400-800 health-years averted per medical career: 20 to 30 lives.</p><p>This figure, however, is also going to be an overestimate, because we implicitly ignore confounding factors—there are fairly obvious things that will increase both health and physician density, like wealth, sanitation, or education. Indeed, it&rsquo;s received wisdom that these ‘social determinants of health&rsquo; are far more important than doctors. Happily, international data on these factors are also available, and one can try and tease apart these interrelationships by a technique called regression analysis. This gives a smaller figure still. The average doctor averts 200 or so DALYs per medical career—six lives or so.</p><p>There are all sorts of caveats with this sort of work&mdash;the data is fair but not great, it is fundamentally an observational study, and there&rsquo;s always the spectre of unaccounted for confounds. Despite these concerns, I&rsquo;d be surprised if this figure was off by an order of magnitude or more. If anything, this already fairly low estimate is also over-optimistic: two big factors would be that I&rsquo;m ignoring/counterfactuals/ and<em>elasticity</em> (if I never went to medical school, there wouldn&rsquo;t be ‘one fewer doctor&rsquo;, it would be more like ‘I would be replaced by the marginal candidate who just missed out on med school); even worse, physician density is serving as a proxy for ‘medical professional density&rsquo;, from nurses, to hospital cleaners, to laboratory scientists. It&rsquo;s implausible that doctors can take all of the credit, or even a majority of it. So even if doctors have the largest impact out of all the health professions, one is still looking at another adjustment down, by a factor of at least two</p><p><strong>Pablo</strong>: How much could altruistically motivated doctors boost that figure if they targeted their efforts more intelligently, e.g. by working in a less developed country or in a more lucrative specialty?</p><p><strong>Greg</strong>: That was the question I asked myself next: given this is the average impact of a doctor, how could I try to do better than average? This is tricky, as the ‘top down&rsquo; technique I used to find the average is too coarse-grained to answer these questions: there isn&rsquo;t the data, for example, to work out whether the marginal impact of cardiologists is greater than colorectal surgeons, or things like that.</p><p>One strategy could be to exploit the ‘diminishing returns&rsquo; effect and go somewhere where the curve is steeper and so there are increasing benefits to having ‘an additional doctor&rsquo;—this really crudely models ‘a career spent working in MSF&rsquo; or with a similar NGO. This does give a bigger impact, by a factor of 10 or so.</p><p>However, the chequebook can likely beat the stethoscope, even one wielded by an MSF doctor. The average doctor in the UK will earn around 2.5 million pounds over their lifetime. Giving 10% of this to the right interventions will still ‘beat&rsquo; an additional doctor abroad. And one can always give more than 10%, and although that is hard, it may not be as hard as spending one&rsquo;s career in the developing world.</p><p>The next question—going back to Unger—is whether there are particularly lucrative medical careers one could target with the aim of giving more away. And there are, at least when working in the Western world. To give the UK as an example, average consultant earnings by specialty vary by a factor of 3 or so, and the main determinant of this variation is the capacity that specialty has for private practice: you can&rsquo;t really work privately as an emergency physician, but one can work wholly outside the NHS as a plastic surgeon. So medicine is a fairly good earning to give option, although it is worth noting that if earning to give ‘beats&rsquo; direct impact by a large margin, it perhaps would be even better to attempt to work in even more lucrative careers outside of medicine.</p><p>Finally, there are ‘peri-medic&rsquo; roles that could be really important but hard to quantify: the chief medical officer for the NHS (or for the WHO), the researcher who makes the breakthrough for a malaria vaccine could have massive impact, so much so that it might be worth attempting even if it is a very long shot and one is likely to achieve something far more modest. It&rsquo;s pretty hard to quantify these considerations, but they look like career paths that could be even better than earning to give.</p><p>Perhaps the upshot is that direct work as a doctor is relatively small-fry compared to what you could do instead. Which ‘instead&rsquo;, though, remains very difficult to work out.</p><p><strong>Pablo</strong>: To wrap up, you mentioned that you are currently giving about 50% of your income to cost-effective charities. Can you elaborate on what motivated you to give away such a big portion of your income and whether you find that difficult on a personal level?</p><p><strong>Greg</strong>: Sure. So, given what I&rsquo;d read by Unger, and in philosophy more generally, giving a lot to charity seemed a bit of a moral no-brainer. On the one side, several lives in my first year of being employed (and several thousand over my career as my salary grows), and on the other side, not a huge amount. So I committed to give 10% of my earnings whilst I was a medical student.</p><p>It became even more of a no-brainer when I actually started working. I am privileged in all manner of ways, but not least in that I live without dependents in a modern liberal democracy with almost double the median income of my country, and so among the top few percent of the planet by wealth. I found living similarly (but still better) than I did as a medical student left me with almost half my paycheck. So I started giving 10%, and have steadily increased this month on month until now I&rsquo;m giving about 50%.</p><p>It&rsquo;s only at this larger proportion that there&rsquo;s any real personal ‘sacrifice&rsquo; on my part: I now plan journeys in advance, keep a monthly budget, and don&rsquo;t reflexively eat out whenever the opportunity presents itself. I also haven&rsquo;t (as some of my colleagues have) got a BMW on franchise, or regularly holiday across the world. I don&rsquo;t really miss these luxuries, especially as these sacrifices are made without choice by most people living in the UK (and the globe), including people who work much harder and longer than I do alongside me in hospital.</p><p>I&rsquo;m still in the wealthiest 10% of people on the planet. More importantly, I still get to keep the things that really matter: family, friends, literature, music, a career that, even though it might not save the world, is immensely personally fulfilling and interesting. Even better, I am happy I am doing something significant in making the world go better. I think the 17 year old me who wanted to be a doctor would be happy, but surprised, at the doctor he turned into.</p><p><strong>Pablo</strong>: Awesome. Thanks, Greg!</p><p><em>Crossposted to<a href="https://80000hours.org/2015/08/how-can-doctors-do-the-most-good-an-interview-with-dr-gregory-lewis/">80,000 Hours</a></em></p>
]]></description></item><item><title>Good Done Right</title><link>https://stafforini.com/notes/good-done-right/</link><pubDate>Sat, 01 Feb 2020 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/good-done-right/</guid><description>&lt;![CDATA[<p>Good Done Right was a conference on effective altruism held at All Souls College, Oxford on 7-9 July, 2014. It was perhaps the very first conference of its kind, and it featured an impressive roster of speakers. Some of the talks explored topics, such as moral trade, that would later become more widely discussed. One of these presentations was so good that I decided to<a href="/notes/crucial-considerations-and-wise-philanthropy-by-nick-bostrom/">transcribe it</a>.</p><p>Recordings of all the talks were subsequently<a href="https://80000hours.org/2014/07/good-done-right-audio-recordings-now-online/">made available</a> on a website dedicated to the conference. Unfortunately, the website has since gone offline, and the Internet Archive hasn&rsquo;t indexed it properly. I contacted Andreas Mogensen, the conference organizer, and he supplied me with an image of the original conference poster (displayed below), but noted that he was no longer in possession of any of the audio recordings. Andreas also clarified that the list of speakers in the poster doesn&rsquo;t quite match the list of people that actually spoke at the event: Thomas Pogge didn&rsquo;t speak, whereas Elizabeth Ashford and Michelle Hutchinson did.</p><p>After a bit of detective work, I managed to locate recordings of most of these presentations. At the time of writing, three of these are on a<a href="https://soundcloud.com/gooddoneright/tracks">Soundcloud channel</a> devoted to the conference, and most of the others are preserved by<a href="https://www.eatalks.org/1755269/episodes">EA Talks</a>. All these talks are listed below, in alphabetical order. I also obtained a number of photos of the event taken by Toby Ord, who kindly gave permission to share them here. I haven&rsquo;t been able to find recordings of the talks by Larissa MacFarquhar and Derek Parfit (as<a href="https://80000hours.org/2014/07/good-done-right-audio-recordings-now-online/">the 80,000 Hours announcement confirms</a>, both MacFarquhar and Parfit did participate in the event). However, upon noticing this post, Matthew van der Merwe reached out to me and generously shared the pdf Parfit used as the basis for his presentation (which he obtained from Parfit himself). I include a link to this text file as a substitute for the missing audio file. If anyone else not listed in the conference programme spoke at the conference, besides Ashford and Hutchinson, I haven&rsquo;t been able to find traces of their presentations.</p><ul><li>Elizabeth Ashford,<a href="https://www.eatalks.org/1755269/episodes/8656192-good-done-right-elizabeth-ashford-the-allowing-of-severe-poverty-as-the-discarding-of-persons-lives">The allowing of severe poverty as the discarding of persons&rsquo; lives</a></li><li>Nick Beckstead,<a href="https://www.eatalks.org/1755269/episodes/8656185-good-done-right-nick-beckstead-how-can-a-long-run-perspective-help-with-strategic-cause-selection">How can a long-run perspective help with strategic cause selection?</a></li><li>Nick Bostrom,<a href="https://soundcloud.com/gooddoneright/nick-bostrom-crucial-considerations-and-wise-philanthropy">Crucial considerations and wise philanthropy</a></li><li>Owen Cotton-Barratt,<a href="https://soundcloud.com/gooddoneright/owen-cotton-barratt-prioritising-under-uncertainty">Prioritising under uncertainty</a></li><li>Norman Daniels,<a href="https://www.eatalks.org/1755269/episodes/8656187-good-done-right-norman-daniels-cost-effectiveness-analysis-and-prioritization">Cost-effectiveness analysis and prioritization</a></li><li>Rachel Glennerster,<a href="https://www.eatalks.org/1755269/episodes/8656191-good-done-right-rachel-glennerster-using-cost-effectiveness-vs-cost-benefit-analysis-in-decision-making">Using cost-effectiveness vs cost-benefit analysis in decision-making</a></li><li>Michelle Hutchinson,<a href="https://www.eatalks.org/1755269/episodes/8656190-good-done-right-michelle-hutchinson-too-young-to-die-how-valuable-is-it-to-extend-lives-of-different-ages">&ldquo;Too Young to Die?&rdquo; &ndash; How valuable is it to extend lives of different ages?</a></li><li>Jeremy Lauer,<a href="https://www.eatalks.org/1755269/episodes/8656188-good-done-right-jeremy-lauer-priority-setting-in-the-health-sector-using-cost-effectiveness-the-who-choice-approach">Priority setting in the health sector using cost-effectiveness &ndash; The WHO-CHOICE approach</a></li><li>Will MacAskill,<a href="https://www.eatalks.org/1755269/episodes/8656193-good-done-right-will-crouch-effective-altruism-the-very-idea">Effective altruism: the very idea</a></li><li>Toby Ord,<a href="https://soundcloud.com/gooddoneright/toby-ord-moral-trade">Moral trade</a></li><li>Derek Parfit,<a href="http://stafforini.com/docs/Parfit%20-%20How%20can%20we%20avoid%20the%20Repugnant%20Conclusion.pdf">How we can avoid the Repugnant Conclusion</a></li></ul><figure><a href="/ox-hugo/conference-poster.png" target="_blank" rel="noopener"><img src="/ox-hugo/conference-poster.png" alt="Good Done Right conference poster listing speakers and schedule"/></figure><figure><a href="/ox-hugo/derek-parfit-at-lectern-closeup.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/derek-parfit-at-lectern-closeup.jpg" alt="Derek Parfit speaking at the lectern, All Souls College, Oxford"/></figure><figure><a href="/ox-hugo/derek-parfit-at-lectern-wide.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/derek-parfit-at-lectern-wide.jpg" alt="Derek Parfit at the lectern in the wood-paneled hall of All Souls College"/></figure><figure><a href="/ox-hugo/derek-parfit-by-stained-glass.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/derek-parfit-by-stained-glass.jpg" alt="Derek Parfit preparing his presentation beside stained glass windows at All Souls College"/></figure><figure><a href="/ox-hugo/conference-audience.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/conference-audience.jpg" alt="Audience at the Good Done Right conference in the vaulted hall of All Souls College"/></figure><figure><a href="/ox-hugo/conference-dinner.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/conference-dinner.jpg" alt="Conference dinner in the great hall of All Souls College, Oxford"/></figure>
]]></description></item><item><title>C. D. Broad: a bibliography</title><link>https://stafforini.com/notes/c-d-broad-a-bibliography/</link><pubDate>Tue, 28 May 2013 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/c-d-broad-a-bibliography/</guid><description>&lt;![CDATA[<figure><a href="/ox-hugo/c-d-broad-portrait.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/c-d-broad-portrait.jpg" alt="C. D. Broad"/></figure><div class="verse"><p>Socius, lector, thesaurarii iunioris inter belli<br/>
angustias uice functus, moralis philosophiae in<br/>
academia professor disciplinae illius alias quoque<br/>
partes singulari acumine et diligentia lucidissime<br/>
tractauit. Non minus se ipsum quam alios nouerat.<br/>
In sermone plus salis quam fellis habuit. Sueciae<br/>
amorem prae se tulit. Huic collegio studuit opera<br/>
consiliis testamento sustinendo. Vita decessit<br/>
A.S.mcmlxxi suae aetatis lxxxiv<br/></p></div><p>This bibliography is based on (1) C. Lewy&rsquo;s &lsquo;Writings of C. D. Broad, to the end of July 1959&rsquo;, in Paul A. Schilpp (ed.)<em>The philosophy of C. D. Broad</em>, New York: Tudor Publishing Company, 1959, pp. 833–852; (2) Andrew Chrucky&rsquo;s<a href="https://www.ditext.com/broad/bybroad.html">Works by C. D. Broad</a>; and (3) my own research online and at various British libraries. It is my best attempt to make Broad&rsquo;s writings freely available on the web. Corrections and additions are welcome.</p><hr><h2 id="1906">1906</h2><ul><li>C. D. Broad,<a href="/works/broad-1906-philosophy-omar-khayyam/">The philosophy of Omar Khayyam and its relation to that of Schopenhauer</a>,<em>Westminster review</em>, vol. 166, 1906, pp. 544–556</li></ul><h2 id="1912">1912</h2><ul><li>C. D. Broad,<a href="/works/broad-1912-review-proceedings-aristotelian/">Review of<em>Proceedings of the Aristotelian Society</em>, 1910-11</a>,<em>Mind</em>, vol. 21, no. 82, 1912, pp. 260–264</li><li>C. D. Broad,<a href="/works/broad-1912-review-sorley-moral/">Review of W. R. Sorley,<em>The Moral Life and Moral Worth</em></a>,<em>The International Journal of Ethics</em>, vol. 22, no. 3, 1912, pp. 352–353</li><li>C. D. Broad,<a href="/works/broad-1912-review-boodin-truth/">Review of J. E. Boodin,<em>Truth and Reality: An Introduction to the Theory of Knowledge</em></a>,<em>Mind</em>, vol. 21, no. 83, 1912, pp. 449–451</li><li>C. D. Broad,<a href="/works/broad-1912-review-welby-significs/">Review of V. Welby,<em>Significs and Language: The Articulate Form of Our Expressive and Interpretive Resources</em></a>,<em>Mind</em>, vol. 21, no. 83, 1912, pp. 455–456</li><li>C. D. Broad,<a href="/works/broad-1912-review-james-ward/">Review of James Ward,<em>The Realm of Ends or Pluralism and Theism</em></a>,<em>The International Journal of Ethics</em>, vol. 23, no. 1, 1912, pp. 77–84</li></ul><h2 id="1913">1913</h2><ul><li>C. D. Broad,<a href="/works/broad-1913-critical-notice-meinong/">Critical notice of A. Meinong,<em>Über Annahmen</em></a>,<em>Mind</em>, vol. 22, no. 1, 1913, pp. 90–102</li><li>C. D. Broad,<a href="/works/broad-1913-note-achilles-tortoise/">Note on Achilles and the tortoise</a>,<em>Mind</em>, vol. 27, no. 4, 1913, pp. 318–319</li><li>C. D. Broad,<a href="/works/broad-1913-review-rogers-short/">Review of R. A. P. Rogers: A Short History of Ethics: Greek and Modern</a>,<em>The International Journal of Ethics</em>, vol. 23, no. 3, 1913, pp. 359–361</li><li>C. D. Broad,<a href="/works/broad-1913-lord-hugh-cecil/">Lord Hugh Cecil's "conservatism"</a>,<em>The International Journal of Ethics</em>, vol. 23, no. 4, 1913, pp. 396–418</li><li>C. D. Broad,<a href="/works/broad-1913-critical-notice-cournot/">Critical notice of A. Cournot,<em>Essai sur les Fondements de not Connaissances et sur les Caractères de la Critique Philosophique</em></a>,<em>Mind</em>, vol. 22, no. 87, 1913, pp. 399–402</li><li>C. D. Broad,<a href="/works/broad-1913-review-proceedings-aristotelian/">Review of<em>Proceedings of the Aristotelian Society</em>, 1911-12</a>,<em>Mind</em>, vol. 22, no. 87, 1913, pp. 408–410</li><li>C. D. Broad,<a href="/works/broad-1913-review-walter-marvin/">Review of Walter T. Marvin,<em>A First Book in Metaphysics</em></a>,<em>Mind</em>, vol. 22, no. 10, 1913</li><li>C. D. Broad,<a href="/works/broad-1913-review-wildon-carr/">Review of H. Wildon Carr,<em>The Problem of Truth</em></a>,<em>The International Journal of Ethics</em>, vol. 24, no. 1, 1913, pp. 104–107</li></ul><h2 id="1914">1914</h2><ul><li>C. D. Broad,<a href="/works/broad-1914-perception-physics-reality/"><em>Perception, physics, and reality: An enquiry into the information that physical science can supply about the real</em></a>, Cambridge, 1914</li><li>C. D. Broad,<a href="/works/broad-1914-critical-notice-aloys/">Critical notice of of Aloys Müller,<em>Wahrheit und Wirklichkeit: Untersuchungen zum realistischen Wahrheitsproblem</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 122–125</li><li>C. D. Broad and A. J. B. Wace,<a href="/works/broad-1914-matters-mainly-mental/">M.M.M. (Matters Mainly Mental)</a>,<em>College echoes</em>, vol. 9, 1914, pp. 140–2</li><li>C. D. Broad and C. C.,<a href="/works/broad-1914-hints-social-aspirants/">Hints to social aspirants: with examples from high life</a>,<em>College echoes</em>, vol. 9, 1914, pp. 268–9</li><li>C. D. Broad and A. J. B. Wace,<a href="/works/broad-1914-heart-emperor-true/">The heart of an emperor: or the true Nero</a>,<em>College echoes</em>, vol. 9, 1914, pp. 281</li><li>C. D. Broad,<a href="/works/broad-1914-doctrine-consequences-ethics/">The doctrine of consequences in ethics</a>,<em>The International Journal of Ethics</em>, vol. 24, no. 3, 1914, pp. 293–320. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 17–42</li><li>C. D. Broad,<a href="/works/broad-1914-critical-notice-ch/">Critical notice of Ch. Renouvier,<em>Traité de logique générale et de logique formelle</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 263–268</li><li>C. D. Broad,<a href="/works/broad-1914-review-encyclopaedia-philosophical/">Review of<em>Encyclopaedia of the Philosophical Sciences</em>. Vol. 1.<em>Logic</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 274–277</li><li>C. D. Broad,<a href="/works/broad-1914-review-proceedings-aristotelian/">Review of<em>Proceedings of the Aristotelian Society</em>, 1912-13</a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 277–279</li><li>C. D. Broad,<a href="/works/broad-1914-review-bottinelli-cournot/">Review of E. P. Bottinelli,<em>A. Cournot, métaphysicien de la connaisance</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 287</li><li>C. D. Broad,<a href="/works/broad-1914-review-steinmann-uber/">Review of H. G. Steinmann,<em>Über den Einfluss Newtons auf die Erkenntnistheorie seiner Zeit</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 297–298</li><li>C. D. Broad,<a href="/works/broad-1914-mr-bradley-truth/">Mr. Bradley on truth and reality</a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 349–370</li><li>C. D. Broad,<a href="/works/broad-1914-review-alfred-robb/">Review of Alfred A. Robb,<em>A Theory of Time and Space</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 437–438</li><li>C. D. Broad,<a href="/works/broad-1914-review-leonard-nelson/">Review of Leonard Nelson,<em>Die Theorie des Wahren Interesses und Ihre Rechtliche und Politische Bedeutung</em></a>,<em>The International Journal of Ethics</em>, vol. 24, no. 4, 1914, pp. 463–466</li><li>C. D. Broad,<a href="/works/broad-1914-review-encyclopaedia-philosophical/">Review of<em>Encyclopaedia of the Philosophical Sciences</em>. Vol. 1.<em>Logic</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 274–277</li><li>C. D. Broad,<a href="/works/broad-1914-review-leonid-gabrilovitsch/">Review of Leonid Gabrilovitsch,<em>Über mathematisches Denken und den Begriff der aktuellen Form</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 619–621</li><li>C. D. Broad,<a href="/works/broad-1914-review-couturat-algebra/">Review of L. Couturat,<em>The Algebra of Logic</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 614–615</li><li>C. D. Broad,<a href="/works/broad-1914-review-gustav-heim/">Review of Gustav Heim,<em>Ursache und Bedingung: Widerlegung des Konditionalismus und Aufbau der Kausalitätslehre auf der Mechanik</em></a>,<em>Mind</em>, vol. 23, no. 1, 1914, pp. 623–624</li></ul><h2 id="1915">1915</h2><ul><li>C. D. Broad,<a href="/works/broad-1915-critical-notice-federigo/">Critical notice of Federigo Enriques,<em>The Problems of Science</em></a>,<em>Mind</em>, vol. 24, no. 1, 1915, pp. 94–98</li><li>C. D. Broad,<a href="/works/broad-1915-critical-notice-aliotta/">Critical notice of Aliotta,<em>The Idealistic Reaction against Science</em>, translated by Agnes McCaskill</a>,<em>Mind</em>, vol. 24, no. 1, 1915, pp. 107–112</li><li>C. D. Broad,<a href="/works/broad-1915-critical-notice-bertrand/">Critical notice of Bertrand Russell,<em>Our Knowledge of the External World</em></a>,<em>Mind</em>, vol. XXIV, no. 2, 1915, pp. 250–254</li><li>C. D. Broad,<a href="/works/broad-1915-review-wildon-carr/">Review of H. Wildon Carr,<em>The Philosophy of Change</em></a>,<em>The Hibbert Journal</em>, vol. 13, no. 3, 1915, pp. 448–451</li><li>C. D. Broad and H. J. Duncan,<a href="/works/broad-1915-extracts-refound-mycenean/">Extracts from the re-found Mycenean ``Kronoi''</a>,<em>College Echoes</em>, vol. 10, 1915, pp. 242–243</li><li>C. D. Broad,<a href="/works/broad-1915-phenomenalism/">Phenomenalism</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 15, 1915, pp. 227–251</li><li>C. D. Broad,<a href="/works/broad-1915-critical-notice-bertrand/">Critical notice of Bertrand Russell,<em>Our Knowledge of the External World</em></a>,<em>Mind</em>, vol. XXIV, no. 2, 1915, pp. 250–254</li><li>C. D. Broad,<a href="/works/broad-1915-review-lindemann-trs/">Review of F. and L. Lindemann (trs.),<em>Wissenschaft und Methode</em> by H. Poincaré</a>,<em>Mind</em>, vol. 24, no. 2, 1915, pp. 275</li><li>C. D. Broad,<a href="/works/broad-1915-what-we-mean/">What do we mean by the question: Is our space euclidean?</a>,<em>Mind</em>, vol. 24, no. 4, 1915, pp. 464–480</li><li>C. D. Broad,<a href="/works/broad-1915-critical-notice-robb/">Critical notice of A. A. Robb,<em>A theory of time and space</em></a>,<em>Mind</em>, vol. 24, no. 4, 1915, pp. 555–561</li><li>C. D. Broad,<a href="/works/broad-1915-review-proceedings-aristotelian/">Review of<em>Proceedings of the Aristotelian Society</em>, 1913-14</a>,<em>Mind</em>, vol. 24, no. 3, 1915, pp. 419–421</li></ul><h2 id="1916">1916</h2><ul><li>C. D. Broad,<a href="/works/broad-1916-prevention-war/">The prevention of war</a>,<em>The International Journal of Ethics</em>, vol. 26, no. 2, 1916, pp. 241–257</li><li>C. D. Broad,<a href="/works/broad-1916-review-more-limitations/">Review of L. T. More,<em>The Limitations of Science</em></a>,<em>Mind</em>, vol. 25, no. 1, 1916, pp. 113–116</li><li>C. D. Broad,<a href="/works/broad-1916-review-mach-science/">Review of E. Mach,<em>Science of Mechanics</em></a>,<em>Mind</em>, vol. 25, no. 1, 1916, pp. 118–119</li><li>C. D. Broad,<a href="/works/broad-1916-review-georg-cantor/">Review of Georg Cantor,<em>Contributions to the founding of the theory of transfinite numbers</em></a>,<em>Mind</em>, vol. 25, no. 97, 1916, pp. 120–121</li><li>C. D. Broad,<a href="/works/broad-1916-function-false-hypotheses/">On the function of false hypotheses in ethics</a>,<em>Ethics</em>, vol. 26, no. 3, 1916, pp. 377. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 43–62</li><li>C. D. Broad,<a href="/works/broad-1916-review-proceedings-aristotelian/">Review of<em>Proceedings of the Aristotelian Society</em>, 1914-15</a>,<em>Mind</em>, vol. 25, no. 2, 1916, pp. 270–272</li><li>C. D. Broad,<a href="/works/broad-1916-note-connotation-denotation/">Note on connotation and denotation</a>,<em>Mind</em>, vol. 25, no. 2, 1916, pp. 287–288</li><li>C. D. Broad,<a href="/works/broad-1916-review-johnston-introduction/">Review of G. A. Johnston,<em>An Introduction to Ethics</em></a>,<em>The International Journal of Ethics</em>, vol. 26, no. 4, 1916, pp. 561–564</li><li>C. D. Broad,<a href="/works/broad-1916-nature-geometry-space/">The nature and geometry of space</a>,<em>Mind</em>, vol. XXV, no. 4, 1916, pp. 522–524</li></ul><h2 id="1917">1917</h2><ul><li>C. D. Broad,<a href="/works/broad-1917-hume-theory-credibility/">Hume's theory of the credibility miracles</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 17, no. 1, 1917, pp. 77–94</li><li>C. D. Broad,<a href="/works/broad-1917-critical-notice-george/">Critical notice of George Boole,<em>Collected Logical Works, Vol. II: Laws of Thought</em></a>,<em>Mind</em>, vol. 26, no. 1, 1917, pp. 81–99</li><li>C. D. Broad,<a href="/works/broad-1917-review-david-eugene/">Review of David Eugene Smith (ed.),<em>A Budget of Paradoxes</em> by Augustus De Morgan</a>,<em>Mind</em>, vol. 26, no. 1, 1917, pp. 226–230</li><li>C. D. Broad,<a href="/works/broad-1917-review-richardson-landis/">Review of P. Richardson & E. H. Landis,<em>Numbers Variables, and Mr. Russell's Philosophy</em></a>,<em>Mind</em>, vol. 26, no. 1, 1917, pp. 235–236</li><li>C. D. Broad,<a href="/works/broad-1917-lord-kilsby-impossible/">Lord Kilsby: an impossible tale</a>,<em>College echoes</em>, vol. 12, 1917, pp. 42–43</li></ul><h2 id="1918">1918</h2><ul><li>C. D. Broad,<a href="/works/broad-1918-body-mind/">Body and mind</a>,<em>Monist</em>, vol. 28, no. 2, 1918, pp. 234–258</li><li>C. D. Broad,<a href="/works/broad-1918-critical-notice-proceedings/">Critical notice of<em>Proceedings of the Aristotelian Society. 1916-1917</em></a>,<em>Mind</em>, vol. 27, no. 3, 1918, pp. 366–370</li><li>C. D. Broad,<a href="/works/broad-1918-dukedom-hampshire/">The dukedom of Hampshire</a>,<em>College echoes</em>, vol. 13, 1918, pp. 75–78</li><li>C. D. Broad,<a href="/works/broad-1918-general-notation-logic/">A general notation for the logic of relations</a>,<em>Mind</em>, vol. 27, no. 3, 1918, pp. 284–303</li><li>C. D. Broad,<a href="/works/broad-1918-critical-notice-proceedings/">Critical notice of<em>Proceedings of the Aristotelian Society. 1916-1917</em></a>,<em>Mind</em>, vol. 27, no. 3, 1918, pp. 366–370</li><li>C. D. Broad,<a href="/works/broad-1918-degradation-energie/">Sur la dégradation de l’énergie</a>,<em>Revue de métaphysique et de morale</em>, vol. 25, no. 4, 1918, pp. 527–8</li><li>C. D. Broad,<a href="/works/broad-1918-relation-induction-probability/">On the relation between induction and probability—(part I.)</a>,<em>Mind</em>, vol. XXVII, no. 4, 1918, pp. 389–404</li><li>C. D. Broad,<a href="/works/broad-1918-what-sense-survival/">In what sense is survival desirable?</a>,<em>The Hibbert Journal</em>, vol. 17, no. 1, 1918, pp. 7–20</li><li>C. D. Broad,<a href="/works/broad-1918-critical-notice-bertrand/">Critical notice of Bertrand Russell,<em>Mysticism and Logic, and Other Essays</em></a>,<em>Mind</em>, vol. 27, no. 4, 1918, pp. 484–492</li><li>C. D. Broad,<a href="/works/broad-1918-note/">Note</a>,<em>Mind</em>, vol. 27, no. 4, 1918, pp. 508</li></ul><h2 id="1919">1919</h2><ul><li>C. D. Broad,<a href="/works/broad-1919-mechanical-explanation-its/">Mechanical explanation and its alternatives</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 19, no. 1, 1919, pp. 86–124</li><li>G. Dawes Hicks et al.,<a href="/works/dawes-hicks-1919-symposium-there-knowledge/">Symposium: Is there "knowledge by acquaintance"?</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 2, no. 1, 1919, pp. 159–220</li><li>C. D. Broad,<a href="/works/broad-1919-antecedent-probability-survival/">The antecedent probability of survival</a>,<em>The Hibbert Journal</em>, vol. 17, no. 4, 1919, pp. 561–578</li><li>C. D. Broad,<a href="/works/broad-1919-critical-notice-ernest/">Critical notice of Ernest Jones,<em>Papers on Psycho-Analysis</em></a>,<em>Mind</em>, vol. 28, no. 3, 1919, pp. 340–347</li><li>C. D. Broad,<a href="/works/broad-1919-review-bechhofer-reckitt/">Review of C. E. Bechhofer, M. B. Reckitt, The Meaning of National Guilds.</a>,<em>Ethics</em>, vol. 29, no. 4, 1919, pp. 504–5</li><li>C. D. Broad,<a href="/works/broad-1919-review-jourdain-philosophy/">Review of P. E. B. Jourdain,<em>The Philosophy of Mr. B*rtr*nd R*ss*ll</em></a>,<em>Mind</em>, vol. XXVIII, no. 4, 1919, pp. 485–486</li><li>C. D. Broad,<a href="/works/broad-1919-notion-general-will/">The notion of a general will</a>,<em>Mind</em>, vol. 28, no. 4, 1919, pp. 502–504</li><li>C. D. Broad,<a href="/works/broad-1919-reality/">Reality</a>, in James Hastings (ed.)<em>Encyclopædia of Religion and Ethics</em>, New York, 1919, pp. 587–592</li></ul><h2 id="1920">1920</h2><ul><li>C. D. Broad,<a href="/works/broad-1920-relation-induction-probability/">The relation between induction and probability (Part II.)</a>,<em>Mind</em>, vol. 29, no. 1, 1920, pp. 11–45</li><li>C. D. Broad,<a href="/works/broad-1920-review-whitehead-inquiry/">Review of A. N. Whitehead,<em>An inquiry concerning the principles of natural knowledge</em></a>,<em>The Hibbert journal</em>, vol. 18, no. 2, 1920, pp. 397–406</li><li>C. D. Broad,<a href="/works/broad-1920-critical-notice-lossky/">Critical notice of N. O. Lossky,<em>The Intuitive Basis of Knowledge</em></a>,<em>Mind</em>, vol. 29, no. 3, 1920, pp. 338–344</li><li>C. D. Broad,<a href="/works/broad-1920-romance-new-jerusalem/">A romance of the New Jerusalem</a>,<em>College Echoes</em>, vol. 15, 1920, pp. 88–90</li><li>C. D. Broad,<a href="/works/broad-1920-euclid-newton-einstein/">Euclid, Newton, and Einstein</a>,<em>The Hibbert Journal</em>, vol. 18, no. 3, 1920, pp. 425–458</li><li>C. D. Broad,<a href="/works/broad-1920-critical-notice-whitehead/">Critical notice of A. N. Whitehead,<em>The Principles of Natural Knowledge</em></a>,<em>Mind</em>, vol. 29, no. 2, 1920, pp. 216–231</li><li>C. D. Broad,<a href="/works/broad-1920-review-aristotelian-society/">Review of<em>Aristotelian Society, Supplementary Volume II.: Problems of Science and Philosophy</em></a>,<em>Mind</em>, vol. 29, no. 2, 1920, pp. 232–235</li><li>C. D. Broad,<a href="/works/broad-1920-euclid-newton-einsteina/">"Euclid, Newton, and Einstein". Reply to G. A. Sexton</a>,<em>The Hibbert Journal</em>, vol. 18, no. 4, 1920, pp. 802</li><li>C. D. Broad,<a href="/works/broad-1920-critical-notice-bernard/">Critical notice of Bernard Bosanquet,<em>Implication and Linear Inference</em></a>,<em>Mind</em>, vol. 29, no. 3, 1920, pp. 323–338</li><li>C. D. Broad,<a href="/works/broad-1920-philosophical-aspect-theory/">The philosophical aspect of the theory of relativity</a>,<em>Mind</em>, vol. 29, no. 116, 1920, pp. 430–445</li></ul><h2 id="1921">1921</h2><ul><li>C. D. Broad,<a href="/works/broad-1921-prof-alexander-gifford/">Prof. Alexander's Gifford Lectures (I.)</a>,<em>Mind</em>, vol. 30, no. 117, 1921, pp. 25–39</li><li>C. D. Broad,<a href="/works/broad-1921-review-erwin-freundlich/">Review of Erwin Freundlich,<em>The Foundations of Einstein's Theory of Gravitation</em></a>,<em>Mind</em>, vol. 30, no. 117, 1921, pp. 101–102</li><li>C. D. Broad,<a href="/works/broad-1921-review-whitehead-concept/">Review of A. N. Whitehead,<em>The Concept of Nature</em></a>,<em>The Hibbert Journal</em>, vol. 19, no. 2, 1921, pp. 360–366</li><li>C. D. Broad,<a href="/works/broad-1921-character-cognitive-acts/">The character of cognitive acts</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 21, no. 1, 1921, pp. 140–151</li><li>C. D. Broad,<a href="/works/broad-1921-prof-alexander-gifforda/">Prof. Alexander's Gifford Lectures (II.)</a>,<em>Mind</em>, vol. 30, no. 118, 1921, pp. 129–150</li><li>C. D. Broad,<a href="/works/broad-1921-review-brose-tr/">Review of H. L. Brose (tr.),<em>Space and time in contemporary physics</em> by M. Schlick</a>,<em>Mind</em>, vol. 30, no. 118, 1921, pp. 245–a–245</li><li>C. D. Broad,<a href="/works/broad-1921-review-taggart-nature/">Review of J. M. E. M'Taggart,<em>The Nature of Existence</em></a>,<em>The Hibbert journal</em>, vol. 20, no. 1, 1921, pp. 172–175</li><li>C. D. Broad,<a href="/works/broad-1921-review-clerk-maxwell/">Review of Clerk Maxwell,<em>Matter and Motion</em></a>,<em>Mind</em>, vol. 30, no. 119, 1921, pp. 372</li><li>C. D. Broad,<a href="/works/broad-1921-review-florian-cajori/">Review of Florian Cajori,<em>A History of the Conceptions of Limits and Fluxions in Great Britain from Newton to Woodhouse</em></a>,<em>Mind</em>, vol. 30, no. 119, 1921, pp. 372–b–374</li><li>C. D. Broad,<a href="/works/broad-1921-external-world/">The external world</a>,<em>Mind</em>, vol. 30, no. 120, 1921, pp. 385–408</li><li>C. D. Broad,<a href="/works/broad-1921-review-taggart-nature/">Review of J. M. E. M'Taggart,<em>The Nature of Existence</em></a>,<em>The Hibbert journal</em>, vol. 20, no. 1, 1921, pp. 172–175</li><li>C. D. Broad,<a href="/works/broad-1921-review-cunningham-relativity/">Review of E. Cunningham,<em>Relativity, the Electron Theory, and Gravitation</em></a>,<em>Mind</em>, vol. 30, no. 120, 1921, pp. 490</li><li>C. D. Broad,<a href="/works/broad-1921-review-robb-absolute/">Review of A. A. Robb,<em>The Absolute Relations of Time and Space</em></a>,<em>Mind</em>, vol. 30, no. 120, 1921, pp. 490–b–490</li><li>C. D. Broad,<a href="/works/broad-1921-time/">Time</a>, in James Hastings (ed.)<em>Encyclopædia of Religion and Ethics</em>, New York, 1919, pp. 334–345</li></ul><h2 id="1922">1922</h2><ul><li>C. D. Broad,<a href="/works/broad-1922-critical-notice-keynes/">Critical notice of J. M. Keynes,<em>A treatise on probability</em></a>,<em>Mind</em>, vol. 31, no. 121, 1922, pp. 72–85</li><li>C. D. Broad,<a href="/works/broad-1922-reply-bosanquet-prof/">Reply to B. Bosanquet’s 'Prof. Broad on the external world'</a>,<em>Mind</em>, vol. 31, no. 121, 1922, pp. 122–123</li><li>C. D. Broad,<a href="/works/broad-1922-neglected-method-psychical/">A neglected method of psychical research</a>,<em>Journal of the Society for Psychical Research</em>, vol. 20, 1922, pp. 251–2</li><li>C. D. Broad,<a href="/works/broad-1922-critical-notice-johnson/">Critical notice of W. E. Johnson,<em>Logic</em>, part II</a>,<em>Mind</em>, vol. 31, no. 124, 1922, pp. 496–510</li></ul><h2 id="1923">1923</h2><ul><li>C. D. Broad,<a href="/works/broad-1923-scientific-thought/"><em>Scientific thought</em></a>, London, 1923</li><li>C. D. Broad,<a href="/works/broad-1923-correction/">A correction</a>,<em>Mind</em>, vol. 32, no. 125, 1923, pp. 139</li><li>C. D. Broad,<a href="/works/broad-1923-various-meanings-term/">Various meanings of the term “unconscious”</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 23, no. 1, 1923, pp. 173–198</li><li>C. D. Broad,<a href="/works/broad-1923-critical-notice-whitehead/">Critical notice of A. N. Whitehead,<em>The Principles of Relativity, with Applications to Physical Science</em></a>,<em>Mind</em>, vol. 32, no. 126, 1923, pp. 211–219</li><li>C. D. Broad,<a href="/works/broad-1923-butler-theologian/">Butler as a theologian</a>,<em>The Hibbert Journal</em>, vol. 21, 1923, pp. 637–656. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 202–219</li><li>C. D. Broad,<a href="/works/broad-1923-butler-moralist/">Butler as a moralist</a>,<em>The Hibbert Journal</em>, vol. 21, 1923, pp. 44–63</li><li>C. D. Broad,<a href="/works/broad-1923-review-boscovich-theoria/">Review of R. J. Boscovich,<em>Theoria Philosophiae Naturalis</em></a>,<em>Mind</em>, vol. 23, no. 127, 1923, pp. 374</li></ul><h2 id="1924">1924</h2><ul><li>C. D. Broad,<a href="/works/broad-1924-symposium-critical-realism/">Symposium: "Critical realism: Can the difficulty of affirming a nature independent of mind be overcome by the distinction between essence and existence?"</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 4, no. 1, 1924, pp. 86–129</li><li>C. D. Broad,<a href="/works/broad-1924-mr-johnson-logical/">Mr. Johnson on the logical foundations of science (I.)</a>,<em>Mind</em>, vol. 33, no. 131, 1924, pp. 242–261</li><li>C. D. Broad,<a href="/works/broad-1924-mr-johnson-logical-2/">Mr. Johnson on the logical foundations of science (II.)</a>,<em>Mind</em>, vol. 33, no. 132, 1924, pp. 369–384</li><li>C. D. Broad,<a href="/works/broad-1924-critical-speculative-philosophy/">Critical and speculative philosophy</a>, in J. H. Muirhead (ed.)<em>Contemporary British Philosophy</em>, London, 1924, pp. 75–100</li></ul><h2 id="1925">1925</h2><ul><li>C. D. Broad,<a href="/works/broad-1925-mind-its-place/"><em>The Mind and its Place in Nature</em></a>, London, 1925</li><li>C. D. Broad,<a href="/works/broad-1925-late-dr-mc-taggart/">The late Dr. McTaggart</a>,<em>The Cambridge Review</em>, vol. 46, 1925, pp. 213–214</li><li>C. D. Broad,<a href="/works/broad-1925-late-dr-mc-taggarta/">The late Dr. McTaggart</a>,<em>The Trinity Magazine</em>, vol. 6, 1925, pp. 21–23</li><li>C. D. Broad,<a href="/works/broad-1925-guide-trinity-college/">Guide to Trinity College</a>,<em>The Trinity Magazine</em>, vol. 6, 1925, pp. 32–48</li><li>C. D. Broad,<a href="/works/broad-1925-review-emile-meyerson/">Review of Émile Meyerson,<em>La déduction relativiste</em></a>,<em>Mind</em>, vol. 34, no. 136, 1925, pp. 504–505</li></ul><h2 id="1926">1926</h2><ul><li>C. D. Broad,<a href="/works/broad-1926-philosophy-francis-bacon/"><em>The philosophy of Francis Bacon: an address delivered at Cambridge on the occasion of the Bacon tercentenary, 5 October 1926</em></a>, Cambridge, 1926. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 117–143</li><li>C. D. Broad,<a href="/works/broad-1926-symposium-validity-belief/">Symposium: The validity of the belief in a personal god. II.</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 6, no. 1, 1926, pp. 84–97. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 159–174</li><li>C. D. Broad,<a href="/works/broad-1926-necromantic-tripos/">The necromantic tripos</a>,<em>The Trinity Magazine</em>, vol. 8, 1926, pp. 6–9. Reprinted in Joel Walmsley (ed.),<a href="/works/walmsley-2022-cdbroad/"><em>C. D. Broad: key unpublished writings</em></a>, London, 2022, pp. 360–364</li></ul><h2 id="1927">1927</h2><ul><li>C. D. Broad,<a href="/works/broad-1927-editor-preface/">Editor's preface</a>, in J. Ellis McTaggart (ed.)<em>The nature of existence</em>, Cambridge, 1927, pp. v–vi</li><li>C. D. Broad,<a href="/works/broad-1927-sir-isaac-newton/">Sir Isaac Newton</a>,<em>Proceedings of the British Academy</em>, vol. 13, 1927, pp. 173–202. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 3–28</li><li>C. D. Broad,<a href="/works/broad-1927-john-mc-taggart-ellis/">John McTaggart Ellis McTaggart, 1866--1925</a>,<em>Proceedings of the British Academy</em>, vol. 13, 1927, pp. 307–334. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 70–93</li><li>C. D. Broad,<a href="/works/broad-1928-principles-problematic-induction/">The principles of problematic induction</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 28, no. 1, 1928, pp. 1–46</li><li>C. D. Broad,<a href="/works/broad-1927-interviews-famous-men/">Interviews with famous men</a>,<em>The Trinity Magazine</em>, vol. 8, 1927, pp. 34–36</li></ul><h2 id="1928">1928</h2><ul><li>C. D. Broad,<a href="/works/broad-1928-review-bertrand-russell/">Review of Bertrand Russell,<em>The Analysis of Matter</em></a>,<em>Mind</em>, vol. 37, no. 145, 1928, pp. 88–95</li><li>C. D. Broad,<a href="/works/broad-1928-symposium-time-change/">Symposium: Time and change. III.</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 8, no. 1, 1928, pp. 175–188</li><li>C. D. Broad,<a href="/works/broad-1928-analysis-ethical-concepts/">Analysis of some ethical concepts</a>,<em>Philosophy</em>, vol. 3, no. 11, 1928, pp. 285–299. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 63–81</li></ul><h2 id="1929">1929</h2><ul><li>C. D. Broad,<a href="/works/broad-1929-critical-notice-tennant/">Critical notice of F. R. Tennant,<em>Philosophical Theology, Vol. I.: The Soul and its Faculties</em></a>,<em>Mind</em>, vol. 38, no. 149, 1929, pp. 94–100</li><li>C. D. Broad,<a href="/works/broad-1929-review-johnston-struthers/">Review of W. H. Johnston & L. G. Struthers,<em>Hegel's Science of Logic</em></a>,<em>Mind</em>, vol. 38, no. 151, 1929, pp. 392–393</li></ul><h2 id="1930">1930</h2><ul><li>C. D. Broad,<a href="/works/broad-1930-five-types-ethical/"><em>Five types of ethical theory</em></a>, London, 1930</li><li>C. D. Broad,<a href="/works/broad-1930-dogmas-religion/">Introduction</a>,<em>Some dogmas of religion</em>, London, 1930, pp. xxv–lii</li><li>C. D. Broad,<a href="/works/broad-1930-principles-demonstrative-induction/">The principles of demonstrative induction (II.)</a>,<em>Mind</em>, vol. XXXIX, no. 156, 1930, pp. 426–439</li><li>C. D. Broad,<a href="/works/broad-1930-critical-notice-ewing/">Critical notice of A. C. Ewing,<em>The Morality of Punishment</em></a>,<em>Mind</em>, vol. 49, no. 155, 1930, pp. 347–353</li><li>C. D. Broad,<a href="/works/broad-1930-principles-demonstrative-induction/">The principles of demonstrative induction (II.)</a>,<em>Mind</em>, vol. XXXIX, no. 156, 1930, pp. 426–439</li><li>C. D. Broad,<a href="/works/broad-1930-critical-notice-tennant/">Critical notice of F. R. Tennant,<em>Philosophical Theology, Vol. II.: The World, the Soul, and God</em></a>,<em>Mind</em>, vol. 39, no. 156, 1930, pp. 476–484</li></ul><h2 id="1931">1931</h2><ul><li>C. D. Broad,<a href="/works/broad-1931-war-thoughts-peacetime/"><em>War-thoughts in peace-time</em></a>, London, 1931. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 247–281</li><li>C. D. Broad,<a href="/works/broad-1931-review-stout-studies/">Review of G. F. Stout,<em>Studies in Philosophy and Psychology</em></a>,<em>Mind</em>, vol. 40, no. 158, 1931, pp. 230–234</li><li>C. D. Broad,<a href="/works/broad-1931-review-wright-miracle/">Review of C. J. Wright, Miracle in history and in modern thought</a>,<em>Journal of the Society for Psychical Research</em>, vol. 27, 1931, pp. 84–86</li><li>C. D. Broad, A. S. Eddington, and R. B. Braithwaite,<a href="/works/broad-1931-indeterminacy-indeterminism/">Indeterminacy and indeterminism</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 10, no. 1, 1931, pp. 135–160</li><li>C. D. Broad,<a href="/works/broad-1931-review-taylor-faith/">Review of A. E. Taylor,<em>The Faith of a Moralist</em></a>,<em>Mind</em>, vol. 40, no. 159, 1931, pp. 364–375</li><li>C. D. Broad,<a href="/works/broad-1931-william-ernest-johnson/">William Ernest Johnson, 1858--1931</a>,<em>Proceedings of the British Academy</em>, vol. 17, 1931, pp. 491–514. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 94–114</li><li>C. D. Broad,<a href="/works/broad-1932-mc-taggart-principle-dissimilarity/">McTaggart's principle of the dissimilarity of the diverse</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 32, no. 1, 1932, pp. 41–52</li></ul><h2 id="1932">1932</h2><ul><li>C. D. Broad,<a href="/works/broad-1931-critical-notice-stout/">Critical notice of G. F. Stout,<em>Mind and Matter</em></a>,<em>Mind</em>, vol. 41, no. 163, 1931, pp. 351–370</li><li>C. D. Broad,<a href="/works/broad-1932-review-lowes-dickinson/">Review of G. Lowes Dickinson,<em>J. McT. E. McTaggart</em></a>,<em>Phlosophy</em>, vol. 7, no. 27, 1932, pp. 343–344</li></ul><h2 id="1933">1933</h2><ul><li>C. D. Broad,<a href="/works/broad-1933-examination-mc-taggart-philosophy/"><em>Examination of McTaggart's philosophy</em></a>, Cambridge, 1933</li><li>C. D. Broad,<a href="/works/broad-1933-john-locke/">John Locke</a>,<em>The Hibbert Journal</em>, vol. 31, 1933, pp. 249–267. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 29–48</li><li>C. D. Broad,<a href="/works/broad-1933-prof-hallett-aeternitas/">Prof. Hallett's' Aeternitas (I.)</a>,<em>Mind</em>, vol. 42, no. 166, 1933, pp. 150–169</li><li>C. D. Broad,<a href="/works/broad-1933-prof-hallett-aeternitas/">Prof. Hallett's' Aeternitas (I.)</a>,<em>Mind</em>, vol. 42, no. 166, 1933, pp. 150–169</li><li>C. D. Broad,<a href="/works/broad-1933-review-brailsford-robertson/">Review of T. Brailsford Robertson, A note book</a>,<em>Journal of the Society for Psychical Research</em>, vol. 28, 1933, pp. 112–114</li></ul><h2 id="1934">1934</h2><ul><li>C. D. Broad,<a href="/works/broad-1934-determinism-indeterminism-libertarianism/"><em>Determinism, indeterminism, and libertarianism: an inaugural lecture</em></a>, Cambridge, 1934. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 195–217 and in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 82–105</li><li>C. D. Broad,<a href="/works/broad-1934-goodness-name-simple/">Is “goodness” a name of a simple non-natural quality?</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 34, no. 1, 1934, pp. 249–268. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 106–123</li></ul><h2 id="1935">1935</h2><ul><li>C. D. Broad,<a href="/works/broad-1935-critcal-notice-keeling/">Critcal notice of S. V. Keeling,<em>Descartes</em></a>,<em>Mind</em>, vol. 44, no. 173, 1935, pp. 70–75</li><li>C. D. Broad,<a href="/works/broad-1935-mr-dunne-theory/">Mr. Dunne's theory of time in “An experiment with time"</a>,<em>Philosophy</em>, vol. 10, no. 38, 1935, pp. 168–185. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 68–85</li><li>C. D. Broad,<a href="/works/broad-1935-mechanical-teleological-causation/">Mechanical and teleological causation</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 14, no. 1, 1935, pp. 83–112</li><li>C. D. Broad,<a href="/works/broad-1935-normal-cognition-clairvoyance/">Normal cognition, clairvoyance, and telepathy</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 43, 1935, pp. 397–438. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 27–67</li><li>C. D. Broad,<a href="/works/broad-1935-review-mc-tellis/">Review of J. McT. Ellis McTaggart,<em>Philosophical Studies</em></a>,<em>Mind</em>, vol. 44, no. 176, 1935, pp. 531–532</li></ul><h2 id="1936">1936</h2><ul><li>C. D. Broad,<a href="/works/broad-1936-ought-we-fight/">Ought we to fight for our country in the next war?</a>,<em>The Hibbert Journal</em>, vol. 34, 1936, pp. 357–367. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 232–243 and in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 124–135</li><li>C. D. Broad,<a href="/works/broad-1936-are-there-synthetic/">Are there synthetic a priori truths?</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 15, no. 1, 1936, pp. 102–117</li><li>C. D. Broad,<a href="/works/broad-1937-ostensibly-precognitive-dream/">An ostensibly precognitive dream unfulfilled</a>,<em>Journal of the Society for Psychical Research</em>, vol. 30, 1937, pp. 82–83</li><li>C. D. Broad,<a href="/works/broad-1937-letter-hon-editor/">Letter to the Hon. Editor</a>,<em>Journal of the Society for Psychical Research</em>, vol. 30, 1937, pp. 124</li></ul><h2 id="1937">1937</h2><ul><li>C. D. Broad,<a href="/works/broad-1937-philosophical-implications-foreknowledge/">The philosophical implications of foreknowledge</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 16, no. 1, 1937, pp. 177–209</li><li>C. D. Broad,<a href="/works/broad-1937-critical-notice-mises/">Critical notice of R. von Mises,<em>Wahrscheinlichkeit, Statistik, und Wahrheit</em></a>,<em>Mind</em>, vol. 46, no. 184, 1937, pp. 478–491</li><li>C. D. Broad,<a href="/works/broad-1937-mc-taggart-john-mc-taggart/">McTaggart, John McTaggart Ellis (1866-1925)</a>, in J. R. H. Weaver (ed.)<em>Dictionary of national biography, 1922-1930</em>, London, 1937, pp. 550–551</li></ul><h2 id="1938">1938</h2><ul><li>C. D. Broad,<a href="/works/broad-1938-examination-mc-taggart-philosophy/"><em>Examination of McTaggart's philosophy</em></a>, Cambridge, 1938</li><li>C. D. Broad,<a href="/works/broad-1938-review-stebbing-philosophy/">Review of L. S. Stebbing,<em>Philosophy and the Physicists</em></a>,<em>Philosophy</em>, vol. 13, no. 50, 1938, pp. 221–226.</li><li>C. D. Broad,<a href="/works/broad-1938-henry-sidgwick/">Henry Sidgwick</a>,<em>The Hibbert Journal</em>, vol. 37, 1938, pp. 25–43. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 49–69</li><li>C. D. Broad,<a href="/works/broad-1938-science-psychical-phenomena/">Science and psychical phenomena</a>,<em>Philosophy</em>, vol. 13, no. 52, 1938, pp. 466–475</li><li>C. D. Broad,<a href="/works/broad-1938-henry-sidgwick-psychical/">Henry Sidgwick and psychical research</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 45, 1938, pp. 131–161. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 86–115</li><li>C. D. Broad,<a href="/works/broad-1938-serialism-immortality/">Serialism and immortality</a>,<em>Nature</em>, vol. 142, no. 3607, 1938, pp. 1052–1053</li></ul><h2 id="1939">1939</h2><ul><li>C. D. Broad,<a href="/works/broad-1939-arguments-existence-god/">Arguments for the existence of God. I</a>,<em>The Journal of Theological Studies</em>, vol. 40, no. 1, 1939, pp. 16–30. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 175–189</li><li>C. D. Broad,<a href="/works/broad-1939-arguments-existence-goda/">Arguments for the existence of God. II</a>,<em>The Journal of Theological Studies</em>, vol. os-XL, no. 2, 1939, pp. 156–167. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 189–201</li><li>C. D. Broad,<a href="/works/broad-1939-present-relations-science/">The present relations of science and religion</a>,<em>Philosophy</em>, vol. 14, no. 54, 1939, pp. 131–154. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 220–243</li></ul><h2 id="1940">1940</h2><ul><li>C. D. Broad,<a href="/works/broad-1940-john-albert-chadwick/">John Albert Chadwick, 1899-1939</a>,<em>Mind</em>, vol. 49, no. 194, 1940, pp. 129–131</li><li>C. D. Broad,<a href="/works/broad-1940-conscience-conscientious-action/">Conscience and conscientious action</a>,<em>Philosophy</em>, vol. 15, no. 58, 1940, pp. 115–130. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 244–262 and in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 136–155</li><li>C. D. Broad,<a href="/works/broad-1940-critical-notice-david/">Critical notice of W. David Ross,<em>Foundations of Ethics</em>. The Gifford Lectures delivered in the University of Aberdeen, 1935-1936</a>,<em>Mind</em>, vol. 49, no. 194, 1940, pp. 228–239</li><li>C. D. Broad,<a href="/works/broad-1940-introduction-whately-carington/">Introduction to Mr. Whately Carington's and Mr. Soal's papers</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 46, 1940, pp. 25–33</li><li>C. D. Broad,<a href="/works/broad-1940-physical-analogy/">A physical analogy</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 46, 1940, pp. 150–151</li><li>C. D. Broad,<a href="/works/broad-1940-review-sir-arthur/">Review of Sir Arthur Eddington,<em>The philosophy of Physical Science</em></a>,<em>Philosophy</em>, vol. 15, no. 59, 1940, pp. 301–312</li></ul><h2 id="1941">1941</h2><ul><li>C. D. Broad,<a href="/works/broad-1941-review-samuel-alexander/">Review of Samuel Alexander,<em>Philosophical and Literary Pieces</em></a>,<em>Mind</em>, vol. 50, no. 198, 1941, pp. 197–198</li><li>C. D. Broad,<a href="/works/broad-1941-review-john-laird/">Review of John Laird,<em>Theism and Cosmology</em></a>,<em>Mind</em>, vol. 50, no. 199, 1941, pp. 294–299</li><li>C. D. Broad,<a href="/works/broad-1940-review-hardy-mathematician/">Review of G. H. Hardy,<em>A Mathematician's Apology</em></a>,<em>Philosophy</em>, vol. 16, no. 63, 1940, pp. 323–326</li></ul><h2 id="1942">1942</h2><ul><li>C. D. Broad,<a href="/works/broad-1942-kant-theory-mathematical/">Kant's theory of mathematical and philosophical reasoning</a>,<em>Proceedings of the Aristotelian Society</em>, 1942</li><li>C. D. Broad,<a href="/works/broad-1942-berkeley-argument-material/">Berkeley's argument about material substance</a>,<em>Proceedings of the British Academy</em>, vol. 28, 1942, pp. 119–138</li><li>C. D. Broad,<a href="/works/broad-1942-relations-science-ethics/">The relations between science and ethics</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 42, no. 1, 1942, pp. 100A–100H</li><li>C. D. Broad,<a href="/works/broad-1942-certain-features-moore/">Certain features in Moore’s ethical doctrines</a>, in Schilpp Paul Arthur (ed.)<em>The philosophy of G. E. Moore</em>, Evanston, 1942, pp. 43–67</li><li>C. D. Broad,<a href="/works/broad-1942-review-paul-arthur/">Review of Paul Arthur Schilpp (ed.),<em>The Philosophy of Alfred North Whitehead</em></a>,<em>The Mathematical Gazette</em>, vol. 26, no. 272, 1942, pp. 223–225</li></ul><h2 id="1943">1943</h2><ul><li>C. D. Broad,<a href="/works/broad-1943-mr-saltmarsh/">Mr. H. F. Saltmarsh</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 47, 1943, pp. 151–153</li></ul><h2 id="1944">1944</h2><ul><li>C. D. Broad,<a href="/works/broad-1944-hr-wright-logic/">Hr. von Wright on the logic of induction (I.)</a>,<em>Mind</em>, vol. 53, no. 209, 1944, pp. 1–24</li><li>C. D. Broad,<a href="/works/broad-1944-hr-wright-logica/">Hr. Von Wright on the logic of induction (II.)</a>,<em>Mind</em>, vol. 53, no. 210, 1944, pp. 97–119</li><li>C. D. Broad,<a href="/works/broad-1944-hr-wright-logicb/">Hr. von Wright on the logic of induction (III.)</a>,<em>Mind</em>, vol. 53, no. 211, 1944, pp. 193–214</li><li>C. D. Broad,<a href="/works/broad-1944-critical-notice-julian/">Critical notice of Julian S. Huxley,<em>Evolutionary Ethics</em></a>,<em>Mind</em>, vol. 58, no. 212, 1944, pp. 344–367. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 156–187</li><li>C. D. Broad,<a href="/works/broad-1944-experimental-establishment-telepathic/">The experimental establishment of telepathic precognition</a>,<em>Philosophy</em>, vol. 19, no. 74, 1944, pp. 261–275</li><li>C. D. Broad et al.,<a href="/works/broad-1944-stebbing-memorial-fund/">L. S. Stebbing memorial fund</a>,<em>Mind</em>, vol. LIII, no. 211, 1944, pp. 287–288</li><li>C. D. Broad,<a href="/works/broad-1944-case-apparently-precognitive/">Case: an apparently precognitive incident in a dream-sequence</a>,<em>Journal of the Society for Psychical Research</em>, vol. 33, 1944, pp. 88–90</li><li>C. D. Broad,<a href="/works/broad-1944-new-philosophy-bruno/">The new philosophy: Bruno to Descartes</a>,<em>Cambridge Historical Journal</em>, vol. 8, no. 1, 1944, pp. 36–54. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 144–167</li></ul><h2 id="1945">1945</h2><ul><li>C. D. Broad,<a href="/works/broad-1945-reflections-moralsense-theories/">Some reflections on moral-sense theories in ethics</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 45, no. 1, 1945, pp. 131–166. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 188–222</li><li>C. D. Broad,<a href="/works/broad-1945-professor-stout/">Professor G. F. Stout (1860--1944)</a>,<em>Mind</em>, vol. 54, no. 215, 1945, pp. 285–288</li></ul><h2 id="1946">1946</h2><ul><li>C. D. Broad,<a href="/works/broad-1946-spinoza-doctrine-human/">Spinoza's doctrine of human immortality</a>,<em>Festskrift till Anders Karitz</em>, Uppsala, 1946, pp. 139–148</li><li>C. D. Broad,<a href="/works/broad-1942-leibnizs-last-controversy/">Leibniz's last controversy with the Newtonians</a>,<em>Theoria</em>, vol. 12, no. 3, 1942, pp. 143–168. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 168–191</li><li>C. D. Broad,<a href="/works/broad-1946-review-taylor-does/">Review of A. E. Taylor,<em>Does God Exist?</em></a>,<em>Mind</em>, vol. 55, no. 219, 1946, pp. 173–178</li><li>C. D. Broad,<a href="/works/broad-1946-discussion-prof-rhine/">Discussion of Prof. Rhine's paper and the foregoing comments upon it</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 48, 1946, pp. 20–25</li><li>C. D. Broad,<a href="/works/broad-1946-main-problems-ethics/">Some of the main problems of ethics</a>,<em>Philosophy</em>, vol. 21, no. 79, 1946, pp. 99–117. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 223–246</li></ul><h2 id="1947">1947</h2><ul><li>C. D. Broad,<a href="/works/broad-1947-professor-marc-wogau-theorie/">Professor Marc-Wogau's<em>Theorie der Sinnesdata</em> (I)</a>,<em>Mind</em>, vol. 56, no. 221, 1947</li><li>C. D. Broad,<a href="/works/broad-1947-professor-marc-wogau-theorie/">Professor Marc-Wogau's<em>Theorie der Sinnesdata</em> (I)</a>,<em>Mind</em>, vol. 56, no. 221, 1947</li><li>C. D. Broad,<a href="/works/broad-1947-philosophical-implications-precognition/">Philosophical implications of precognition</a>,<em>The Listener</em>, vol. 37, 1947, pp. 709–710</li><li>C. D. Broad,<a href="/works/broad-1949-relevance-psychical-research/">The relevance of psychical research to philosophy</a>,<em>Philosophy</em>, vol. 24, no. 91, 1949, pp. 291–309</li><li>C. D. Broad,<a href="/works/broad-1947-methods-speculative-philosophy/">Some methods of speculative philosophy</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 21, no. 1, 1947, pp. 1–32</li><li>C. D. Broad,<a href="/works/broad-1947-critical-notice-paul/">Critical notice of Paul Arthur Schilpp,<em>The Philosophy of Bertrand Russell</em></a>,<em>Mind</em>, vol. LVI, no. 224, 1947, pp. 355–364</li><li>C. D. Broad,<a href="/works/broad-1947-review-bertrand-russell/">Review of Bertrand Russell,<em>A History of Western Philosophy, and its Connection with political and social Circumstances from the earliest Times to the present Day</em></a>,<em>Philosophy</em>, vol. 22, no. 83, 1947, pp. 256–264</li></ul><h2 id="1948">1948</h2><ul><li>C. D. Broad,<a href="/works/broad-1948-program-next-ten/">Symposium: a program for the next ten years of research in para-psychology: a letter from Professor C. D. Broad</a>,<em>The Journal of Parapsychology</em>, vol. 12, 1948, pp. 2–6</li><li>C. D. Broad,<a href="/works/broad-1947-alfred-north-whitehead/">Alfred North Whitehead (1861-1947)</a>,<em>Mind</em>, vol. 57, no. 226, 1947, pp. 139–145</li><li>C. D. Broad,<a href="/works/broad-1948-ian-gallie/">Ian Gallie</a>,<em>Mind</em>, vol. 57, no. 228, 1948, pp. 401–402</li><li>C. D. Broad,<a href="/works/broad-1948-review-toksvig-emanuel/">Review of Signe Toksvig,<em>Emanuel Swedenborg</em></a>,<em>The Journal of Parapsychology</em>, vol. 12, 1948, pp. 296–301</li></ul><h2 id="1949">1949</h2><ul><li>C. D. Broad,<a href="/works/broad-1949-review-brown-metaphysical/">Review of A. W. Brown,<em>The Metaphysical Society, 1869--1880</em></a>,<em>Mind</em>, vol. 58, no. 229, 1949, pp. 101–104</li><li>C. D. Broad,<a href="/works/broad-1949-leibniz-predicatein-notion-principle/">Leibniz's Predicate-in-Notion Principle and some of its alleged consequences</a>,<em>Theoria</em>, vol. 15, no. 1, 1949, pp. 54–70</li><li>C. D. Broad, Gilbert Murray, and W. H. Salter,<a href="/works/broad-1949-telepathy/">Telepathy</a>,<em>The Times</em>, no. 51487, 1949, pp. 5</li><li>C. D. Broad,<a href="/works/broad-1949-relevance-psychical-research/">The relevance of psychical research to philosophy</a>,<em>Philosophy</em>, vol. 24, no. 91, 1949, pp. 291–309. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 7–26</li><li>C. D. Broad,<a href="/works/broad-1950-review-whately-carington/">Review of W. Whately Carington,<em>Matter, Mind, and Meaning</em></a>,<em>Philosophy</em>, vol. 25, no. 94, 1950, pp. 275–277</li><li>C. D. Broad,<a href="/works/broad-1949-dr-keynes/">Dr. J. N. Keynes</a>,<em>Nature</em>, vol. 164, 1949, pp. 1031–1032</li></ul><h2 id="1950">1950</h2><ul><li>C. D. Broad,<a href="/works/broad-1950-dr-soal-forskning/"><em>Dr S. G. Soal's forskning i telepati och framtidsförnimmelse</em></a>, Stockholm, 1950</li><li>C. D. Broad,<a href="/works/broad-1950-egoism-theory-human/">Egoism as a theory of human motives</a>,<em>The Hibbert Journal</em>, vol. 48, 1950, pp. 105–114. Reprinted in C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952, pp. 218–231 and in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 247–261</li><li>C. D. Broad,<a href="/works/broad-1950-critical-notice-wm/">Critical notice of Wm. Kneale,<em>Probability and Induction</em></a>,<em>Mind</em>, vol. 59, no. 233, 1950, pp. 94–115</li><li>C. D. Broad,<a href="/works/broad-1950-review-paton-tr/">Review of H. J. Paton (tr.),<em>The Moral Law, or Kant's Groundwork of the Metaphysic of Morals</em></a>,<em>Philosophy</em>, vol. 25, no. 92, 1950, pp. 85–86</li><li>C. D. Broad,<a href="/works/broad-1950-common-fallacies-political/">Some common fallacies in political thinking</a>,<em>Philosophy</em>, vol. 25, no. 93, 1950, pp. 99–113. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 282–297</li><li>C. D. Broad,<a href="/works/broad-1950-some-trinity-philosophers/">Some Trinity philosophers: 1900--1950</a>,<em>Trinity Magazine</em>, 1950, pp. 2–6</li><li>C. D. Broad,<a href="/works/broad-1950-dr-keynes-18521949/">Dr. J. N. Keynes (1852-1949)</a>,<em>The economic journal</em>, vol. 60, no. 238, 1950, pp. 403–407</li><li>C. D. Broad,<a href="/works/broad-1950-immanuel-kant-psychical/">Immanuel Kant and psychical research</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 49, 1950, pp. 79–104. Reprinted in C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953, pp. 116–155</li><li>C. D. Broad,<a href="/works/broad-1950-review-arthur-prior/">Review of Arthur N. Prior,<em>Logic and the Basis of Ethics</em></a>,<em>Mind</em>, vol. 59, no. 235, 1950, pp. 392–395</li><li>C. D. Broad,<a href="/works/broad-1950-review-whately-carington/">Review of W. Whately Carington,<em>Matter, Mind, and Meaning</em></a>,<em>Philosophy</em>, vol. 25, no. 94, 1950, pp. 275–277</li><li>C. D. Broad,<a href="/works/broad-1950-imperatives-categorical-hypothetical/">Imperatives, categorical and hypothetical</a>,<em>The Philosopher</em>, vol. 2, 1950, pp. 62–75</li></ul><h2 id="1951">1951</h2><ul><li>C. D. Broad,<a href="/works/broad-1951-hagerstrom-account-sense/">Hägerström's account of sense of duty and certain allied experiences</a>,<em>Philosophy</em>, vol. 26, no. 97, 1951, pp. 99–113</li><li>C. D. Broad,<a href="/works/broad-1951-logistic-analysis-twofold/">A logistic analysis of the two-fold time theory of the specious present</a>,<em>The British Journal for the Philosophy of Science</em>, vol. 2, no. 6, 1951, pp. 137–141</li><li>C. D. Broad,<a href="/works/broad-1951-locke-doctrine-substantial/">Locke's doctrine of substantial identity & diversity</a>,<em>Theoria</em>, vol. 17, no. 1-3, 1951, pp. 13–26</li></ul><h2 id="1952">1952</h2><ul><li>C. D. Broad,<a href="/works/broad-1952-ethics-history-philosophy/"><em>Ethics and the History of Philosophy</em></a>, Westport, CT, 1952</li><li>C. D. Broad,<a href="/works/broad-1952-elementary-reflexions-senseperception/">Some elementary reflexions on sense-perception</a>,<em>Philosophy</em>, vol. 27, no. 100, 1952, pp. 3–17</li><li>C. D. Broad,<a href="/works/broad-1952-critical-notice-toulmin/">Critical notice of S. E. Toulmin, An examination of the place of reason in ethics</a>,<em>Mind</em>, vol. 61, no. 241, 1952, pp. 93–101</li><li>C. D. Broad,<a href="/works/broad-1952-review-moncrieff-clairvoyanta/">Review of M. M. Moncrieff,<em>The Clairvoyant Theory of Perception: a New Theory of Vision</em></a>,<em>Philosophy</em>, vol. 27, no. 102, 1952, pp. 255–259</li></ul><h2 id="1953">1953</h2><ul><li>C. D. Broad,<a href="/works/broad-1953-religion-philosophy-psychical/"><em>Religion, Philosophy and Psychical Reaseach: Selected Essays</em></a>, New York, 1953</li><li>Axel Hägerström,<a href="/works/hagerstrom-1953-inquiries-nature-law/"><em>Inquiries into the nature of law and morals</em></a>, Uppsala, 1953</li><li>C. D. Broad,<a href="/works/broad-1953-translator-preface/">Translator's preface</a>, in Axel Hägerström (ed.)<em>Inquiries into the nature of law and morals</em>, Uppsala, 1953, pp. vii–ix</li><li>C. D. Broad,<a href="/works/broad-1953-review-bjorkhem-det/">Review of John Björkhem,<em>Det ockulta problemet</em></a>,<em>Journal of the Society for Psychical Research</em>, vol. 37, 1953, pp. 35–38</li><li>C. D. Broad,<a href="/works/broad-1953-phantasms-living-dead/">Phantasms of the living and of the dead</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 50, 1953, pp. 51–66</li><li>C. D. Broad,<a href="/works/broad-1953-berkeley-theory-morals/">Berkeley's theory of morals</a>,<em>Revue Internationale de Philosophie</em>, vol. 7, no. 1-2, 1953, pp. 72–86</li></ul><h2 id="1954">1954</h2><ul><li>C. D. Broad,<a href="/works/broad-1954-letter-editor/">Letter to the editor</a>,<em>Journal of the Society for Psychical Research</em>, vol. 37, 1954, pp. 254–256</li><li>C. D. Broad,<a href="/works/broad-1954-berkeley-denial-material/">Berkeley's denial of material substance</a>,<em>The Philosophical Review</em>, vol. 63, no. 2, 1954, pp. 155</li><li>C. D. Broad,<a href="/works/broad-1954-critical-note-price/">Critical note of H. H. Price,<em>Thinking and Experience</em></a>,<em>Mind</em>, vol. 63, no. 251, 1954, pp. 390–403</li><li>C. D. Broad,<a href="/works/broad-1954-synopses-papers/">Synopses of his papers published in<em>Proceedings of the Aristotelian Society</em> and<em>Aristotelian Society Supplementary Volumes</em>, from 1915 to 1947</a>, in J. W. Scott (ed.)<em>Synopses of his papers published in<em>Proceedings of the Aristotelian Society</em> and<em>Aristotelian Society Supplementary Volumes</em>, from 1915 to 1947</em>, Oxford, 1954, pp. 22–35</li><li>C. D. Broad,<a href="/works/broad-1955-kant-mathematical-antinomies/">Kant's mathematical antinomies: the presidential address</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 55, no. 1, 1955, pp. 1–22</li><li>C. D. Broad,<a href="/works/broad-1954-emotion-sentiment/">Emotion and sentiment</a>,<em>The Journal of Aesthetics and Art Criticism</em>, vol. 13, no. 2, 1954, pp. 203. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 283–301</li></ul><h2 id="1955">1955</h2><ul><li>C. D. Broad,<a href="/works/broad-1955-human-personality-possibility/"><em>Human personality and the possibility of its survival</em></a>, Berkeley and Los Angeles, 1955</li><li>C. D. Broad,<a href="/works/broad-1955-phenomenology-mrs-leonard/">The phenomenology of Mrs Leonard's mediumship</a>,<em>Journal of the American Society for Psychical Research</em>, vol. 49, 1955, pp. 47–63</li></ul><h2 id="1956">1956</h2><ul><li>C. D. Broad,<a href="/works/broad-1956-end-borley-rectory/">The end of Borley Rectory?</a>,<em>The Cambridge Review</em>, vol. 77, 1956, pp. 439–441</li><li>C. D. Broad,<a href="/works/broad-1956-review-luce-sense/">Review of A. A. Luce,<em>Sense without Matter, or Direct Perception</em></a>,<em>Philosophy</em>, vol. 31, no. 117, 1956, pp. 169–171</li><li>C. D. Broad,<a href="/works/broad-1956-halfcentury-psychical-research/">A half-century of psychical research</a>,<em>The journal of parapsychology</em>, vol. 20, no. 4, 1956, pp. 209–228</li></ul><h2 id="1957">1957</h2><ul><li>C. D. Broad,<a href="/works/broad-1957-correspondence-heaven-hell/">Correspondence: Heaven and Hell</a>,<em>The Aryan Path</em>, vol. 28, 1957, pp. 45–46</li><li>C. D. Broad,<a href="/works/broad-1957-local-historical-background/">The local historical background of contemporary Cambridge</a>, in C. A. Mace (ed.)<em>British philosophy in the mid-century</em>, London, 1957, pp. 13–61</li><li>C. D. Broad,<a href="/works/broad-1956-eraita-tuomas-akvinolaisen/">Eräita Tuomas Akvinolaisen filosofian peruskäsitteitä</a>,<em>Ajatus</em>, vol. 19, 1956, pp. 59–79</li><li>C. D. Broad,<a href="/works/broad-1957-dr-tennant/">Dr. F. R. Tennant</a>,<em>The Times</em>, no. 53945, 1957, pp. 13</li></ul><h2 id="1958">1958</h2><ul><li>C. D. Broad,<a href="/works/broad-1958-personal-identity-survival/"><em>Personal identity and survival</em></a>, London, 1958</li><li>C. D. Broad,<a href="/works/broad-1958-philosophy/">Philosophy</a>,<em>Inquiry</em>, vol. 1, no. 2, 1958, pp. 99–129</li><li>C. D. Broad,<a href="/works/broad-1958-review-maurice-cranston/">Review of Maurice Cranston,<em>John Locke, a Biography</em></a>,<em>Mind</em>, vol. 67, no. 268, 1958, pp. 548–554</li><li>C. D. Broad,<a href="/works/broad-1958-gemoore/">G. E. Moore</a>,<em>The Manchester Guardian</em>, no. 34936, 1958, pp. 3</li><li>C. D. Broad,<a href="/works/broad-1958-frederic-robert-tennant/">Frederic Robert Tennant, 1866--1957</a>,<em>Proceedings of the British Academy</em>, vol. 44, 1958, pp. 241–252</li><li>C. D. Broad et al.,<a href="/works/broad-1958-homosexual-acts/">Homosexual acts</a>,<em>The Times</em>, 1958, pp. 11</li></ul><h2 id="1959">1959</h2><ul><li>C. D. Broad,<a href="/works/broad-1959-dreaming-some-implications/">Dreaming, and some of its implications</a>,<em>Proceedings of the Society for Psychical Research</em>, vol. 52, 1959, pp. 53–78</li><li>C. D. Broad,<a href="/works/broad-1959-review-norman-malcolm/">Review of Norman Malcolm, Ludwig Wittgenstein: a memoir</a>,<em>Universities quarterly</em>, vol. 13, no. 3, 1959, pp. 304–306</li><li>C. D. Broad,<a href="/works/broad-1959-autobiography/">Autobiography</a>, in Paul A. Schilpp (ed.)<em>The philosophy of C.D. Broad</em>, New York, 1959, pp. 3–68</li><li>C. D. Broad,<a href="/works/broad-1959-reply-my-critics/">A reply to my critics</a>, in Paul A. Schilpp (ed.)<em>The philosophy of C.D. Broad</em>, New York, 1959, pp. 711–830. Partially reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 302–323</li><li>C. D. Broad,<a href="/works/broad-1959-bacon-experimental-method/">Bacon and the experimental method</a>, in A. C. Crombie (ed.)<em>A Short History of Science: Origins and Results of the Scientific Revolution: A Symposium</em>, Garden City, 1959</li></ul><h2 id="1961">1961</h2><ul><li>C. D. Broad,<a href="/works/broad-1961-moore-latest-published/">G. E. Moore's latest published views on ethics</a>,<em>Mind</em>, vol. 70, no. 280, 1961, pp. 435–457. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 324–350</li><li>C. D. Broad,<a href="/works/broad-1961-humes-doctrine-of/">Hume's doctrine of space</a>,<em>Proceedings of the British Academy</em>, vol. 52, 1961, pp. 161–176</li><li>C. D. Broad,<a href="/works/broad-1961-physicality-psi/">Physicality and psi: a symposium and forum discussion</a>,<em>The Journal of Parapsychology</em>, vol. 25, no. 1, 1961, pp. 13–30</li></ul><h2 id="1962">1962</h2><ul><li>C. D. Broad,<a href="/works/broad-1962-lectures-psychical-research/"><em>Lectures on psychical research: Incorporating the Perrot Lectures given in Cambridge University in 1959 and 1960</em></a>, New York, 1962</li><li>C. D. Broad,<a href="/works/broad-1962-wittgenstein-vienna-circle/">Wittgenstein and the Vienna Circle</a>,<em>Mind</em>, vol. LXXI, no. 282, 1962, pp. 251–b–251</li><li>C. D. Broad,<a href="/works/broad-1962-problem-precognition/">The problem of precognition: notes on Mr. Roll's paper and comments evoked</a>,<em>Journal of the Society for Psychical Research</em>, 1962</li></ul><h2 id="1964">1964</h2><ul><li>C. D. Broad,<a href="/works/broad-1964-obligations-ultimate-derived/">Obligations, ultimate and derived</a>, in Fritjof Lejman (ed.)<em>Festskrift tillägnad professor, juris doktor Karl Olivecrona vid hans avgång från professorämbetet den 30 juni 1964 av kolleger, lärjungar och vänner</em>, Stockholm, 1964. Revised version of C. D. Broad,<a href="/works/broad-1950-imperatives-categorical-hypothetical/">Imperatives, categorical and hypothetical</a>,<em>The Philosopher</em>, vol. 2, 1950, pp. 62–75. Reprinted in David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971, pp. 351–368</li><li>C. D. Broad,<a href="/works/broad-1964-memoir-axel-hagerstrom/">Memoir of Axel Hägerström</a>, in Axel Hägerström (ed.)<em>Philosophy and religion</em>, London, 1964, pp. 15–29</li></ul><h2 id="1967">1967</h2><ul><li>C. D. Broad,<a href="/works/broad-1967-personal-impressions-russell/">Some personal impressions of Russell as a philosopher</a>, in Ralph Schoenman (ed.)<em>Bertrand Russell: philosopher of the century</em>, Boston, 1967, pp. 100–108</li><li>C. D. Broad,<a href="/works/broad-1967-remarks-senseperception/">Some remarks on sense-perception</a>, in Ralph Schoenman (ed.)<em>Bertrand Russell: philosopher of the century</em>, Boston, 1967, pp. 108–121</li><li>C. D. Broad and J. R. Smythies,<a href="/works/broad-1967-notion-precognition/">The notion of 'precognition'</a>, in J. R. Smythies (ed.)<em>Science and ESP</em>, New York, 1967, pp. 165–196. Reprinted in C. D. Broad,<a href="/works/broad-1968-notion-precognitiona/">The notion of ``precognition''</a>,<em>International Journal of Parapsychology</em>, vol. 10, no. 2, 1968, pp. 165–195</li></ul><h2 id="1968">1968</h2><ul><li>C. D. Broad,<a href="/works/broad-1968-induction-probability-and/"><em>Induction, probability, and causation: Selected papers</em></a>, Dordrecht, 1968</li><li>C. D. Broad,<a href="/works/broad-1968-review-anders-wedberg/">Review of Anders Wedberg,<em>Filosofins Historia (från Bolzano till Wittgenstein)</em></a>,<em>The Philosophical Quarterly</em>, vol. 18, no. 72, 1968, pp. 269–271</li><li>C. D. Broad,<a href="/works/broad-1968-bertrand-russell-first/">Bertrand Russell's first forty-two years, in self-portraiture</a>,<em>The Philosophical Review</em>, vol. 77, no. 4, 1968, pp. 455–473</li></ul><h2 id="1970">1970</h2><ul><li>C. D. Broad,<a href="/works/broad-1970-foreword/">Foreword</a>,<em>Bertrand Russell and Trinity</em>, London, 1970</li></ul><h2 id="1971">1971</h2><ul><li>David R. Cheney (ed.),<a href="/works/broad-1971-broads-critical-essays/"><em>Broad's critical essays in moral philosophy</em></a>, London, 1971</li><li>C. D. Broad,<a href="/works/broad-1971-preface/">Preface</a>,<em>Preface</em>, pp. 13–16</li><li>C. D. Broad,<a href="/works/broad-1971-self-others/">Self and others</a>,<em>Self and others</em>, pp. 262–282</li></ul><h2 id="1973">1973</h2><ul><li>C. D. Broad,<a href="/works/broad-1973-bertrand-russell-philosopher/">Bertrand Russell, as philosopher</a>,<em>Bulletin of the London Mathematical Society</em>, vol. 5, no. 3, 1973, pp. 328–341</li></ul><h2 id="1975">1975</h2><ul><li>C. D. Broad,<a href="/works/broad-1975-leibniz-introduction/"><em>Leibniz: An Introduction</em></a>, Cambridge, 1975</li></ul><h2 id="1978">1978</h2><ul><li>C. D. Broad,<a href="/works/broad-1978-kant-introduction/"><em>Kant: an introduction</em></a>, Cambridge, 1978</li></ul><h2 id="1985">1985</h2><ul><li>C. D. Broad,<a href="/works/broad-1985-ethics/"><em>Ethics</em></a>, Dordrecht, 1985</li></ul><h2 id="2022">2022</h2><ul><li>Joel Walmsley (ed.),<a href="/works/walmsley-2022-cdbroad/"><em>C. D. Broad: key unpublished writings</em></a>, London, 2022</li></ul><p><em>With thanks to Gwern, Kenneth Blackwell, and Leonardo Picón.</em></p>
]]></description></item><item><title>'Crucial Considerations and Wise Philanthropy', by Nick Bostrom</title><link>https://stafforini.com/notes/crucial-considerations-and-wise-philanthropy-by-nick-bostrom/</link><pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/crucial-considerations-and-wise-philanthropy-by-nick-bostrom/</guid><description>&lt;![CDATA[<p>On July 9th, 2014, Nick Bostrom gave a talk on &lsquo;Crucial Considerations and Wise Philanthropy&rsquo; (<a href="https://soundcloud.com/gooddoneright/nick-bostrom-crucial-considerations-and-wise-philanthropy">audio</a>|<a href="https://nickbostrom.com/lectures/crucial.pptx">slides</a>) at<a href="/notes/good-done-right/">Good Done Right</a>, a conference on effective altruism held at All Souls College, Oxford. I found the talk so valuable that I decided to transcribe it.</p><hr><p>This talk will build on some of the ideas that Nick Beckstead was<a href="https://podcastaddict.com/episode/https%3A%2F%2Fwww.buzzsprout.com%2F1755269%2Fepisodes%2F8656185-good-done-right-nick-beckstead-how-can-a-long-run-perspective-help-with-strategic-cause-selection.mp3&amp;podcastRSS=https%3A%2F%2Ffeeds.buzzsprout.com%2F1755269.rss&amp;guid=http%3A%2F%2Fearad.io%2F%3Fp%3D84">talking about</a> before lunch. By contrast with his presentation, though, this will not be a well-presented presentation. This is very much a work in progress, and so there&rsquo;s going to be some jump cuts, and some of the bits will be muddled, etc. But I&rsquo;ll look forward to the discussion part of this.</p><h2 id="what-is-a-crucial-consideration">What is a crucial consideration?</h2><p>So I want to talk about this concept of a<em>crucial consideration</em>, which comes up in the kind of work that we&rsquo;re doing a lot. Suppose you&rsquo;re out in the forest, and you have a map and a compass, and you&rsquo;re trying to find some destination. You&rsquo;re carrying some weight, maybe you have a lot of water because you need to hydrate yourself to reach your goal and carry weight, and trying to fine-tune the exact direction you&rsquo;re going. You&rsquo;re trying to maybe figure out how much water you can pour out, to lighten your load without having too little to last to the destination.</p><p>All of these are normal considerations: you&rsquo;re fine-tuning the way you&rsquo;re going to make more rapid progress towards your goal. But then you look more closely at this compass that you have been using, and you realize that the magnet part has actually come loose. This means that the needle might now be pointing in a completely different direction that bears no relation to North: it might have rotated some unknown number of laps or parts of a lap.</p><p>With this discovery, you now completely lose confidence in all the earlier reasoning that was based on trying to get the more accurate reading of where the needle was pointing. This would be an example of a crucial consideration in the context of orienteering. The idea is that there could be similar types of consideration in more important contexts, that throw us off completely what we thought we knew about the overall direction or priority.</p><p>So here are two earlier attempts to describe this idea that I had. So a crucial consideration is:</p><ul><li>a consideration such that if it were taken into account it would overturn the conclusions we would otherwise reach about how we should direct our efforts, or</li><li>an idea or argument that might possibly reveal the need not just for some minor course adjustment in our practical endeavors but a major change of direction or priority.</li></ul><p>Within a utilitarian context, one can perhaps try to explicate it as follows:</p><ul><li>a crucial consideration is a consideration that radically changes the expected value of pursuing some high-level subgoal.</li></ul><p>The idea here is that you have some evaluation standard that is fixed, and you form some overall plan to achieve some high-level subgoal. This is your idea of how to maximize this evaluation standard. A crucial consideration, then, would be a consideration that radically changes the expected value of achieving this subgoal, and we will see some examples of this. Now if you widen the context not limited to some utilitarian context, then you might want to retreat to these earlier more informal formulations, because one of the things that could be questioned is utilitarianism itself. But for most of this talk we will be kind of thinking about that component.</p><p>There are some related concepts that are useful to have. So a<em>crucial consideration component</em> will be an argument, idea or some datum which, while not on its own amounting to a crucial consideration, seems to have a substantial probability of maybe being able to serve a central role within a crucial consideration. It&rsquo;s the kind of thing [of which we would say:] “This looks really intriguing, this could be important; I&rsquo;m not really sure what to make of it at the moment.” On its own maybe it doesn&rsquo;t tell us anything, but maybe there&rsquo;s another piece that, when combined, will suddenly yield an important result. So those kinds of crucial consideration components could be useful to discover.</p><p>Then there&rsquo;s the concept of a<em>deliberation ladder</em>, which would be a sequence of crucial considerations, regarding the same high-level subgoal, where the considerations jostled you in opposing directions. Let&rsquo;s look at some examples of these kinds of crucial consideration ladders that help to illustrate the general predicament.</p><h2 id="should-i-vote-in-the-national-election">Should I vote in the national election?</h2><p>Let&rsquo;s take this question: (A1) “Should I vote in the national election?” At the sort of “level one” of reasoning, you think, “Yes, I should vote to put a better candidate into office.” That clearly makes sense.</p><p>Then you reflect some more: (A2) “But, my vote is extremely unlikely to make a difference. I should not vote but put my time to better use.”</p><p>(These examples are meant to illustrate the general idea; it&rsquo;s not so much I want a big discussion as to these particular examples, they&rsquo;re kind of complicated. But I think they will serve to illustrate the general phenomenon.)</p><p>So, with consideration number two we have gone from “Yes, we should vote. Now that involves making a plan to get to the polling booth,” etc. to “No, I should not vote. I should do something completely different.”</p><p>Then you think, (A3) “Well, although it&rsquo;s unlikely that my vote will make a difference, the stakes are very high: millions of lives are affected by the president. So even if the chance that my vote will be decisive is one in several million, the expected benefit is still large enough to be worth a trip to the polling station.” So, all right, I was going to kick back in front of the television, turn on the football game, and now “Oh, well, actually I should vote”, so we&rsquo;ve gained reversed direction.</p><p>Then you continue to think, (A4) “Well, if the election is not close, then my vote will make no difference. If the election<em>is</em> close, then approximately half of the votes will be for the wrong candidate, implying either that the candidates are of almost exactly the same merit, so it doesn&rsquo;t really matter who wins, or typical voters&rsquo; judgment of the candidates&rsquo; merits is<em>extremely</em> unreliable, and carries almost no signal, so I should not bother to vote.”</p><p>Now you sink back into the comfy sofa and bring out the popcorn or whatever, and then you think, (A5) “Oh, well, of course I&rsquo;m a much better judge of the candidates&rsquo; merits than the typical voter, so I should vote.”</p><p>Okay, on with the coat again. Then you think, (A6) “Well, but psychological studies show that people tend to be overconfident: almost everybody believes themselves to be above average, but they are as likely to be wrong as right about that. So If I am as likely to vote for the wrong candidate as is the typical voter, then my vote would have negligible information to the selection process, and I should not vote.”</p><p>Then we go on: (A7) “Okay, I&rsquo;ve gone through all of this reasoning that really means that I&rsquo;m special, so I should vote.”</p><p>But then, (A8) “Well, if I&rsquo;m so special, then the opportunity cost is really high. I should do something more important.”</p><p>(A9) “But if I don&rsquo;t vote my acquaintances will see that I have failed to support the candidates that we all think are best, they would think me weird and strange, and disloyal, so then that would maybe diminish my influence, which I could otherwise have used for good ends, so I should vote after all.”</p><p>(A10) “But it&rsquo;s important to stand up for one&rsquo;s convictions, to stimulate fruitful discussion. They might think I&rsquo;m like really sophisticated if I explained all this complicated reasoning for voting, and that might increase my influence, which I can then invest in some good cause”, etc.</p><p>There is no reason to think that the ladder would stop there; it&rsquo;s just that we run out of steam at this point. If you end up at some point, you might then wonder, maybe there are further steps on the ladder, and how much reason do you really think you have for the completion you&rsquo;re temporarily at, at that stage?</p><h2 id="should-we-favor-more-funding-for-x-risk-tech-research">Should we favor more funding for x-risk tech research?</h2><p>I want to look at one other example of a deliberation ladder more in the context of technology policy and X-risk. This is a kind of argument that can be run with regard to certain types of technologies: whether we should try to promote them or get more funding for them.</p><p>The X technology here is nanotechnology —this is in fact the example where this line of reasoning originally came up, some parts of this harking back to Eric Drexler&rsquo;s book , where he actually advocated this line of thinking.</p><p>(B1) “So we should fund nanotechnology —this is the”level one” reasoning— because there are many potential future applications: medicine, manufacturing, clean energy, etc. It would be really great if we had all those benefits.”</p><p>(B2) “But it also looks like nanotechnology could have important military applications, and it could be used by terrorists etc., to create new weapons of mass destruction that could pose a major existential threat. So if it&rsquo;s so dangerous,<em>no</em>, maybe we shouldn&rsquo;t really fund it.”</p><p>(B3) “But if this kind of technology is possible, it will almost certainly be developed sooner or later, whether or not<em>we</em> decide to pursue it. (‘We’ being maybe the people in this room or the people in Britain or Western democracies.) If responsible people refrain from developing it, then it will be developed by irresponsible people, which would make the risks even greater, so we should fund it.” (And you can see that with regard to nanotechnology, this seems to work, but the same template could be relevant for evaluating other technologies with upsides and downsides.)</p><p>(B4) “But<em>we</em> —obviously not the people in this room, but, say, advanced democracies— are already ahead in its development, so extra funding would only get us there sooner, leaving us less time to prepare for the dangers. So we should not add funding: the responsible people can get there first even without adding funding to this endeavor.”</p><p>(B5) But then you look around and see virtually no serious effort to prepare for the dangers of nanotechnology, because —and this is basically Drexler&rsquo;s point back in<em>Engines/— serious preparation will begin only /after</em> a massive project is already underway to develop nanotechnology. Only then will people take the prospect seriously. The earlier a serious Manhattan-like project to develop nanotechnology is initiated, the longer it will take to complete, because the earlier you start, the lower the foundation from which you begin. The actual project will then run for longer, and that will then mean more time for preparation: serious preparation only starts when the project starts, and the sooner the project starts, the longer it will take, so the longer the preparation time will be. And that suggests that we should push as hard as we can to get this product launched immediately, to maximize time for preparation.</p><p>But then there are more considerations that should be taken into account:</p><p>(B6) The level of risk will be affected by factors other than the amount of serious preparation that has been made specifically to counter the threat from nanotechnology. For instance, machine intelligence or ubiquitous surveillance might be developed before nanotechnology, eliminating or mitigating the risks of the latter. Although these other technologies may pose great risks of their own, those risks would have to be faced anyway &mdash;and there&rsquo;s a lot more that can be said: this is against the background, like a discourse about these kinds of things that has been going on&mdash; and nanotechnology would not really reduce these other risks, like the risks from AI, for example. So the preferred sequence is that we get superintelligence or ubiquitous surveillance before nanotechnology, and so we should oppose extra funding for nanotechnology even though superintelligence and ubiquitous surveillance might be very dangerous on their own, including posing existential risks. Given certain background assumptions about the<a href="https://www.nickbostrom.com/papers/future.pdf">technological completion conjecture</a> &mdash;that in the fullness of time, unless civilization collapses, all possible general useful technologies will be developed&mdash; these dangers will have to be confronted, and all our choice really concerns is the sequence in which we confront these. And it&rsquo;s better to confront superintelligence before nanotechnology because superintelligence can obviate the nanotechnology risk, but not<em>vice versa</em>.</p><p>(B7) However, if people oppose extra funding for nanotechnology, then people working in nanotechnology will dislike those people who are opposing it. (This is also a point from Drexler&rsquo;s book.) Other scientists might regard these people who oppose funding for nanotechnology as being anti-science and this will reduce our ability to work with these scientists, hampering our efforts on more specific issues —efforts that stand a better chance of making a material difference than any attempts on our part to influence the level of national funding for nanotechnology. So we should not oppose nanotechnology. That is, rather than opposing nanotechnology in an attempt to slow it down a little bit —and we are a small group, we can&rsquo;t make much difference— we should work with the nanotechnology scientists, be their friend, and then maybe try to influence on the margin, so that they develop nanotechnology in a slightly different way or add some safeguards, and stuff like that.</p><p>Again, there is no clear reason to think that we have reached the limit of the level of deliberation that we could apply to this. So it&rsquo;s disconcerting because it looks like the practical upshot keeps switching back and forth as we look more deeply into the search tree. And we might wonder what it is about, and I think that these kinds of deliberation ladders are crucial considerations: they seem to be particularly likely to turn up when one is trying to be a thoroughgoing utilitarian, and one really takes these big-picture questions seriously.</p><h2 id="crucial-considerations-and-utilitarianism">Crucial considerations and utilitarianism</h2><p>There are some possible reasons for why that might be. If we compare, for example, the domain of application “utilitarianism” to another domain of application, say if you have an ordinary human preference function —you want a flourishing life, a healthy family, a successful career and some relaxation: a typical human&rsquo;s value— if you&rsquo;re trying to satisfy those, it looks less likely that you will encounter a large number of these crucial considerations. Why might that be?</p><p>One possible explanation is that we have more knowledge and experience of human life at the personal level. Billions of people have tried to maximize an ordinary human utility function and have received a lot of feedback and a lot of things have been tried out. So we already know some of the basics like, if you want to go on for decades, it&rsquo;s a good idea to eat, things like that. They&rsquo;re not suddenly going to be discovered, right? And maybe our preferences in the first place have been shaped to more or less fit with the kind of opportunities we can cognitively exploit in the environment by evolution. So we might not have some weird preference that there was no way that we could systematically satisfy. Whereas with utilitarianism, the utilitarian preference, as it were, extends far and wide beyond our familiar environment, including into the cosmic commons and billions of years into the future and super advanced civilizations: they do matter from the utilitarian perspective, and matter a lot. Most of what the utilitarian preference cares about is stuff that we have no familiarity with.</p><p>Another possible source of crucial considerations with regard to utilitarianism is difficulties in understanding the goal itself that is postulated by utilitarianism. For example, if one tries to think about how to apply utilitarianism to a world that has a finite probability of being infinite, you run into difficulties in terms of how to measure different infinite magnitudes and still seeing how we could possibly make any difference to it. I have a big paper about that,<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and we don&rsquo;t need to go into it here. There are some other issues that consist in trying actually to articulate utilitarianism to deal with all these possible cases.</p><p>The third possible reason here is that one might think that we are kind of close &mdash;not super close, but close&mdash; to some pivot point of history. That means that we might have special opportunities to influence the long-term future now. And we&rsquo;re still far enough away from this, that it&rsquo;s not obvious what we should do to have the maximally beneficial impact on the future, but still close enough that we can maybe begin to perceive some contours of the apparatus that will shape the future. So, for example, if you think that superintelligence might be this pivot point, or one of them (there may be x-risk pivot points as well that we will confront in this century), then it might just be that we are barely just beginning to get the ability to think about those things, which introduces a whole set of new considerations that might be very important. This could affect the personal domain as well. It&rsquo;s just like with an ordinary person&rsquo;s typical utility function: they probably don&rsquo;t place a million times more value on living for a billion years than living for a hundred years, or a thousand times more value on raising a thousand children than on raising one child. So even though the future still exists, it just doesn&rsquo;t weigh as heavily in a normal human utility function as it does for the utilitarian.</p><p>One might also argue that we have recently discovered some key exploration tools that enable us to make these very important discoveries about how to be a good utilitarian, and we haven&rsquo;t yet run the course with these tools, so we keep turning up fundamental new important discoveries using these exploration tools. That&rsquo;s why there seem to be so many crucial considerations being discovered. We might talk a little bit about some of those later in the presentation.</p><h2 id="evaluation-functions">Evaluation functions</h2><p>Now let me come at this from a slightly different angle. In chess, the way we would ideally play is you would start by thinking the possible moves that you could make, then the possible responses that your opponent could make, and your responses to those responses. Ideally, you would think that through all the way to the end state, and then just try to select a first move that would be best from the point of view of winning when you could calculate through the entire game tree. But that&rsquo;s computationally infeasible because the tree branches too much: you have an exponential number of moves to consider. So what you instead have to do is to calculate explicitly some number of plies ahead. Maybe a dozen plies ahead or something like that. But at that point, your analysis has to stop, and what you do is to have some evaluation function which is relatively simple to compute, which tries to look at the board state that could result from this sequence of six moves and countermoves, and in some rough and ready way try to estimate how good that state is. A typical chess evaluation function might look something like this:</p><blockquote><p>Evalchess = (c1 × material) + (c2 × mobility) + (c3 × king safety) + (c4 × center control) + &hellip;</p></blockquote><p>You have some term that evaluates how much material we have, like having your queen and a lot of pieces is beneficial, the opponent having few of those is also beneficial &mdash;we have some metric like a pawn is worth one and queen is worth, I don&rsquo;t know, 11 or something like that. So you weigh that up &mdash;that&rsquo;s one component in the evaluation function. Then maybe consider how mobile your pieces are. If they&rsquo;re all crammed in the corner, that&rsquo;s usually an unpromising situation, so you have some term for that. King safety [is another component in the function]. Center control adds a bit of value: if you control the middle of the board, we know from experience that tends to be a good position. So what you do is calculate explicitly some number of steps ahead and then you have this relatively unchanging evaluation function that is used to figure out which of these initial games that you could play would be resulting in the most beneficial situation for you. These evaluation functions are mainly derived from human chess masters who have a lot of experience playing with the game. And the parameters, the weight assigned to these different features, might also be learned by machine intelligence.</p><p>We do something analogous to that in other domains. In a typical traditional public policy, social welfare economists might think that you need to maximize some social welfare function which might take a form somewhat like this:</p><blockquote><p>Evalpublic policy = (c1 × GDP) + (c2 × employment) + (c3 × equality) + (c4 × environment) + &hellip;</p></blockquote><p>GDP? Yes, we want more GDP, but we also have to take into account the amount of unemployment, maybe the amount of equality or inequality, some factor for the health of the environment. It might not be that whatever we write there is exactly the thing that is equivalent to moral goodness fundamentally considered. But we know that these things tend to be good, or we think so. This is a useful approximation of true value that might be more tractable in a practical decision-making context. One thing I can ask, then, is if there is something similar to that for moral goodness.</p><blockquote><p>Evalmoral_goodness = ?</p></blockquote><p>You want to do the morally best thing you can do, but to calculate all of these out from scratch just looks difficult or impossible to do in any one situation. You need some kind of more stable principles that you can use to evaluate different things you could do. So here we might look at the more restricted version of utilitarianism and we can wonder what we might put in there.</p><blockquote><p>Evalutilitarian = ?</p></blockquote><p>So here we can hark back to some of the things Beckstead talked about. If we plot capacity, which could be sort of level of economic development and technological sophistication —stuff like that— on one axis and time on the other, my view is that the human condition is a kind of metastable region on this capability axis:</p><figure><a href="/ox-hugo/future-technological-capacity-graph.png" target="_blank" rel="noopener"><img src="/ox-hugo/future-technological-capacity-graph.png" alt="A graph of capacity over time depicting various existential outcomes. Branches lead to extinction, short-term viability, singleton sustainability, or an upper limit labeled cosmic endowment."/></figure><p>You might fluctuate inside for a while, but the longer the time scale you&rsquo;re considering, the greater the chance that you will exit that region in either the downwards direction and go extinct &mdash;we have too few resources below the minimum viable population size and go extinct (and that&rsquo;s one attractor state: once you&rsquo;re extinct, you tend to stay extinct)&mdash; or in the upwards direction: we get through to technological maturity, start a colonization process and the future of earth-originating intelligent life might then just be this bubble that expands at some significant fraction of the speed of light and eventually accesses all the cosmological resources that are in principle accessible from our starting point. So it&rsquo;s a finite quantity: because of the positive cosmological constant, it looks like we can only access a finite amount of stuff. But once you&rsquo;ve started that, once you&rsquo;ve set off an intergalactic empire, it looks like it could just keep going with high probability to this natural conclusion.</p><p>From that perspective we can define this concept of an existential risk as one that fails to realize the potential for realizing value that you could gain by accessing the cosmological commons, either by going extinct or by maybe accessing all the cosmological commons but then failing to use them for beneficial purposes, because your values are corrupted or something like that.</p><p>That suggests this MAXIPOK principle that Beckstead also mentioned: “Maximize the probability of an OK outcome”:</p><blockquote><p>arg max [- P(existential catastrophe / action)]</p></blockquote><p>It&rsquo;s clearly, at best, a rule of thumb: it&rsquo;s not meant to be a valid moral principle that&rsquo;s true in all possible situations. It&rsquo;s not that. In fact, if you want to go away from the original principle you started [with] to something practically tractable, I think you have to make it contingent on various empirical assumptions. That&rsquo;s the trade-off there: you want to make as weak assumptions as you can and still move it as far as possible towards being tractable as you can. I think this is something that makes a reasonable compromise there. In other words, take the action that minimizes the integral of existential risk that humanity will confront. It will not always give you the right answer, but it&rsquo;s a starting point. There are different things to the ones that Beckstead mentioned: there could be other scenarios where this would give the wrong answer. If you thought that there was a big risk of some sort of hyper existential catastrophe like some sort of hell scenario, then you might want to increase the level of existential risks slightly in order to decrease the risk that there would not just be an existential catastrophe but hyper existential catastrophe. Other things that could come into it are trajectory changes that are less than drastic and just shift slightly.</p><p>For present purposes, we could consider the suggestion of using the Maxipok rule as our attempt to define the value function for utilitarian agents.</p><blockquote><p>Evalutilitarian ≈ MAXIPOK</p></blockquote><p>Then the question becomes, “If you want to minimize existential risk, what should you do?”</p><blockquote><p>EvalMAXIPOK = ?</p></blockquote><p>That is still a very high-level objective. We still need to do more work to break that down into more tangible components.</p><p><em>[Slide: A conceptual graphic entitled &lsquo;Dynamic Sustainability&rsquo; with axes labelled &lsquo;Technology&rsquo;, &lsquo;Coordination&rsquo;, and &lsquo;Insight&rsquo;, depicting humanity&rsquo;s current position with a rocket, dangerous regions with lightning, and a safe region indicated by a sun.]</em></p><p>So another little jump cut. I&rsquo;m not exactly sure how well this fits in with the rest of the presentation —I have this nice slide from another presentation. Maybe it&rsquo;s a different way of saying some of what I just said: that instead of thinking about sustainability as is commonly known, as this static concept that is as a stable state that we should try to approximate, where we use up no more resources than are regenerated by the natural environment, we need, I think, to think about sustainability in dynamical terms, where instead of reaching a state, we try to enter and stay on a trajectory that is indefinitely sustainable in the sense that we can continue to travel on that trajectory indefinitely, and it leads in a good direction.</p><p>An analogy here would be if you have a rocket. One stable state for a rocket is on the launch pad: it can stand there for a long time. Another stable state is if it&rsquo;s up in space, it can continue to travel for an even longer time, perhaps, since it doesn&rsquo;t rust and stuff. But in midair, you have this unstable system. I think that&rsquo;s where humanity is now: we&rsquo;re in midair. The static sustainability concept suggests that we should reduce our fuel consumption to the minimum that just enables us to hover there. Thus, maybe prolong the duration in which we could stay in our current situation, but what we perhaps instead should do is maximize the fuel consumption so that we have enough thrust to reach escape velocity. (And that&rsquo;s not a literal argument for burning as much fossil fuels as possible: it&rsquo;s just a metaphor.)</p><p>But the point here is that there are these several different axes of seeing that to have a utopia, to have the best possible condition, we need super advanced technology —to be able to access the cosmic commons, to be able to cure all the diseases that plague us, etc. I think to have the best possible world, you&rsquo;ll also need a huge amount of insight and wisdom, and a large amount of coordination so as to avoid using high technology to wage war against one another, and so forth.</p><blockquote><p>EvalMAXIPOK = f (wisdom, coordination, differential tech development, &hellip;)</p></blockquote><p>Ultimately, we would want a state where we have huge quantities of each of these three variables, but that leaves open the question of what we want more from our current situation. It might be, for example, that we would want more coordination and insight before we have more technology of a certain type. So that before we have various powerful technologies, we would first want to make sure that we have enough peace and understanding to not use them for warfare, and that we have enough insight and wisdom not to accidentally blow ourselves up with them. A superintelligence, clearly, seems to be something you want in utopia &mdash;it&rsquo;s a very high level of technology&mdash;, but we might want a certain amount of insight before we develop superintelligence, so we can develop it in the correct way. Anyway, one can begin to think about, as in analogy with the computer chess situation, if there are different features that one could possibly think of as components of this evaluation function for the utilitarian (the MAXIPOK). This principle of differential technological development suggests “retard the development of dangerous and harmful technologies &mdash;the ones that raise existential risk, that is&mdash; and accelerate technologies that reduce existential risks”, so that it&rsquo;s just this component. This is our first sketch, it&rsquo;s not a final answer, but one might think we want a lot of wisdom, we want a lot of international peace and cooperation, and with regard to technologies, it gets a little bit more complicated: we want faster progress in some technology areas, perhaps, and slower in others. I think those are three broad kinds of things one might want to put into one&rsquo;s evaluation function.</p><h2 id="cause-selection-vs.-signature-determination">Cause selection vs. signature determination</h2><p>This suggests that one thing to be thinking about in addition to interventions or causes, is the signature of different kinds of things. So an intervention should be sort of high leverage, and a cause area should promise high leverage interventions. It&rsquo;s not enough that something you could do would do good, you also want to think hard about how much good it could do relative to other things you could do. There is no point in thinking about causes without thinking about how you see all the low-hanging fruits that you could access. So a lot of the thinking is about that. But when we&rsquo;re moving at this more elevated plane, this high altitude where there are these crucial considerations, then it also seems to become valuable to think about determining the sign of different basic parameters, maybe even when we are not sure how we could affect them &mdash;the sign being, basically, “Do we want more or less of it?”. We might initially bracket questions as to leverage here, because to first orient ourselves in the landscape we might want to postpone that question a little bit in this context. But a good signpost &mdash;that is a good parameter of which we would like to determine the signature&mdash; would have to be visible from afar. That is, if we define some quantity in terms that still make it very difficult for any particular intervention to say whether it contributes positively or negatively to this quantity that we just defined, then it&rsquo;s not so useful as a signpost. So, “maximize expected value”, say, that is the quantity we could define. It just doesn&rsquo;t help us very much, because whenever you try to do something specific you&rsquo;re still virtually as far away as you are. But on the other hand, if you set some more concrete objective, like “maximize the number of people in this room”, or something like that, we can now easily tell like how many people there are, we have ideas of how we could maximize it, so any particular action we think of we might easily see how it bears on this objective of maximizing the people in this room. However, we might feel it&rsquo;s very difficult to get strong reasons for knowing whether more people in this room is better, or whether there is presumably some inverse U curve there. A good signpost should strike a reasonable compromise between being visible from afar and also being such that we can have strong reason to be sure of its sign.</p><h2 id="some-tentative-signposts">Some tentative signposts</h2><p>Here are some very tentative signposts, and they&rsquo;re tentative in my own view, and I guess there might also be a lot of disagreement among different people, so these are more areas for investigation. But it might be useful just to show how one might begin to think about it.</p><p><em>Do we want faster progress in computer hardware or slower progress?</em> My best guess there is that we want slower progress. And that has to do with the risks from the machine intelligence transition. Faster computers would make it easier to make AI, which (a) would make them happen sooner probably, which seems perhaps bad in itself because it leaves less time for the relevant kind of preparation, of which there is a great need; and (b) might reduce the skill level that would be required to produce AI. So with a ridiculously large amount of computing power you might be able to produce AI without really knowing much about what you&rsquo;re doing. When you are hardware-constrained you might need more insight and understanding, and it&rsquo;s better that AI be created by people who have more insight and understanding.</p><p>This is not by any means a knockdown argument, because there are other existential risks. If you thought that we are about to go extinct anytime soon, because somebody will develop nanotechnology, then you might want to try the AI wildcard as soon as possible. All things considered this is my current best guess, but these are the kinds of reasoning that one can engage in.</p><p><em>Whole brain emulation?</em> We did a long, big analysis of that.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> More specifically, not whether we want to have whole brain emulation, but whether we want to have more or less funding for whole brain emulation, more or less resources for developing that. This is one possible path towards machine superintelligence, and for complicated reasons, my guess is “No”, but that&rsquo;s even more uncertain, and we have a lot of different views in our research group on that. (In the discussion, if anybody is interested in one particular one, we can zoom in on that.)</p><p><em>Biological cognitive enhancement of humans?</em> My best guess there is that we want faster progress in that area.</p><p>I talk more about these three in the book and also about artificial intelligence.<em>Artificial intelligence?</em> I think we want AI probably to happen a little bit slower than it&rsquo;s likely to do by default.</p><p>Another question is:<em>If there is one company or project or team that will develop the first successful AI, how much ahead does one want that team to be to the second team that is trying to do it?</em> My best guess is that we want it to have a lot of lead, many years ideally, to enable them to slow down at the end to implement more safety measures, rather than being in the tight tech race.</p><p><em>Solutions to the control problem for AI?</em> I think we want faster progress in that, and that&rsquo;s one of our focus areas, and some of our friends from the<a href="https://intelligence.org/">Machine Intelligence Research Institute</a> are here, also working hard on that. Let&rsquo;s move away from the AI domain.</p><p><em>The effective altruism movement?</em> I think that looks very good in many ways, robustly good, to have faster, better growth in that.</p><p><em>International peace and cooperation?</em> Looks good.</p><p><em>Synthetic biology?</em> I think it looks bad. We haven&rsquo;t thought as carefully about that, so that could change, but it looks like there could be x-risks from that, although [it looks] also beneficial. Insofar as it might enable improvements in cognitive enhancement, there&rsquo;ll be a kind of difficult trade-off.</p><p><em>Nanotechnology?</em> I think it looks bad: we want slower progress towards that.</p><p><em>Economic growth?</em> Very difficult to tell the sign of that, in my view. And within a community of people that have thought hard about that there are, again, different guesses as to the sign of that.</p><p><em>Small and medium-scale catastrophe prevention?</em> Global catastrophic risks falling short of existential risk, it&rsquo;s very difficult to know the sign of that. Here we are bracketing leverage at all: even just knowing whether we would want more or less, if we could get it for free, it&rsquo;s non-obvious. On the one hand, small-scale catastrophes might create an immune response that makes us better, puts in place better safeguards, and stuff like that, that could protect against really big stuff. If we&rsquo;re thinking about medium-scale catastrophes that could cause civilizational collapse, large by ordinary standards but only medium-scale in comparison to existential catastrophes, which are large in this context, again, [it is] not totally obvious what the sign of that is: there&rsquo;s a lot more work to be done to try to figure that out. If recovery looks very likely, you might then have guesses as to whether the recovered civilization would be more likely to avoid existential catastrophe having gone through this experience or not.</p><p>A lot more work is needed, but these are the parameters that one can begin to think about. One doesn&rsquo;t realize just how difficult it is: even some parameters that from an ordinary common-sense point of view seem kind of obvious, actually turn out to be quite non-obvious once you start to think through the way that they&rsquo;re all supposed to fit together. Suppose you&rsquo;re an administrator here in Oxford, you&rsquo;re working in the Computer Science department, and you&rsquo;re the secretary there. Suppose you find some way to make the department run slightly more efficiently: you create this mailing list so that everybody can, when they have an announcement to make, just email it to the mailing list rather than having to put in each person individually in the address field. And that&rsquo;s a useful thing &mdash;that&rsquo;s a great thing: it didn&rsquo;t cost anything, other than a one-off cost, and now everybody can go about their business more easily. From this perspective, it&rsquo;s very non-obvious whether that is, in fact, a good thing. It might be contributing to AI: that might be the main effect of this, other than the very small general effect on economic growth, which is questionable. And it might probably be that you have made the world worse in expectation by making this little efficiency improvement. So this project of trying to think through this it&rsquo;s in a sense a little bit like the Nietzschean<em><a href="https://en.wikipedia.org/wiki/Transvaluation_of_values">Umwertung aller Werte</a></em> (the revaluation of all values) project that he never had a chance to complete, because he went mad before he could start.</p><h2 id="possible-areas-with-additional-crucial-considerations">Possible areas with additional crucial considerations</h2><ul><li>Counterfactual trade</li><li>Simulation stuff</li><li>Infinite paralysis</li><li>Pascalian muggings</li><li>Different kinds of aggregative ethics (total, average, negative)</li><li>Information hazards</li><li>Aliens</li><li>Baby universes</li><li>Other kinds of moral uncertainty</li><li>Other game theory stuff</li><li>Pessimistic metainduction; epistemic humility; anthropics</li><li>Insects, subroutines</li></ul><p>So, these are some kinds of areas —I&rsquo;m not going to go into all of these, I&rsquo;m just giving examples of the kinds of areas where today it looks like there might still be crucial considerations. This is not an exhaustive list by any means, and we can talk more about some of those. They kind of go from more general and abstract and powerful, to more specific and understandable by ordinary reasoning.</p><p>To just pick an example:<em>insects</em>. If you are a classical utilitarian, this consideration arises within the more mundane —so we&rsquo;re setting aside these cosmological commons and just thinking about here on Earth. If insects are sentient then maybe the amount of sentience in insects is very large because there are so very, very many of them. So that maybe the effect of our policies on insect well-being might trump the effect of our policies on human well-being or animals in factories and stuff like that. I&rsquo;m not saying it does, but it&rsquo;s a question that is non-obvious and that could have a big impact.</p><p><em>Subroutines</em>. With certain kinds of machine intelligence there are processes, like reinforcement learning algorithms and other subprocesses within the AI. Maybe some of those could turn out to have moral status in some way. Maybe there will be hugely large numbers of runs of these subprocesses, so that if it turns out that some of these kinds of things count for something, then maybe the numbers again would come to dominate. Each of these is a whole workshop on its own, so it&rsquo;s not something we can go into.</p><h2 id="some-partial-remedies">Some partial remedies</h2><p>So what can one do if one suspects that there might be these crucial considerations, some of them not yet discovered? I don&rsquo;t have a crisp answer to that. Here are some<em>prima facie</em> plausible things one might try to do a little bit of:</p><ul><li><em>Don&rsquo;t act precipitously, particularly in ways that are irrevocable.</em></li><li><em>Invest in more analysis to find and assemble missing crucial considerations.</em> That&rsquo;s why I&rsquo;m doing the kind of work that I&rsquo;m doing, and the rest of us are also involved in that enterprise.</li><li><em>Take into account that expected value changes are probably smaller than they appear when thinking about this big.</em> If you are a utilitarian, let&rsquo;s say you think of this new argument that has this radical implication for what you should be doing, the first instinct might be to radically change your expected utility of different practical policies in light of this new insight. But maybe when you reflect on the fact that there are new crucial considerations being discovered every once in a while, maybe you should still change your expected value, but not as much as it seems you should at first sight. You should reflect on this at the meta level.</li><li><em>Use parliamentary/mixed models.</em> If we widen our purview to not just consider utilitarianism, as we should consider things from a more general unrestricted normative perspective, then it looks like something like the Parliamentary Model<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> for taking normative uncertainty into account looks fairly robust. This is the idea that if you are unsure as to which moral theory is true, then you should assign probabilities to different moral theories and imagine that there were a kind of parliament where each moral theory got to send delegates to that parliament in proportion to their probability. Then in this imaginary parliament, these delegates from the different moral theories discuss and compromise and work out what to do. And then you should do what that moral parliament of yours would have decided, as a sort of metaphor. The idea is that, other things equal, the more probability a moral theory has, the greater its say in determining your actions, but there might also be these trades between different moral theories which I think Toby talked about in<a href="https://soundcloud.com/gooddoneright/toby-ord-moral-trade">his presentation</a>. This is one metaphor for how to conceive of those traits. It might not be exactly the right way to think about fundamental normative uncertainty, but it seems to be close in many situations, and it seems to be relatively robust in the sense of being unlikely to have a totally crazy implication.</li><li><em>Focus more on near-term and convenient objectives.</em> To the extent that one is despairing about having any coherent view about how to go about maximizing aggregative welfare in this cosmological context, the greater it seems the effective voice of other types of things that one might be placing weight on. So if you&rsquo;re partly an egoist and partly an altruist, then if you say that the altruistic component is on this kind of deliberation ladder then maybe you should go more with the egoistic part, until and unless you can find stability in your altruistic deliberations.</li><li>And then this general idea of maybe<em>focus on developing our capacity as a civilization to wisely deliberate on these types of things</em>: to build up our capacity, rather than pursuing very specific goals —and by capacity in this context it looks like perhaps we should focus less on powers and more on the propensity to use powers well. This is still quite vague, but something in that general direction seems to be robustly desirable. Certainly, you could have a crucial consideration that&rsquo;s turned up to show that that was the wrong thing to do, but it still looks like a reasonable guess.</li></ul><p>That&rsquo;s it. Thanks.</p><div class="footnotes" role="doc-endnotes"><hr><ol><li id="fn:1"><p>Nick Bostrom,<a href="/works/bostrom-2016-infinite-ethics/">Infinite ethics</a>,<em>Analysis and metaphysics</em>, vol. 10, 2016, pp. 9–59&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li><li id="fn:2"><p>Anders Sandberg and Nick Bostrom,<a href="/works/sandberg-2008-whole-brain-emulation/"><em>Whole brain emulation: A roadmap</em></a>, 2008&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li><li id="fn:3"><p>Nick Bostrom,<a href="/works/bostrom-2009-moral-uncertainty-solution/">Moral uncertainty — towards a solution?</a>,<em>Overcoming bias</em>, January 1, 2009&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#8617;&#xfe0e;</a></p></li></ol></div>
]]></description></item><item><title>Ben Kuhn on the effective altruist movement</title><link>https://stafforini.com/notes/ben-kuhn-on-the-effective-altruist-movement/</link><pubDate>Wed, 23 Jul 2014 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/ben-kuhn-on-the-effective-altruist-movement/</guid><description>&lt;![CDATA[<p>Ben Kuhn is a data scientist and engineer at a small financial technology firm. He previously studied mathematics and computer science at Harvard, where he was also co-president of<a href="http://harvardea.org/">Harvard College Effective Altruism</a>. He writes on effective altruism and other topics at<a href="http://www.benkuhn.net/">his website</a>.</p><hr><p><strong>Pablo</strong>: How did you become involved in the EA movement?</p><p><strong>Ben</strong>: When I was a sophomore in high school (that&rsquo;s age 15 for non-Americans), Peter Singer gave his<a href="http://www.thelifeyoucansave.org/"><em>The Life You Can Save</em></a> talk at<a href="http://commschool.org/">my high school</a>. He went through his whole &ldquo;child drowning in the pond&rdquo; spiel and explained that we were morally obligated to give money to charities that helped those who were worse off than us. In particular, I think at that point he was recommending donating to Oxfam in a sort of Kantian way where you gave an amount of money such that if everyone gave the same percentage it would eliminate world poverty. My friends and I realized that there was no utilitarian reason to stop at that amount of money&ndash;you should just donate everything that you didn&rsquo;t need to survive.</p><p>So, being not only sophomores but also sophomoric, we decided that since Prof. Singer didn&rsquo;t live in a cardboard box and wear only burlap sacks, he must be a hypocrite and therefore not worth paying attention to.</p><p>Sometime in the intervening two years I ran across Yvain&rsquo;s essay<a href="http://lesswrong.com/lw/3gj/efficient_charity_do_unto_others/"><em>Efficient Charity: Do Unto Others</em></a> and through it<a href="http://www.givewell.org/">GiveWell</a>. I think that was the point where I started to realize Singer might have been onto something. By my senior year (ages 17-18) I at least professed to believe pretty strongly in some version of effective altruism, although I think I hadn&rsquo;t heard of the term yet. I wrote<a href="https://s3.amazonaws.com/bknet/on_charity.pdf">an essay</a> on the subject in a publication that my writing class put together. It was anonymous (under the brilliant<em>nom de plume</em> of &ldquo;Jenny Ross&rdquo;) but somehow my classmates all figured out it was me.</p><p>The next big update happened during the spring of my first year of Harvard, when I started going to the Cambridge Less Wrong meetups and met<a href="http://www.jefftk.com/index">Jeff</a> and<a href="http://www.givinggladly.com/">Julia</a>. Through some chain of events they set me up with the folks who were then running Harvard High-Impact Philanthropy (which later became<a href="http://harvardea.org/">Harvard Effective Altruism</a>). After that spring, almost everyone else involved in HHIP left and I ended up becoming president. At that point I guess I counted as &ldquo;involved in the EA movement&rdquo;, although things were still touch-and-go for a while until John Sturm came onto the scene and made HHIP get its act together and actually do things.</p><p><strong>Pablo</strong>: In spite of being generally sympathetic to EA ideas, you have recently written a thorough<a href="http://www.benkuhn.net/ea-critique">critique of effective altruism</a>.  I&rsquo;d like to ask you a few questions about some of the objections you raise in that critical essay.  First, you have drawn a distinction between pretending to try and actually trying.  Can you tell us what you mean by this, and why do you claim that a lot of effective altruism can be summarized as “pretending to actually try”?</p><p><strong>Ben</strong>: I&rsquo;m not sure I can explain better than what I wrote in that post, but I&rsquo;ll try to expand on it. For reference, here&rsquo;s the excerpt that you referred to:</p><p>By way of clarification, consider a distinction between two senses of the word “trying”&hellip;. Let&rsquo;s call them “actually trying” and “pretending to try”. Pretending to try to improve the world is something like responding to social pressure to improve the world by querying your brain for a thing which improves the world, taking the first search result and rolling with it. For example, for a while I thought that I would try to improve the world by developing computerized methods of checking informally-written proofs, thus allowing more scalable teaching of higher math, democratizing education, etc. Coincidentally, computer programming and higher math happened to be the two things that I was best at. This is pretending to try. Actually trying is looking at the things that improve the world, figuring out which one maximizes utility, and then doing that thing. For instance, I now run an effective altruist student organization at Harvard because I realized that even though I&rsquo;m a comparatively bad leader and don&rsquo;t enjoy it very much, it&rsquo;s still very high-impact if I work hard enough at it. This isn&rsquo;t to say that I&rsquo;m actually trying yet, but I&rsquo;ve gotten closer.</p><p>Most people say they want to improve the world. Some of them say this because they actually want to improve the world, and some of them say this because they want to be perceived as the kind of person who wants to improve the world. Of course, in reality, everyone is motivated by other people&rsquo;s perceptions to some extent&ndash;the only question is by how much, and how closely other people are watching. But to simplify things let&rsquo;s divide the world up into those two categories, &ldquo;altruists&rdquo; and &ldquo;signalers.&rdquo;</p><p>If you&rsquo;re a signaler, what are you going to do? If you don&rsquo;t try to improve the world at all, people will notice that you&rsquo;re a hypocrite. On the other hand, improving the world takes lots of resources that you&rsquo;d prefer to spend on other goals if possible. But fortunately, looking like you&rsquo;re improving the world is easier than actually improving the world. Since people usually don&rsquo;t do a lot of due diligence, the kind of improvements that signallers make tend to be ones with very good appearances and surface characteristics&ndash;like<a href="http://www.pbs.org/frontlineworld/stories/southernafrica904/video_index.html">PlayPumps</a>, water-pumping merry-go-rounds which initially appeared to be a clever and elegant way to solve the problem of water shortage in developing countries. PlayPumps got tons of money and celebrity endorsements, and their creators got lots of social rewards, even though the pumps turned out to be hideously expensive, massively inefficient, prone to breaking down, and basically a disaster in every way.</p><p>So in this oversimplified world, the EA observation that &ldquo;charities vary in effectiveness by orders of magnitude&rdquo; is explained by &ldquo;charities&rdquo; actually being two different things: one group optimizing for looking cool, and one group optimizing for actually doing good. A large part of effective altruism is realizing that signaling-charities (&ldquo;pretending to try&rdquo;) often don&rsquo;t do very much good compared to altruist-charities.</p><p>(In reality, of course, everyone is driven by some amount of signalling and some amount of altruism, so these groups overlap substantially. And there are other motivations for running a charity, like being able to convince<em>yourself</em> that you&rsquo;re doing good. So it gets messier, but I think the vastly oversimplified model above is a good illustration of where my point is coming from.)</p><p>Okay, so let&rsquo;s move to the second paragraph of the post you referenced:</p><p>Using this distinction between pretending and actually trying, I would summarize a lot of effective altruism as “pretending to actually try”. As a social group, effective altruists have successfully noticed the pretending/actually-trying distinction. But they seem to have stopped there, assuming that knowing the difference between fake trying and actually trying translates into ability to actually try. Empirically, it most certainly doesn&rsquo;t. A lot of effective altruists still end up satisficing&mdash;finding actions that are on their face acceptable under core EA standards and then picking those which seem appealing because of other essentially random factors. This is more likely to converge on good actions than what society does by default, because the principles are better than society&rsquo;s default principles. Nevertheless, it fails to make much progress over what is directly obvious from the core EA principles. As a result, although “doing effective altruism” feels like truth-seeking, it often ends up being just a more credible way to pretend to try.</p><p>The observation I&rsquo;m making here is roughly that EA seems not to have switched entirely to doing good for altruistic rather than signaling reasons. It&rsquo;s more like we&rsquo;ve switched to<em>signaling</em> that we&rsquo;re doing good for altruistic rather than signaling reasons. In other words, the motivation didn&rsquo;t switch from &ldquo;looking good to outsiders&rdquo; to &ldquo;actually being good&rdquo;&ndash;it switched from &ldquo;looking good to outsiders&rdquo; to &ldquo;looking good to the EA movement.&rdquo;</p><p>Now, the EA movement is way better than random outsiders at distinguishing between things with good surface characteristics and things that are actually helpful, so the latter criterion is much stricter than the former, and probably leads to much more good being done per dollar. (For instance, I doubt the EA community would ever endorse something like PlayPumps.) But, at least at the time of writing that post, I saw a lot of behavior that seemed to be based on finding something pleasant and with good surface appearances rather than finding the thing that optimized utility&ndash;for instance, donating to causes without a particularly good case that they were better than saving or picking career options that seemed decent-but-not-great from an EA perspective. That&rsquo;s the source of the phrase &ldquo;pretending to actually try&rdquo;&ndash;the signaling isn&rsquo;t going away, it&rsquo;s just moving up a level in the hierarchy, to signaling that you don&rsquo;t care about signaling.</p><p>Looking back on that piece, I think “pretending to actually try” is still a problem, but my intuition is now that it&rsquo;s probably not huge in the scheme of things. I&rsquo;m not quite sure why that is, but here are some arguments against it being very bad that have occurred to me:</p><ul><li>It&rsquo;s probably somewhat less prevalent than I initially thought, because the EAs making weird-seeming decisions may be doing them for reasons that aren&rsquo;t transparent to me and that get left out by the typical EA analysis. The typical EA analysis tends to be a 50000-foot average-case argument that can easily be invalidated by particular personal factors.</li><li>As Katja Grace<a href="http://meteuphoric.wordpress.com/2013/12/22/pretend-to-really-really-try/">points out</a>, encouraging pretending to really try might be optimal from a movement-building perspective, inasmuch as it&rsquo;s somewhat inescapable and still leads to pretty good results.</li><li>I probably overestimated the extent to which motivated/socially-pressured life choices are bad, for a couple reasons. I discounted the benefit of having people do a diversity of things, even if the way they came to be doing those things wasn&rsquo;t purely rational. I also discounted the cost of doing something EA tells you to do instead of something you also want to do.</li><li>For instance, suppose for the sake of argument that there&rsquo;s a pretty strong EA case that politics isn&rsquo;t very good (I know this isn&rsquo;t actually true). It&rsquo;s probably good for marginal EAs to be dissuaded from going into politics by this, but I think it would still be bad for every single EA to be dissuaded from going into politics, for two reasons. First, the arguments against politics might turn out to be wrong, and having a few people in politics hedges against that case. Second, it&rsquo;s much easier to excel at something you&rsquo;re motivated at, and the category of &ldquo;people who are excellent at what they do&rdquo; is probably as important to the EA movement as &ldquo;people doing job X&rdquo; for most X.</li></ul><p>I also just haven&rsquo;t noticed as much pretending-stuff going on in the last few months, so maybe we&rsquo;re just getting better at avoiding it (or maybe I&rsquo;m getting worse at noticing it). Anyway, I still definitely think there&rsquo;s pretending-to-actually-try going on, but I don&rsquo;t think it&rsquo;s a huge problem.</p><p><strong>Pablo</strong>: In another section of that critique, you express surprise at the fact that so many effective altruists donate to global health causes now.  Why would you expect EAs to use their money in other ways&ndash;whether it&rsquo;s donating now to other causes, or donating later&ndash;, and what explains, in your opinion, this focus on causes for which we have relatively good data?</p><p><strong>Ben</strong>; I&rsquo;m no longer sure enough of where people&rsquo;s donations are going to say with certainty that too much is going to global health. My update here is from of a combination of being overconfident when I wrote the piece, and what looks like an increase in waiting to donate shortly after I wrote it. The latter was probably due in large part to<a href="http://blog.givewell.org/2013/11/26/change-in-against-malaria-foundation-recommendation-status-room-for-more-funding-related/">AMF&rsquo;s delisting</a> and perhaps the precedent set by<a href="http://blog.givewell.org/2013/12/12/staff-members-personal-donations/">GiveWell employees</a>, many of whom waited last year (though<a href="http://blog.givewell.org/2013/12/31/some-considerations-against-saving-for-next-year/">others argued against it</a>). (Incidentally, I&rsquo;m excited about the projects going on to make this more transparent, e.g. the questions on the survey about giving!)</p><p>The giving now vs. later debate has been<a href="http://www.effective-altruism.com/giving-now-vs-later-summary/">ably summarized by Julia Wise</a> on the EA blog. My sense from reading various arguments for both sides is that I more often see bad arguments for giving now. There are definitely good arguments for giving at least some money now, but on balance I suspect I&rsquo;d like to see more saving. Again, though, I don&rsquo;t have a great idea of what people&rsquo;s donation behavior actually is; my samples could easily be biased.</p><p>I think my strongest impression right now is that I suspect we should be exploring more different ways to use our donations. For instance, some people who are earning to give have experimented with funding people to do independent research, which was a pretty cool idea. Off the top of my head, some other things we could try include scholarships, essay contest prizes, career assistance for other EAs, etc. In general it seems like there are tons of ways to use money to improve the world, many of which haven&rsquo;t been explored by GiveWell or other evaluators and many of which don&rsquo;t even fall in the category of things they care about (because they&rsquo;re too small or too early-stage or something), but we should still be able to do something about them.</p><p><strong>Pablo</strong>: In the concluding section of your essay, you propose that<em>self-awareness</em> be added to the list of principles that define effective altruism. Any thoughts on how to make the EA movement more self-aware?</p><p><strong>Ben</strong>: One thing that I like to do is think about what our blind spots are. I think it&rsquo;s pretty easy to look at all the stuff that is obviously a bad idea from an EA point of view, and think that our main problem is getting people &ldquo;on board&rdquo; (or even &ldquo;getting people to admit they&rsquo;re wrong&rdquo;) so that they stop doing obviously bad ideas. And that&rsquo;s certainly helpful, but we also have a ways to go just in terms of figuring things out.</p><p>For instance, here&rsquo;s my current list of blind spots&ndash;areas where I wish there were a lot more thinking and idea-spreading going on then there currently is:</p><ul><li><strong>Being a good community.</strong> The EA community is already having occasional growing pains, and this is only going to get worse as we gain steam e.g. with Will MacAskill&rsquo;s upcoming book. And beyond that, I think that ways of making groups more effective (as opposed to individuals) have a lot of promise for making the movement better at what we do. Many, many intellectual groups fail to accomplish their goals for basically silly reasons, while seemingly much worse groups do much better on this dimension. It seems like there&rsquo;s no intrinsic reason we should be worse than, say, Mormons at building an effective community, but we&rsquo;re clearly not there yet. I think there&rsquo;s absolutely huge value in getting better at this, yet almost no one putting in a serious concerted effort.</li><li><strong>Knowing history.</strong> Probably as a result of EA&rsquo;s roots in math/philosophy, my impression is that our average level of historical informedness is pretty low, and that this makes us miss some important pattern-matches and cues. For instance, I think a better knowledge of history could help us think about capacity-building interventions, policy advocacy, and community building.</li><li><strong>Fostering more intellectual diversity.</strong> Again because of the math/philosophy/utilitarianism thing, we have a massive problem with intellectual monoculture. Of my friends, the ones I enjoy talking about altruism the most with now are largely actually the ones who associate least with the broader EA community, because they have more interesting and novel perspectives.*</li><li><strong>Finding individual effective opportunities</strong>. I suspect that there&rsquo;s a lot of room for good EA opportunities that GiveWell hasn&rsquo;t picked up on because they&rsquo;re specific to a few people at a particular time. Some interesting stuff has been done in this vein in the past, like funding small EA-related experiments, funding people to do independent secondary research, or giving loans to other EAs investing in themselves (at least I believe this has been done). But I&rsquo;m not sure if most people are adequately on the lookout for this kind of opportunity.</li></ul><p>(Since it&rsquo;s not fair to say &ldquo;we need more X&rdquo; without specifying how we get it, I should probably also include at least one anti-blind spots that I think we should be spending fewer resources on, on the margin: Object-level donations to e.g. global health causes. I feel like we may be hitting diminishing returns here. Probably donating some is important for signalling reasons, but I think it doesn&rsquo;t have a very high naive expected value right now.)</p><p><strong>Pablo</strong>: Finally, what are your plans for the mid-term future?  What EA-relevant activities will you engage in over the next few years, and what sort of impact do you expect to have?</p><p><strong>Ben</strong>: A while ago I did some reflecting and realized that most of the things I did that I was most happy about were pretty much unplanned&ndash;they happened not because I carefully thought things through and decided that they were the best way to achieve some goal, but because they intuitively seemed like a cool thing to do. (Things in this category include starting a blog, getting involved in the EA/rationality communities, running Harvard Effective Altruism, getting my current job, etc.) As a result, I don&rsquo;t really have &ldquo;plans for the mid-term future&rdquo; per se. Instead, I typically make decisions based on intuitions/heuristics about what will lead to the best opportunities later on, without precisely knowing (or even knowing at all, often) what form those opportunities will take.</p><p>So I can&rsquo;t tell you what I&rsquo;ll be doing for the next few years&ndash;only that it will probably follow some of my general intuitions and heuristics:</p><ul><li><strong>Do lots of things</strong>. The more things I do, the more I increase my &ldquo;luck surface area&rdquo; to find awesome opportunities.</li><li><strong>Do a few things really well</strong>. The point of this heuristic is hopefully obvious.</li><li><strong>Do things that other people aren&rsquo;t doing</strong>&ndash;or more accurately, things that not enough people are doing relative to how useful or important they are. My effort is most likely to make a difference in an area that is relatively under-resourced.</li></ul><p>I&rsquo;d like to take a moment here to plug the<a href="http://www.givewell.org/altruistic-career-choice">conference call on altruistic career choice</a> that Holden Karnofsky of GiveWell had, which makes some great specific points along these lines.</p><p>Anyway, that&rsquo;s my long-winded answer to the first part of this question. As far as EA-relevant activities and impacts, all the same caveats apply as above, but I can at least go over some things I&rsquo;m currently interested in:</p><ul><li>Now that I&rsquo;m employed full-time, I need to start thinking much harder about where exactly I want to give: both what causes seem best, and which interventions within those causes. I actually currently don&rsquo;t have much of a view on what I would do with more unrestricted funds.</li><li>Related to the point above about self-awareness, I&rsquo;m interested in learning some more EA-relevant history&ndash;how previous social movements have worked out, how well various capacity-building interventions have worked, more about policy and the various systems that philanthropy comes into contact with, etc.</li><li>I&rsquo;m interested to see to what extent the success of Harvard Effective Altruism can be sustained at Harvard and replicated at other universities.</li></ul><p>I also have some more speculative/gestational interests&ndash;I&rsquo;m keeping my eye on these, but don&rsquo;t even have concrete next steps in mind:</p><ul><li>I think there may be under-investment in healthy EA community dynamics, preventing common failure modes like unfriendliness, ossification to new ideas, groupthink etc.&ndash;though I can&rsquo;t say for sure because I don&rsquo;t have a great big-picture perspective of the EA community.</li><li>I&rsquo;m also interested in generally adding more intellectual/epistemic diversity to EA&ndash;we have something of a monoculture problem right now. Anecdotally, there are a number of people who I think would have a really awesome perspective on many problems that we face, but who get turned off of the community for one reason or another.</li></ul>
]]></description></item><item><title>The Gift</title><link>https://stafforini.com/notes/the-gift/</link><pubDate>Fri, 24 May 2013 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/the-gift/</guid><description>&lt;![CDATA[<p>by Ian Parker</p><p><em>The New Yorker</em>, vol. 80, no. 21 (August 2, 2004), pp. 54-63</p><p>Last summer, not long after Zell Kravinsky had given almost his entire forty-five-million-dollar real-estate fortune to charity, he called Barry Katz, an old friend in Connecticut, and asked for help with an alibi. Would Katz call Kravinsky&rsquo;s wife, Emily, in Philadelphia, and say that the two men were about to take a weeklong trip to Katz&rsquo;s ski condominium in Vermont? This untruth would help Kravinsky do something that did not have his wife&rsquo;s approval: he would be able to leave home, check into the Albert Einstein Medical Center, in Philadelphia, for a few days, and donate a kidney to a woman whose name he had only just learned.</p><p>Katz refused, and Kravinsky became agitated. He said that the intended recipient of his gift would die without the kidney, and that his wife&rsquo;s reluctance to support this &ldquo;nondirected&rdquo; donation-it would be only the hundred and thirty-fourth of its kind in the United States-would make her culpable in that death. &ldquo;I can&rsquo;t allow her to take this person&rsquo;s life!&rdquo; Kravinsky said. He was, at forty-eight, a former owner of shopping malls and distribution centers, and a man with a single thrift-store suit that had cost him twenty dollars.</p><p>&ldquo;You think she&rsquo;d be taking a life?&rdquo; Katz asked.</p><p>&ldquo;Absolutely,&rdquo; Kravinsky replied.</p><p>Katz then asked, warily, &ldquo;Do you mean that anybody who is not donating a kidney is taking someone&rsquo;s life?&rdquo;</p><p>&ldquo;Yes,&rdquo; Kravinsky said.</p><p>&ldquo;So, by your terms, I&rsquo;m a murderer?&rdquo;</p><p>&ldquo;Yes,&rdquo; Kravinsky said, in as friendly a way as possible.</p><p>After a pause, Katz said, &ldquo;I have to get off the phone-I can&rsquo;t talk about this anymore,&rdquo; and he hung up. A few weeks later, Kravinsky crept out of his house at six o&rsquo;clock in the morning while his wife and children were still asleep. Emily Kravinsky learned that her husband had donated a kidney when she read about it in a local newspaper.</p><p>Kravinsky, whose unrestrained disbursement of his assets-first financial, then corporeal-has sometimes been unsettling for the people close to him, grew up in a row house in the working-class Philadelphia neighborhood of Oxford Circle, amid revolutionary rhetoric. &ldquo;My father would say how great things were in the Soviet Union, and how shabby they were here,&rdquo; Kravinsky recalled recently. &ldquo;He would rail against rich people and the ruling class.&rdquo;</p><p>Kravinsky&rsquo;s father, Irving, who is now eighty-nine, was born in Russia to a Jewish family, which immigrated to America when he was a boy. A tank commander in the Second World War, he was a socialist whose faith in the Soviet Union was extinguished only after that country no longer existed. He worked as a printer, Kravinsky told me, &ldquo;thinking he&rsquo;d be in the vanguard of the revolution by remaining in the proletariat&rdquo;; and when Zell, who had two older sisters, began to excel in school his success seems to have been taken by his father as a sign of class disloyalty. After Zell graduated from elementary school with a prize as the best student, Irving told him, &ldquo;Well, next year you&rsquo;ll be nothing.&rdquo;</p><p>James Kahn, a childhood friend of Kravinsky&rsquo;s, and a fellow-member of the chess team in high school, told me that Zell&rsquo;s father and mother-Reeda Kravinsky is a former teaching supervisor, now seventy-eight-&ldquo;were steadfast in denying him any praise.&rdquo; He added, &ldquo;I think what he did later was almost in desperation-doing the most extreme thing possible, something that they couldn&rsquo;t deny was a good thing.&rdquo; Reeda told me, &ldquo;I think we did praise him, but maybe he didn&rsquo;t get enough attention, for an outstanding child.&rdquo;</p><p>As a boy, Kravinsky could hope to gain his parents&rsquo; attention either by conforming or by rebelling; he did both. &ldquo;Zell was simultaneously more left-wing and more right-wing than I was,&rdquo; Kahn said. He had an active social conscience-he read books on Gandhi, and, at the age of twelve, he picketed City Hall in support of public housing. (He remembers this as the last time he did anything that met with his father&rsquo;s approval.) But, by the standards of the late sixties, Kravinsky was unfashionably curious about money. He first invested in the stock market when he was twelve, and told me that he was &ldquo;pretty young when I understood money better than my father did.&rdquo;</p><p>In Kravinsky&rsquo;s eyes, his father had humiliated himself in his relationships with money. Citing his radical politics, Irving Kravinsky said he couldn&rsquo;t apply for union work. &ldquo;He was terrifically exploited,&rdquo; Kravinsky recalled. &ldquo;He was afraid to ask for a raise. My mother yelled at him, day and night, said he wasn&rsquo;t a man, and &lsquo;Zell&rsquo;s more of a man than you are.&rsquo; "</p><p>In 1971, Kravinsky won a scholarship to Dartmouth. He majored in Asian studies, wrote poetry, took up meditation, and grew his hair long. Soon after graduation, Kravinsky returned to Philadelphia, where he got a job at an insurance company. He began a relationship with a co-worker there, and moved in with her; the match lasted less than a year, but it had the side effect of introducing Kravinsky to real estate. He bought a duplex in the working-class neighborhood of Logan for ten thousand dollars, and rented out half of it. When the couple split up, Kravinsky kept the apartment, then sold it for a two-thousand-dollar profit.</p><p>As Kravinsky acquired a taste for property, he looked for ways to satisfy his idealistic self-in which good intentions were mixed with habits of self-criticism and a preemptive resentment about being ridiculed or undervalued. In 1978, he began to work with socially and emotionally troubled students in Philadelphia&rsquo;s public schools. &ldquo;I became a teacher in the ghetto,&rdquo; Kravinsky recalls. &ldquo;Everyone I went to college with laughed at that. I was written off as a failure.&rdquo;</p><p>The job offered moral satisfaction, but it also depressed Kravinsky-his pride in self-sacrifice counterbalanced by the thought that he was being taken for a ride. (Once, after school, he took a promising student to the theatre and, as he walked the boy home, he was mugged in a way that made Kravinsky think he might have been set up.) He grew more involved in real estate: he bought a condo, then a house in Maine; his deals became grander, and he began to see profits of tens of thousands of dollars. &ldquo;Nobody in my family had ever made that much money,&rdquo; he said. He spent very sparingly, preferring to reinvest; by 1982, he owned a three-story building near the University of Pennsylvania campus, but he lived in the smallest, gloomiest apartment, with no shower, kitchen, or windows.</p><p>Barry Katz, who met Kravinsky around this time, and who is now a developer of luxury homes in Connecticut, found him to be brilliant and articulate, &ldquo;with the kind of intensity you don&rsquo;t encounter in many people. He also had a lost-puppy quality.&rdquo; Kravinsky had skipped a year in high school and one in college, and, according to Edward Miller, another old friend, who is now a lecturer in English literature, his intellectual and emotional maturity seemed out of step. &ldquo;You could call it high-school-geek syndrome,&rdquo; Miller said.</p><p>In 1984, Kravinsky was devastated by the death of Adria, the elder of his two sisters, from lung cancer. She was thirty-three; Zell was thirty. &ldquo;She was the only person in my family who liked me in any meaningful way,&rdquo; Kravinsky said, describing the guilt he still feels for not showing her enough affection, and for not persuading her to quit smoking. &ldquo;We were close, but there were so many things that kept me from spending more time with her. I wish I could go back.&rdquo; Kravinsky entered a period of deep depression. He shared a house with Miller, who remembers that Kravinsky mostly stayed in his room, writing poetry on a typewriter. Kravinsky stopped teaching in 1986, and he gave two of his three properties to his surviving sister, Hilary, and sold the other.</p><p>It was a despairing time, but it jolted Kravinsky out of the life of the self-abnegating schoolteacher. He expanded his intellectual ambitions, completing a Ph.D. in composition theory at Penn&rsquo;s School of Education. (His unusual dissertation proposed a &ldquo;table of rhetorical elements,&rdquo; which was inspired by the periodic table.) He also took courses at the New School, in New York, and at the School of Criticism and Theory, at Dartmouth; in 1990, he began a second Ph.D. at Penn, with a dissertation, &ldquo;Paradise Glossed,&rdquo; that dissected the rhetoric of Milton with mathematical rigor. At Penn, he started teaching undergraduate courses in Renaissance literature, and met and married Emily Finkelstein, a doctor who is now a psychiatrist with an expertise in eating disorders. Kravinsky became a resident adviser, and the couple lived frugally in student housing. (&ldquo;Free rent, free meals-the greatest deal in the world,&rdquo; Kravinsky recalled.) They had the first of four children in 1991.</p><p>Kravinsky&rsquo;s Milton dissertation was &ldquo;an intense close reading and quite wonderful,&rdquo; according to Maureen Quilligan, then the graduate chairperson of Penn&rsquo;s English department and now a professor at Duke. &ldquo;It&rsquo;s one of the best I&rsquo;ve ever read. It sounded like deconstruction, although he&rsquo;d got there without having to do any deconstruction theory.&rdquo; After it was finished, Kravinsky taught an undergraduate Milton course at Penn that Quilligan describes as &ldquo;fantastically successful-the kids responded to it with the wildest enthusiasm, and they worked hard for him and had a sublime intellectual experience.&rdquo; At the end of each lecture, Kravinsky would stand at the door and shake hands with every student. &ldquo;He said he was hunting for another Milton,&rdquo; Quilligan remembers.</p><p>Though he was admired by students-and had impeccable leftist credentials-he was galled to find that his intellectual interests were considered insufficiently avant-garde by academe. As Kravinsky saw it, &ldquo;What they didn&rsquo;t like was that Milton was the great classical liberal. Classical liberalism, bourgeois liberalism-they felt the same way about it as my father.&rdquo; Quilligan says that he was handicapped by &ldquo;the eccentricity of his intellectual and spiritual intensity, added to the fact that he had written about a single white male author.&rdquo; Kravinsky recalls going to job interviews carrying letters of recommendation from scholars as distinguished as Stanley Fish, &ldquo;and at every one they said, &lsquo;You have a spectacular portfolio, both of your Ph.D.s are relevant, Fish said you &ldquo;can do anything&rdquo;-but we&rsquo;re looking for diversity.&rsquo; " Only the University of Helsinki offered him a job.</p><p>By 1994, he had decided to give up on an academic career. Instead, he would make a living in real estate. Kravinsky said that his wife was skeptical. &ldquo;She said I&rsquo;d become a bum,&rdquo; he told me. But, thanks to his earlier real-estate record, and his evident mathematical brilliance, Kravinsky was able to persuade the United Valley Bank to lend him two million dollars, with which he bought two apartment buildings-around a hundred and fifty thousand square feet in total-one near Penn, the other near St. Joseph&rsquo;s University. Kravinsky knew that in a recession people will go back to school, and that the ratio of rent to property prices will be highest where a university is in a run-down urban area. He was also fearless about being highly leveraged.</p><p>Kravinsky was improvising-&ldquo;Nobody ever taught me how to succeed, or took me under their wing&rdquo;-but his portfolio quickly grew, and within a year he had assets of six million dollars and debts of four million. Though he was now wealthy, he spent no more than he had before, with the exception of a hundred-and-thirty-thousand-dollar house that he bought in Jenkintown, a Philadelphia suburb, in 1995. (His second child had just been born.) &ldquo;There was little of the mogul apparent to the eye,&rdquo; Barry Katz said. Even to his close associates, Kravinsky&rsquo;s business seemed implausible. Edward Miller took a job with him as an apartment manager but was never convinced that the property empire was real. &ldquo;I didn&rsquo;t fully believe it,&rdquo; he told me. &ldquo;I thought that somehow it was a deck of cards.&rdquo; These mistaken thoughts were reinforced by seeing &ldquo;the most disorganized, chaotic organization you can imagine-leases at the bottom of closets, under the toilets, soaking wet.&rdquo; Miller was also surprised to see how blithely neglectful Kravinsky could sometimes be of contractors and janitors, as if he were grateful for the chance to take a vacation from the patient, solicitous persona he showed to his friends.</p><p>Property management ultimately did not suit Kravinsky-&rdquo; &lsquo;Tenants and toilets&rsquo;; there&rsquo;s a phrase that suggests the agony,&rdquo; he said-and in 1998 he began selling most of his rental properties (now about four hundred apartments) and turning to commercial real estate, investing at a level where the building is a mere premise for an intricate dance of numbers. &ldquo;Everything else can change, but numbers remain the same; numbers are your best friends,&rdquo; Kravinsky said. &ldquo;I needed to leverage my intellect, return to math.&rdquo;</p><p>Kravinsky bought supermarkets and warehouses; that is, he looked for tenants with good credit ratings and with long leases, then paid for the buildings with loans bundled into bonds by Wall Street banks and sold to institutional investors. These loans have a singular advantage: if things go wrong, nobody comes for your stereo. In 1999, in a typical deal, Kravinsky bought a clothing-distribution center in Ohio for $16.8 million. He put up $1.1 million and borrowed $15.7 million. If the building decreased in value by a hundred per cent, he would lose $1.1 million; if it increased in value by a hundred per cent, he would make $16.8 million.</p><p>&ldquo;Most people think the more you borrow the riskier it is,&rdquo; Kravinsky has said. &ldquo;In my system, the more you borrow the safer it is.&rdquo; (On a single day in April, 1999, he borrowed thirty-two million dollars. He remembers Emily asking, &ldquo;How much do we have to pay on that?&rdquo; It was around ten thousand dollars a day. She said, dryly, &ldquo;Well, if worst comes to worst, I can just treat a hundred people a day.&rdquo;) Kravinsky made full use of the tax advantages of commercial-real-estate investments: in the eyes of the I.R.S., a shopping mall depreciates in value, like an office chair, and one can set that depreciation against income tax, overlooking the fact that a mall, over time, is likely to increase in value.</p><p>Kravinsky knew how to make money, but he had no talent for spending it. His investments were an expression of his intellect-they were splendid rhetorical gestures, and to take money out for, say, a swimming pool would be to lose the debate. Even as he became rich, he was arguing at home against buying two minivans to replace a 1985 Toyota Camry. (He eventually gave in, and lost the Camry, which has since become an object of regret and longing.) The children did not get pocket money, and Emily had to fight to have the front porch repaired. (&ldquo;Emily was certainly complicit in the family&rsquo;s frugality, but she became frustrated by Zell&rsquo;s refusal to spend money,&rdquo; a friend of the Kravinskys&rsquo; told me.) Kravinsky worked from home. He recalled how one well-dressed man came to interview for an accountant&rsquo;s job and, seeing Kravinsky&rsquo;s modest home and casual dress, ran away. Kravinsky watched him disappear down the street and called out, &ldquo;Where are you going?&rdquo; The interviewee shouted, &ldquo;I don&rsquo;t believe you,&rdquo; and kept running.</p><p>About three years ago, as Kravinsky&rsquo;s assets rose to nearly forty-five million dollars-a million square feet of commercial real estate, along with lofts, houses, and condos-friends began to hear him talk of giving all his assets to charity. He had long entertained philanthropic thoughts, although, as Katz told me, &ldquo;I don&rsquo;t think it ever occurred to Zell that the by-product of what he was doing would be wealth on this scale.&rdquo; In 1998, Kravinsky had tried to donate some properties and empty lots to the University of Pennsylvania. He says that the university was wary of him, and &ldquo;didn&rsquo;t even take me out to lunch.&rdquo; As his portfolio grew, however, Kravinsky&rsquo;s charitable impulse became more urgent. Edward Miller remembers sitting at his dining table one night with Kravinsky and James Kahn, &ldquo;and Zell began to talk of giving away his wealth. And we said, &lsquo;Don&rsquo;t do it.&rsquo; " Kahn asked him why he didn&rsquo;t give away a third of his fortune, and use the rest to become richer, and ultimately give even more money away. As Miller recalled, &ldquo;We berated him for three or four hours. We said, &lsquo;You&rsquo;re depressed.&rsquo; He seemed like King Lear, dividing his kingdom so he could &lsquo;unburdened crawl toward death.&rsquo; "</p><p>For the moment, Kravinsky&rsquo;s friends prevailed. &ldquo;I think he wanted to be talked out of it,&rdquo; Miller said. But Kravinsky, the skilled rhetorician, seems to have discovered something unanswerable in his own rhetoric. &ldquo;The reasons for giving a little are the reasons for giving a lot, and the reasons for giving a lot are the reasons for giving more,&rdquo; he recently said. Kravinsky feared that he might lose his assets, or his impulse to give, or that his wife would challenge the idea. Emily was philanthropically inclined, but, as Kravinsky recalled it, he needed to &ldquo;walk her into the idea&rdquo; of total divestment-gift by gift, keeping the emphasis on public health, which attracted her, and promising that quitting real estate would bring him closer to the family. &ldquo;I said I&rsquo;d have more time for the kids,&rdquo; he told me. &ldquo;She thought it was crazy to give everything away, but she said, &lsquo;At least we&rsquo;ll be out of the business.&rsquo; " The gifts were made with her blessing and in her name. &ldquo;My impression was that she decided she didn&rsquo;t want to be made out to be a Scrooge,&rdquo; a friend of the Kravinskys&rsquo; told me.</p><p>In 2002, Zell and Emily gave an eighty-seven-thousand-square-foot apartment building to a school for the disabled in Philadelphia. The same year, they gave two gifts, worth $6.2 million, to the Centers for Disease Control Foundation. The gifts were partly in the form of a distribution center, four condominiums, three houses, and a parking lot; Kravinsky placed them in a fund named for his late sister, Adria. In March, 2003, the Kravinskys created the Adria Kravinsky Foundation, to support a School of Public Health at Ohio State University; the gift included three warehouses, four department stores, and a shopping center in Indianapolis. Together, these were worth around thirty million dollars. Karen Holbrook, the president of O.S.U., called the gift &ldquo;a magnificent commitment.&rdquo;</p><p>Kravinsky had put some money aside-he had established trust funds for his wife, his children, and the children of his surviving sister. But his personal assets were now reduced to a house (on which he had a large mortgage), two minivans, and about eighty thousand dollars in stocks and cash. According to Katz, &ldquo;He gave away the money because he had it and there were people who needed it. But it changed his way of looking at himself. He decided the purpose of his life was to give away things.&rdquo;</p><p>Jenkintown, Pennsylvania, is a mixed-income community of about four thousand people which tries to maintain a small-town character within the sprawl of housing developments and shopping malls just north of Philadelphia. I made my first visit to Kravinsky in November, parking in front of a wooden-shingled house with a broken photocopier on the front porch and a tangle of bicycles, tricycles, and wagons. A handwritten sign by the door, a marker of spousal frustration, read, &ldquo;Put Your Keys Away Before You Forget.&rdquo;</p><p>Kravinsky came to the door several minutes after I rang the bell. He is slight, and looked both boyish and wan, with pale, almost translucent skin. He wore sneakers, a blue plaid shirt, and tan trousers with an elasticized waist. He seemed distracted, and I realized later that the timing of my visit was awkward: he knew that his wife would not want a reporter in the house, but she had gone out, and two of his four young children were home, so he could not immediately go out to lunch with me.</p><p>He invited me into a house crowded with stuff, including a treadmill in the middle of the living room. He cleared away enough books and toys for me to sit down on a sofa. His daughter, who is nine, came into the room to say hello, but when Emily Kravinsky came home, a moment later, she walked straight past us into the kitchen, taking the girl with her. Kravinsky followed. He came back after a few minutes and picked up his coat, and as we left the house he said, &ldquo;She wants us out of here.&rdquo;</p><p>We drove to a restaurant in a nearby mini-mall. He ordered a mushroom sandwich and a cup of warm water that he didn&rsquo;t touch. &ldquo;I used to feel that I had to be good, truly good in my heart and spirit, in order to do good,&rdquo; he said, in a soft voice. &ldquo;But it&rsquo;s the other way around: if you do good, you<em>/ become better. With each thing I&rsquo;ve given away, I&rsquo;ve been /more</em> certain of the need to give more away. And at the end of it maybe I will be good. But what are they going to say-that I&rsquo;m depressed? I am, but this isn&rsquo;t suicidal. I&rsquo;m depressed because I haven&rsquo;t done enough.&rdquo;</p><p>Within a few minutes, Kravinsky had talked of Aristotle, Nietzsche, and the Talmud, and, in less approving terms, of the actor Billy Crudup, who had just left his pregnant girlfriend for another woman. (&ldquo;How do you like that!&rdquo;) Kravinsky&rsquo;s mostly elevated range of reference, along with a rhetorical formality and a confessional tone, sometimes gave the impression that he was reading from his collected letters. &ldquo;What I aspire to is ethical ecstasy,&rdquo; he said. &ldquo;<em>Ex stasis:</em> standing out of myself, where I&rsquo;d lose my punishing ego. It&rsquo;s tremendously burdensome to me.&rdquo; Once achieved, &ldquo;the significant locus would be in the sphere of others.&rdquo;</p><p>His cell phone rang, and a mental switch was flicked: &ldquo;You have to do a ten-thirty-one and put fresh money in on terms that are just as leveraged . . . going eight per cent over debt. . . . I think we should do it. It&rsquo;s nice to start with a blue chip.&rdquo;</p><p>These contrasting discourses have one clear point of contact. In our conversations, Kravinsky showed an almost rhapsodic appreciation of ratios. In short, ratios are dependable and life is not. &ldquo;No number is significant in itself: its only significance is in relation to other numbers,&rdquo; he said. &ldquo;I try to rely on relationships between numbers, because those relationships are constant-unlike Billy Crudup and the woman he impregnated. Even if the other relationships in our lives are going to hell in a handbasket, numbers continue to cooperate with one another.&rdquo;</p><p>In the months following the first of Kravinsky&rsquo;s financial gifts, a new ratio began to preoccupy him: the one-in-four-thousand chance that a person has of dying in an operation to donate a kidney. In early 2003, he read an article in the<em>Wall Street Journal</em> that introduced him to the idea of nondirected kidney donations, in which an altruistic-minded person gives an organ to benefit a stranger-someone in the pool of sixty thousand people on America&rsquo;s kidney-transplant waiting list. The demand for kidneys outstrips the supply; the buying and selling of organs is illegal, and although there are between fifteen and twenty thousand deaths in America each year that could yield organs, about half of families deny permission for the bodies of their relatives to be used in this way, often disregarding the dead person&rsquo;s donor card. Kravinsky was so struck by the article that he cut it out and kept it in a desk drawer.</p><p>The notion of nondirected organ donation is not new. Joseph E. Murray, who directed the first successful human kidney-transplant operation, in 1954, in Boston, recently recalled that, by that time, he had received three offers of kidneys-from a prisoner, a homeless man, and a nun. They could not be accepted; early transplants were generally between identical twins, for a precise biological match. But in the early sixties advances in immunosuppressant drugs allowed surgeons to begin transplanting from deceased donors to unrelated recipients and from living donors other than twins-typically, blood relatives. By 1963, there were no medical barriers to nondirected donation. But while kidney transplants became almost routine-last year, there were sixty-five hundred living-donor and eighty-seven hundred deceased-donor transplants in America-nondirected donation did not.</p><p>On occasion, altruists engaged in a somewhat less radical practice, donating kidneys to people they had not met but whose plights had attracted their attention (say, through a newspaper article). But doctors were resistant even to this idea, and questioned the sanity of these donors; according to a paper published in<em>Seminars in Psychiatry</em> in 1971, the practice was viewed by most physicians as &ldquo;impulsive, suspect, and repugnant.&rdquo; Doctors were also under the impression, now revised, that related donations were almost always better than unrelated ones. In addition, a kidney-removal operation was initially far more painful and invasive than it later became; until the mid-nineties, it was often necessary to break the donor&rsquo;s rib, and the donor was frequently left with a long scar.</p><p>In the late nineties, by coincidence, two donors independently approached two hospitals with a request to make a nondirected kidney donation, and neither hospital could think of a good reason for turning them away. Joyce Roush, a transplant nurse from Indiana, introduced herself to Lloyd Ratner, a leading transplant surgeon then at Johns Hopkins, in Baltimore. &ldquo;I was quite skeptical,&rdquo; Ratner told me. &ldquo;I said, &lsquo;Give me a call and we&rsquo;ll consider,&rsquo; thinking she&rsquo;d never call me. She called and called.&rdquo; And at the University of Minnesota a would-be donor with a long record of altruistic acts made the same request, saying, &ldquo;I want to do this and go home and be happy.&rdquo; Following bioethical consultation, and psychiatric testing of the donors, the hospitals accepted the offers: in Minnesota, the anonymous donor&rsquo;s kidney was transplanted in August, 1999; a few weeks later, at Johns Hopkins, Joyce Roush donated one to a thirteen-year-old boy. Now, several dozen nondirected donations are performed each year in the U.S.</p><p>Kravinsky considered the risks. Although Richard Herrick, who received the first kidney transplant, died eight years later, Ronald Herrick, his donor and twin brother, is still alive. As Herrick&rsquo;s example suggests, and medical research confirms, there are no health disadvantages to living with one kidney. One is enough-it grows a little bigger-and the notion that a spare should be packed for emergencies is misconceived: nearly all kidney disease affects both.</p><p>The risks are in the operation. &ldquo;I had a one-in-four-thousand chance of dying,&rdquo; Kravinsky told me. &ldquo;But my recipient had a certain death facing her.&rdquo; To Kravinsky, this was straightforward: &ldquo;I&rsquo;d be valuing my life at four thousand times hers if I let consideration of mortality sway me.&rdquo;</p><p>He made one other calculation: there was a chance that one of his four children-then aged between three and eleven-might need a kidney that only he could supply. Kravinsky took into account the rarity of childhood kidney disease, the fact that he had only ten or so years left as a viable donor, and the fact that siblings tend to be the best kidney matches-his children were well provided with siblings. He decided that the risk was no greater than one in two hundred and fifty thousand, and that it was a risk he could accept. In fact, Kravinsky began to think of a donation as &ldquo;a treat to myself. I really thought of it as something pleasurable.&rdquo;</p><p>In a now famous 1972 essay, &ldquo;Famine, Affluence and Morality,&rdquo; the Australian philosopher Peter Singer set up the ethical puzzle that has become known as the Shallow Pond and the Envelope. In the first case, a child has fallen into a shallow pond and is drowning; Singer considers saving the child, and reflects on the inconvenience of muddy clothes. In the second, he is asked by the Bengal Relief Fund to send a donation to save the lives of children overseas.</p><p>To ignore the child in the pond would be despicable, most people would agree; to ignore an envelope from a charity would not be. (And the law supports that view.) But Singer&rsquo;s contention was that the two derelictions are ethically alike. &ldquo;If we can prevent something bad without sacrificing anything of comparable significance, we ought to do it,&rdquo; he has written. To allow harm is to do harm; it is wrong not to give money that you do not need for the most basic necessities.</p><p>Many philosophers disagree-and would argue, in one way or another, that we can have greater faith in our intuitive moral judgments. Colin McGinn, a philosopher at Rutgers, has called Singer&rsquo;s principle &ldquo;positively bad, morally speaking,&rdquo; for &ldquo;it encourages a way of life in which many important values are sacrificed to generalized altruism&rdquo; and devalues &ldquo;spending one&rsquo;s energies on things other than helping suffering people in distant lands. . . . Just think of how much the human race would have lost if Newton and Darwin and Leonardo and Socrates had spent their time on charitable acts!&rdquo; Singer has his adherents: in 1996, Peter Unger, a philosopher at New York University, published &ldquo;Living High and Letting Die,&rdquo; an extension of Singer&rsquo;s analysis whose aim was to show how we let ourselves off the ethical hook too easily. According to Unger, we placate our consciences with an &ldquo;illusion of innocence.&rdquo;</p><p>By the spring of 2003, Zell Kravinsky had become a man with no such illusion. &ldquo;It seems to me crystal clear that I should be giving all my money away and donating all of my time and energy,&rdquo; Kravinsky said, and he speculated that failure to be this generous was corrosive, in a way that most people don&rsquo;t recognize. &ldquo;Maybe that&rsquo;s why we&rsquo;re fatigued all the time,&rdquo; he mused-from &ldquo;the effort&rdquo; of disregarding the greater need of others. &ldquo;Maybe that&rsquo;s why we break down and suffer depressions: we have a sense that there&rsquo;s something we should be remembering and we&rsquo;re not. Maybe that&rsquo;s what we should be remembering-that other people are suffering.&rdquo;</p><p>He discussed the idea of kidney donation with his family and friends. &ldquo;I thought, at first, that people would understand,&rdquo; Kravinsky told me. &ldquo;But they don&rsquo;t understand math. That&rsquo;s an American pastime-grossly misunderstanding math. I&rsquo;ve had to repeat it over and over. Some people eventually got it. But many people felt the way my wife did: she said, &lsquo;No matter how infinitesimal the risk to your family, we&rsquo;re your family, and the recipient doesn&rsquo;t count.&rsquo; "</p><p>Arguments about philanthropic extremes tend to be arguments about families. In &ldquo;Bleak House,&rdquo; Dickens says of his character Mrs. Jellyby that she &ldquo;could see nothing nearer than Africa&rdquo;: in a home full of trash, she is so busy helping the unfortunate abroad that she disregards her children, who are filthy and covered with bruises-the &ldquo;notched memoranda of their accidents.&rdquo; As Esther Summerson, the novel&rsquo;s moral center, says of Mrs. Jellyby, &ldquo;It is right to begin with the obligations of home. . . . While those are overlooked and neglected, no other duties can possibly be substituted for them.&rdquo; This is a reasonable case for philanthropic restraint, but it&rsquo;s also an excuse for philanthropic inaction: the narrator of Nick Hornby&rsquo;s novel &ldquo;How to Be Good&rdquo; wrestles with this argument, guiltily, after her husband makes a sudden conversion to virtue-giving away money and goods, and offering their spare room to a homeless teen-ager. &ldquo;I&rsquo;m a liberal&rsquo;s worst nightmare,&rdquo; her husband says, in response to the narrator&rsquo;s Esther-like fears for her children&rsquo;s comfort. &ldquo;I think everything you think. But I&rsquo;m going to walk it like I talk it.&rdquo;</p><p>Chuck Collins, a great-grandson of Oscar Mayer, is a rare nonfictional example of someone who gave away all his assets during his lifetime-a half-million-dollar inheritance, which he donated to charity nearly twenty years ago. He became used to hearing pleas in behalf of his (then only potential) offspring. &ldquo;People would say, &lsquo;That&rsquo;s fine, you can be reckless in your own life, but you shouldn&rsquo;t do that to your children,&rsquo; " Collins told me. &ldquo;But I think parents make decisions for their kids all the time-that&rsquo;s what parenting is.&rdquo; He now has a daughter, who does not live like a Jellyby. &ldquo;Of course, we have to respond to our immediate family, but, once they&rsquo;re O.K., we need to expand the circle. A larger sense of family is a radical idea, but we get into trouble as a society when we don&rsquo;t see that we&rsquo;re in the same boat.&rdquo;</p><p>Kravinsky&rsquo;s conversations with his family, and about his family, left him feeling like an alien. &ldquo;The sacrosanct commitment to the family is the rationalization for all manner of greed and selfishness,&rdquo; he said. &ldquo;Nobody says, &lsquo;I&rsquo;m working for the tobacco company because I like the money.&rsquo; They say, &lsquo;Well, you know, I hate to do it, but I&rsquo;m saving up for the kids.&rsquo; Everything is excused that way. To me, it&rsquo;s obscene.&rdquo;</p><p>During one of our conversations, I asked Kravinsky to calculate a ratio between his love for his children and his love for unknown children. Many people would refuse to engage in this kind of thought experiment, but Kravinsky paused for only a moment. &ldquo;I don&rsquo;t know where I&rsquo;d set it, but I would not let many children die so my kids could live,&rdquo; he said. &ldquo;I don&rsquo;t think that two kids should die so that one of my kids has comfort, and I don&rsquo;t know that two children should die so that one of my kids lives.&rdquo;</p><p>Judith Jarvis Thomson, a philosopher at M.I.T. and the author of &ldquo;The Realm of Rights,&rdquo; later told me, &ldquo;His children are presumably no more valuable to the universe than anybody else&rsquo;s children are, but the universe doesn&rsquo;t really care about<em>any</em> children-yours or mine or anybody else&rsquo;s. A father who says, &lsquo;I&rsquo;m no more concerned about my children&rsquo;s lives than about anybody else&rsquo;s life&rsquo; is just flatly a defective parent; he&rsquo;s deficient in views that parents ought to have, whether it maximizes utility or not.&rdquo;</p><p>Someone who knows both Kravinskys well told me, &ldquo;If your spouse is doing something to himself, he is, to a certain extent, doing it to you also. Zell would be an exasperating person to be married to.&rdquo; Susan Katz, the wife of Kravinsky&rsquo;s friend Barry Katz, told me, &ldquo;I thought he was crazy. I thought it was just weird. If you&rsquo;re a father, you can&rsquo;t put your life at risk.&rdquo; Kravinsky said that his wife&rsquo;s initial attitude echoed these sentiments-she was &ldquo;adamantly opposed,&rdquo; on the ground of familial responsibility. She eventually grew more accepting of the idea, at least in the abstract. During a recent telephone conversation in which her anger about Zell&rsquo;s actions was made clear, Emily disputed this description, saying that her opposition was constant, and derived from her opinion that Zell, who has digestive difficulties, was unsuited to an operation of this kind. &ldquo;I have no objection to nondirected organ donations,&rdquo; she said. &ldquo;I think they&rsquo;re a very good thing, if the donor is medically appropriate for elective surgery, and if the donation is carried out in a medical center that&rsquo;s prepared to provide good care.&rdquo;</p><p>The rest was math and poetry: Kravinsky has said that he was driven by &ldquo;the mathematical calculus of utilitarianism,&rdquo; which gives primacy to the idea of the &ldquo;greatest good.&rdquo; But he acknowledges, too, another impulse, which emanated from what he calls his romantic or neurotic self: to give a kidney was a self-sacrificing, self-dramatizing act. The utilitarian in Kravinsky might give up his coat to a stranger, if to have no coat would not disable him as a champion of the coatless; but the romantic in Kravinsky would give the coat unquestioningly, loudly renounce coat-wearing worldwide, and then give away his pants.</p><p>In April, 2003, Kravinsky called the Albert Einstein Medical Center, an inner-city hospital where he could be fairly confident that a donated kidney would go to a low-income African-American patient. Kravinsky told me that the transplant coordinator who spoke to him was &ldquo;pretty leery of the whole thing, and kept telling me there was no payment.&rdquo; The hospital had never operated on a nondirected donor. But he went there to meet a surgeon, who believed Kravinsky&rsquo;s reports of two Ph.D.s and his philanthropy only after doing a Google search, and then a psychiatrist, who told him, &ldquo;You&rsquo;re doing something you don&rsquo;t have to do.&rdquo; Kravinsky replied, &ldquo;I<em>do</em> have to do it. You&rsquo;re missing the whole point. It&rsquo;s as much a necessity as food, water, and air.&rdquo;</p><p>Kravinsky acknowledged that he suffered from depression and that he did not have his wife&rsquo;s approval for the donation. He allowed the hospital to speak to his own psychiatrist, but said that he would not be able to bring Emily in for joint consultations. The hospital accepted this, after officials learned that family support of nondirected donors is often hesitant, at best. &ldquo;The consensus was, if this is what he wants to do and he&rsquo;s a competent individual, you can&rsquo;t deny him because someone doesn&rsquo;t want him to do it,&rdquo; Radi Zaki, the director of the Center for Renal Disease at Albert Einstein, said. &ldquo;But we made the process hard for him. We delayed, we put him off. The more impatient he got, the more delay I gave him. You want to make sure this is the real deal.&rdquo;</p><p>In June, Kravinsky was accepted for the operation. Donnell Reid, a twenty-nine-year-old single black woman studying for a degree in social work, whose hypertension had forced her to undergo dialysis for eight years, was informed that she was the possible recipient of a kidney from a nondirected donor. &ldquo;It was so surreal,&rdquo; she recently told me. &ldquo;You&rsquo;re going about your life, and then you get this phone call.&rdquo; She went in for tests, then waited. &ldquo;I prayed. I left it in God&rsquo;s hands.&rdquo; She told none of her friends: &ldquo;It was such an overwhelming thing, such an awesome thing, I wanted to meditate on it on my own.&rdquo; A week later, on July 7th, she learned that she had been selected for the operation, and the next day, at Kravinsky&rsquo;s request, they met at the transplant center. They talked for two hours. She described her plans for the future, and thanked him for a generosity &ldquo;beyond words.&rdquo;</p><p>On July 22nd, Kravinsky left home early-&ldquo;I snuck out&rdquo;-and drove to the hospital, where Zaki asked him again if he would like to reconsider his decision. &ldquo;He was very calm,&rdquo; Zaki recalls. Kravinsky had not told his wife the details of his plan, but he had approached a reporter at the Philadelphia<em>Daily News,</em> a local tabloid, which ran a story that morning. In a three-hour operation that started at 8 a.m.-a laparoscopic removal, requiring minimal incisions-he gave up his right kidney to Reid, who was in the room next door.</p><p>The next morning, Kravinsky called his wife from his hospital bed. Because of his digestive complications, he had to be taken off opiate-based painkillers, and he says that he took nothing in their place. (Zaki, affectionately describing Kravinsky as a &ldquo;dramatic&rdquo; patient, disputed this memory of total abstinence.) Zell asked Emily for help: &ldquo;She was furious. She didn&rsquo;t want me to die, but, on the other hand, she was beyond human rage.&rdquo; She said that she was willing to talk to the doctors about his treatment. She also threatened to divorce him.</p><p>At that moment, Kravinsky recalled, &ldquo;I really thought I might have shot it with my family.&rdquo; His parents were also appalled. When Reeda Kravinsky visited her son in the hospital, she recalled, &ldquo;I was so filled with anger that I didn&rsquo;t speak.&rdquo; Meanwhile, Kravinsky&rsquo;s mind was still turning on philanthropic questions. &ldquo;I lay there in the hospital, and I thought about all my other organs. When I do something good, I feel that I can do more; I burn to do more. It&rsquo;s a heady feeling.&rdquo; He went home after four days, and by then he was wondering if he should give away his other kidney.</p><p>A few weeks ago, in a Barnes &amp; Noble bookstore in Jenkintown, Kravinsky pulled out his shirt a couple of inches and showed me a tidy scar, no more than six inches long, on his right hip. &ldquo;Once in a while, I remember I only have one kidney,&rdquo; he said, smiling-apparently struck anew by the thought that the donation had been a surgical act as well as a symbolic one. &ldquo;It feels a little weird-&lsquo;Oh, yeah, I only have one!&rsquo;-but the other body parts are very happy, they have breathing room.&rdquo; It was an unusually upbeat thought, connected to a moment of moral clarity. &ldquo;It was a good deed,&rdquo; he said. &ldquo;However I screw up morally in the future, this is something nobody can take away.&rdquo;</p><p>Kravinsky&rsquo;s mood had improved since our first meeting, four months after the operation, when he had seemed vulnerable. He was always engaging, eccentric company-during lunch at a restaurant, he opened twenty packets of sugar and poured the contents into his mouth; he gave the impression that he would rather wait forever in a stationary elevator than be the one to press the button-but he was dispirited. He often spoke in fateful terms about his marriage, which had held together but was under constant stress. He worried about his relationship with his children-he showed me touching poems he had written about them-and their relationship with the world. (In the schoolyard, a child had approached one of his sons, saying, &ldquo;Why don&rsquo;t you just donate me that cheese stick?&rdquo;) He said he had lost his sense of direction. &ldquo;I feel unmoored,&rdquo; he told me.</p><p>Having redefined his life as a continuing donation, but having given away everything that came immediately to hand, Kravinsky was not sure how to proceed. His utilitarian and romantic selves were now in competition, and he did not trust his ability to distinguish between the two, or to distinguish between them and vanity. He saw a baffling choice between engagement and disengagement, between creating wealth and withdrawing into a life of poverty. When Kravinsky&rsquo;s thoughts migrated to rhetorical extremes, the choice seemed to be between life and death.</p><p>Several times, Kravinsky talked of giving away his other kidney and living on dialysis, and then he would upbraid himself for hesitating. &ldquo;If I didn&rsquo;t have kids, and I saw a child who was dying for want of a kidney, I would offer mine,&rdquo; he said. He sometimes imagined a full-body donation. &ldquo;My organs could save several people if I gave my whole body away,&rdquo; he told me. &ldquo;But I don&rsquo;t think I can do that to my family. Or, at least, I can&rsquo;t endure the humiliation. I&rsquo;ve thought about it: my kids would be under a cloud, everybody would pillory me as a showboat or a suicide. I know it&rsquo;s a thing I ought to do; other lives are equal to my own, and I could save at least three or four. I have fantasized about it. I&rsquo;ve dreamed about it. But I don&rsquo;t have the nerve.&rdquo; He said that &ldquo;before it happened I&rsquo;d have to endure the screams and yells from my family. Then I would be committed.&rdquo; He laughed. &ldquo;My wife and my sister are psychiatrists.&rdquo;</p><p>Kravinsky could see one clear role for himself: as a promoter of a free market in kidneys, an idea with limited but growing intellectual support. Richard A. Epstein, a libertarian law professor at the University of Chicago, championed this argument in his 1999 book, &ldquo;Mortal Peril: Our Inalienable Right to Health Care?,&rdquo; urging a &ldquo;frontal assault on the present legal regime&rdquo; and its &ldquo;moral philosophy of false comradeship.&rdquo; He wrote, &ldquo;No one disputes the Beatles&rsquo; proposition that &lsquo;money can&rsquo;t buy you love,&rsquo; but the proposition does not require any form of<em>ban</em> on the payment of cash in certain human relations.&rdquo; Epstein recently told me, &ldquo;When I talk about this now, nobody treats me as a complete kook. People are a little more respectful.&rdquo; In Kravinsky&rsquo;s opinion, an efficient market would quickly set a price for a kidney at ten thousand dollars or so. &ldquo;College kids would do it. A college kid goes to a party, there&rsquo;s a greater risk of dying from drugs or alcohol or a car crash than one in four thousand.&rdquo; He said that any anxiety about exploitation was misplaced: &ldquo;If the risk is lower than the other ways to make the money, where&rsquo;s the exploitation? How dare people be so condescending.&rdquo;</p><p>A few weeks after this discussion, Kravinsky called me. He had just been approached by a local woman in her forties who had spent years on dialysis, and who was running out of places on the body where a dialysis needle can enter a vein. She wanted to buy a kidney. Not long before, two young women had jointly written to Kravinsky; both were interested in selling a kidney. He told me that he had arranged to bring the women together at a cafe near his house. He would be an unpaid broker in a kidney sale. &ldquo;I&rsquo;ll take the heat, which will probably mean getting arrested,&rdquo; he said. (The 1984 National Organ Transplantation Act prohibits the sale of kidneys.) &ldquo;I feel very nervous, but I feel the decision&rsquo;s been made-because I&rsquo;m not going to let that woman die, and who else in America would do this? I&rsquo;m the only person who can save her life by setting this up. I&rsquo;m not going to do anything that stands in the way of saving a life, whether it&rsquo;s my money, my reputation. It&rsquo;s a very big step, but there&rsquo;s no choice. The choice is, I say no and the rest of my life I know that someone died.&rdquo;</p><p>He called me when he got home, a few hours later. &ldquo;Oh, brother, she&rsquo;s in bad shape,&rdquo; he said of the would-be recipient. He said that &ldquo;everyone had liked each other&rdquo; at the meeting, and an agreement had been reached. The recipient would take a kidney from whichever of the two women was a better match: both would present themselves to a hospital as friends offering a donation. The sick woman had agreed to pay fifty thousand dollars for the organ.</p><p>Kravinsky was energized-he foresaw a test case, a shift in public opinion. He was ready to embrace infamy. But when we spoke again he was worried about legal consequences. &ldquo;Can you imagine<em>me</em> in prison for five years?&rdquo; he asked.</p><p>Later, when I brought up the subject once more, he said that a lawyer had told him to &ldquo;just leave it alone.&rdquo; He was taking every opportunity to promote kidney donation, but he had given up the role of broker. Today, the three women remain in touch, but they have not yet closed a deal.</p><p>According to Kravinsky, his family was living on about sixty thousand dollars a year, from Emily&rsquo;s part-time medical practice and from interest derived from Zell&rsquo;s remaining capital. The children were in public schools; the minivans were paid for. &ldquo;The real test of my vanity would be if I gave everything away,&rdquo; Kravinsky said. &ldquo;Not just to the point of a working-class existence but to the point of poverty.&rdquo;</p><p>Yet even while Kravinsky aspired to a life spent &ldquo;passing out pamphlets on the subway,&rdquo; as he put it, it pained him to think of giving up the language of finance, which he spoke so well. &ldquo;To really achieve wealth, you have to have a love of money-you have to enjoy the play of numbers behind your eyelids,&rdquo; he said.</p><p>Indeed, near the end of last year, Kravinsky had begun talking to a local venture capitalist; together they planned a real-estate partnership that would invest on behalf of others in the kind of commercial property that Kravinsky had experience buying and selling. He would give his half of the shares to charity. Other charities could invest without paying fees. Kravinsky initially talked of this as a single stratum in a layered life of agitation, donation, and sacrifice, but this spring, as he began to talk to real-estate agents, the partnership began to emerge as a new full-time job. His mood lightened, and he seemed giddy whenever I overheard him using the jargon of amortization, appraisals, and conduit financing. &ldquo;I do feel a kind of bonhomie-it&rsquo;s strange-in business,&rdquo; he admitted.</p><p>Not long ago, Kravinsky toured a Cingular wireless-call center in eastern Kentucky, a building being offered at thirteen million dollars. His guide, the office manager, was a young tanned woman who wore pin-striped trousers. Kravinsky, bouncy and a little flirtatious, looked like a graduate student in geology, and, as he walked among the thousand desks laid out in honeycomb arrangements under signs reading &ldquo;I Am Proud to Be Part of the Perfectly Awesome Crew,&rdquo; everyone looked up. &ldquo;It&rsquo;s just a glue-down carpet?&rdquo; he asked the office manager. &ldquo;Are these load-bearing walls? Is that eight inches of concrete?&rdquo; At the end of the tour, he said, with feeling, &ldquo;This is a beautiful center, I have to say.&rdquo;</p><p>He was no longer adrift, yet he had not discovered ethical ecstasy, either. Peter Singer has called him &ldquo;a remarkable person who has taken very seriously questions of what are our moral obligations to assist people.&rdquo; He says, &ldquo;I think it&rsquo;s very difficult for people to go as far as he has, and I don&rsquo;t think we should blame people who don&rsquo;t, but we should admire those who do.&rdquo;</p><p>Kravinsky himself held on to self-doubt. He did buy the Kentucky call center; soon afterward, he spent the night at the sunny, high-ceilinged home of Barry and Susan Katz, in Westport, Connecticut. He got up late, and, long after his friends had finished breakfast, he sat eating cereal at the head of a polished black table. He was unrested, and was troubled by the thought that a renewed career in real estate might block his path to virtue.</p><p>&ldquo;But don&rsquo;t you think giving away forty-five million dollars was a good first step?&rdquo; Barry Katz asked him, taking up the challenge of having moral absolutism as a weekend house guest.</p><p>&ldquo;No,&rdquo; Kravinsky replied. &ldquo;That&rsquo;s not the hard part. The hard part is the last ten thousand dollars a year-when you have to live so cheaply you can&rsquo;t function in the business world.&rdquo; He added, &ldquo;If I need a coat to visit an investment banker&rsquo;s office because I&rsquo;ll look bizarre if I don&rsquo;t have one, but then I see somebody shiver, I should give my coat to him.&rdquo;</p><p>&ldquo;But what if you made enough money, after meeting with the investment banker, to fund research into aids prevention, something extremely good for the world?&rdquo; Katz asked. &ldquo;You&rsquo;re not going to get very far in an investment banker&rsquo;s office wearing sackcloth.&rdquo;</p><p>&ldquo;I think suits are despicable. Suits and ties. I think I should go into the office naked.&rdquo; Kravinsky was smiling. &ldquo;If I went into the office of a banker naked, I&rsquo;d be . . .&rdquo;</p><p>&ldquo;You&rsquo;d be arrested,&rdquo; Katz said.</p><p>Katz remembered the time he had hung up on Kravinsky a few weeks before the kidney operation. &ldquo;He almost broke off with you,&rdquo; Susan Katz told Kravinsky.</p><p>&ldquo;Oh, Barry,&rdquo; Kravinsky said. &ldquo;It isn&rsquo;t that I think people are evil. But it&rsquo;s a fact that our actions, in some sense our thoughts, let some people live and some people die.&rdquo;</p><p>Susan, sitting at the other end of the table, looked at Kravinsky with fond exasperation and asked, &ldquo;This is how you think every day, really? That&rsquo;s got to be tough. It seems so sad. You seem so sad.&rdquo;</p><p>&ldquo;Well, I am sad.&rdquo; Kravinsky had arranged everything within arm&rsquo;s reach-orange juice, mug, salt, sugar, cereal box-into a tight cluster on his placemat. His adventure in donation had been a rhetorical opportunity-a showcase for his underappreciated talent for argument. But for a moment the debate had slowed, and Kravinsky spoke less forcefully, in apparent recognition of the unequal ratio of sacrifice to sustenance, of good done to moral certainty felt.</p><p>&ldquo;But shouldn&rsquo;t there be more joy in this?&rdquo; Barry said.</p><p>&ldquo;I don&rsquo;t think of it as something that&rsquo;s joyful. Why should I feel joy?&rdquo;</p><p>&ldquo;I just feel that if you really were on this path to enlightenment, whatever it is, you would feel joy.&rdquo;</p><p>&ldquo;It&rsquo;s not enlightenment,&rdquo; Kravinsky said quietly. &ldquo;It&rsquo;s the start of a moral life.&rdquo;</p>
]]></description></item><item><title>Derek Parfit: a bibliography</title><link>https://stafforini.com/notes/derek-parfit-a-bibliography/</link><pubDate>Sat, 25 May 2013 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/derek-parfit-a-bibliography/</guid><description>&lt;![CDATA[<p><em><img src="/ox-hugo/derek-parfit-portrait.jpg" alt=""/></p><blockquote><p>What interests me most are the metaphysical questions whose answers can affect our emotions, and have rational and moral significance. Why does the Universe exist? What makes us the same person throughout our lives? Do we have free will? Is time&rsquo;s passage an illusion?</p></blockquote><hr><ul><li>Derek Parfit,<a href="/works/parfit-2021-improving-scanlon-s/">Improving Scanlon's contractualism</a>, in Markus S. Stepanians and Michael Frauchiger (eds.)<em>Reason, justification, and contractualism: themes from Scanlon</em>, Berlin ; Boston, 2021, pp. 109–117</li><li>Derek Parfit,<a href="/works/parfit-2017-what-matters-volume/"><em>On What Matters: Volume 3</em></a>, Oxford, 2017</li><li>Derek Parfit,<a href="/works/parfit-2017-future-people-nonidentity/">Future people, the non-identity problem, and person-affecting principles</a>,<em>Philosophy & Public Affairs</em>, vol. 45, no. 2, 2017, pp. 118–157</li><li>Derek Parfit,<a href="/works/parfit-2017-responses/">Responses</a>, in Simon Kirchin (ed.)<em>Reading Parfit: On what matters</em>, London, 2017, pp. 189–236</li><li>Derek Parfit,<a href="/works/parfit-2016-conflicting-reasons/">Conflicting reasons</a>,<em>Etica & politica</em>, vol. 18, no. 1, 2016, pp. 169–186</li><li>Derek Parfit,<a href="/works/parfit-2016-can-we-avoid/">Can we avoid the repugnant conclusion?</a>,<em>Theoria</em>, vol. 82, no. 2, 2016, pp. 110–127</li><li>Derek Parfit,<a href="/works/parfit-2016-personal-omnipersonal-duties/">Personal and omnipersonal duties:</a>,<em>The Harvard Review of Philosophy</em>, vol. 23, 2016, pp. 1–15</li><li>Derek Parfit,<a href="/works/parfit-2012-another-defence-priority/">Another defence of the priority view</a>,<em>Utilitas</em>, vol. 24, no. 3, 2012, pp. 399–440</li><li>Derek Parfit,<a href="/works/parfit-2012-we-are-not/">We are not human beings</a>,<em>Philosophy</em>, vol. 87, no. 1, 2012, pp. 5–28</li><li>Derek Parfit,<a href="/works/parfit-2011-what-matters-volumeb/"><em>On What Matters: Volume 2</em></a>, Oxford, 2011</li><li>Derek Parfit,<a href="/works/parfit-2011-what-matters-volume/"><em>On What Matters: Volume 1</em></a>, Oxford, 2011</li><li>Derek Parfit,<a href="/works/parfit-2007-persons-bodies-human/">Persons, bodies, and human beings</a>, in Dean W. Zimmerman, Theodore Sider, and John Hawthorne (eds.)<em>Contemporary debates in metaphysics</em>, Oxford, 2008, pp. 177–208</li><li>Derek Parfit,<a href="/works/parfit-2007-personal-identity-what/"><em>Is personal identity what matters?</em></a>, 2007</li><li>Derek Parfit,<a href="/works/parfit-2006-kant-arguments-his/">Kant's arguments for his formula of universal law</a>, in Christine Sypnowich (ed.)<em>The egalitarian conscience: Essays in honour of G. A. Cohen</em>, Oxford, 2006, pp. 56–69</li><li>Derek Parfit,<a href="/works/parfit-2006-normativity/">Normativity</a>, in Russ Shafer-Landau (ed.)<em>Oxford studies in metaethics</em>, Oxford, 2006, pp. 325–380</li><li>Derek Parfit,<a href="/works/parfit-2004-postcript/">Postcript</a>, in Jesper Ryberg and Torbjörn Tännsjö (eds.)<em>The Repugnant Conclusion: Essays on Population Ethics</em>, Dordrecht, 2004, pp. 257</li><li>Derek Parfit,<a href="/works/parfit-2003-justifiability-each-person/">Justifiability to each person</a>,<em>Ratio</em>, vol. 16, no. 4, 2003, pp. 368–390</li><li>Derek Parfit,<a href="/works/parfit-2004-what-we-could/">What we could rationally will</a>, in Grethe B. Peterson (ed.)<em>The Tanner lectures on human values</em>, Salt Lake City, 2004, pp. 285–369</li><li>Derek Parfit,<a href="/works/parfit-2001-rationality-reasons/">Rationality and reasons</a>, in Dan Egonsson et al. (ed.)<em>Exploring practical philosophy: from action to values</em>, Aldershot, 2001, pp. 17–39</li><li>Derek Parfit,<a href="/works/parfit-2001-bombs-coconuts-rational/">Bombs and coconuts, or rational irrationality</a>, in Christopher W. Morris and Arthur Ripstein (eds.)<em>Practical rationality and preference: Essays for David Gauthier</em>, Cambridge, 2001, pp. 81–97</li><li>Derek Parfit,<a href="/works/parfit-1999-experiences-subjects-conceptual/">Experiences, subjects, and conceptual schemes</a>,<em>Philosophical topics</em>, vol. 26, no. 1-2, 1999, pp. 217–270</li><li>Derek Parfit,<a href="/works/parfit-1998-why-anything-why-2/">Why anything? Why this?</a>,<em>London Review of Books</em>, vol. 20, no. 3, 1998, pp. 22–25</li><li>Derek Parfit,<a href="/works/parfit-1998-why-anything-why/">Why anything? Why this?</a>,<em>London Review of Books</em>, vol. 20, no. 2, 1998, pp. 24–27</li><li>Derek Parfit,<a href="/works/parfit-1997-equality-priority/">Equality and priority</a>,<em>Ratio</em>, vol. 10, no. 3, 1997, pp. 202–221</li><li>Derek Parfit,<a href="/works/parfit-1997-reasons-motivation/">Reasons and motivation</a>,<em>Aristotelian Society Supplementary Volume</em>, vol. 71, no. 1, 1997, pp. 99–130</li><li>Derek Parfit,<a href="/works/parfit-1996-acts-outcomes-reply/">Acts and outcomes: a reply to Boonin-Vail</a>,<em>Philosophy & Public Affairs</em>, vol. 25, no. 2, 1996, pp. 308–317</li><li>Derek Parfit,<a href="/works/parfit-1995-unimportance-identity/">The Unimportance of Identity</a>, in Henry Harris (ed.)<em>Identity: Essays based on Herbert Spencer lectures given in the University of Oxford</em>, Oxford, 1995</li><li>Derek Parfit,<a href="/works/parfit-1995-interview-derek-parfit/">An interview with Derek Parfit</a>,<em>Cogito</em>, vol. 9, no. 2, 1995, pp. 115–125</li><li>Derek Parfit,<a href="/works/parfit-1993-indeterminacy-identity-reply/">The indeterminacy of identity: A reply to Brueckner</a>,<em>Philosophical Studies</em>, vol. 70, no. 1, 1993, pp. 23–33</li><li>Derek Parfit,<a href="/works/parfit-1993-paul-seabright-pluralism/">Paul Seabright: Pluralism and the standard of living</a>, in Martha Nussbaum and Amartya K. Sen (eds.)<em>The Quality of Life</em>, New York, 1993, pp. 410–417</li><li>Derek Parfit,<a href="/works/parfit-1992-who-you-think/">Who do you think you are?</a>,<em>Times higher education supplement</em>, 1992, pp. 19–20</li><li>Derek Parfit,<a href="/works/parfit-1992-puzzle-reality-why/">The puzzle of reality: Why does the universe exist?</a>,<em>Times literary supplement</em>, 1992, pp. 3–5</li><li>Tyler Cowen and Derek Parfit,<a href="/works/cowen-1992-social-discount-rate/">Against the social discount rate</a>, in Peter Laslett and James Fishkin (eds.)<em>Justice between age groups and generations</em>, New Haven, 1992, pp. 144–161</li><li>Derek Parfit,<a href="/works/parfit-1991-isaiah-berlin/">Isaiah Berlin</a>,<em>Times literary supplement</em>, 1991, pp. 13</li><li>Derek Parfit,<a href="/works/parfit-1991-why-does-universe/">Why does the universe exist?</a>,<em>Harvard review of philosophy</em>, vol. 1, no. 1, 1991, pp. 2–5</li><li>Derek Parfit,<a href="/works/parfit-1991-equality-priority/"><em>Equality or priority</em></a>, Lawrence, 1991</li><li>Derek Parfit,<a href="/works/parfit-1988-what-we-together/">What we together do</a>,<em>What we together do</em>, no. unpublished, 1988</li><li>Derek Parfit,<a href="/works/parfit-1987-response/">A response</a>, in A. R. Peacocke and Grant Gillett (eds.)<em>Persons and personality: a contemporary inquiry</em>, Oxford, 1987, pp. 88–98</li><li>Derek Parfit,<a href="/works/parfit-1987-reply-sterba/">A reply to Sterba</a>,<em>Philosophy & Public Affairs</em>, vol. 16, no. 2, 1987, pp. 193–194</li><li>Derek Parfit,<a href="/works/parfit-1987-divided-minds-nature/">Divided minds and the nature of persons</a>, in Colin Blakemore and Susan Greenfield (eds.)<em>Mindwaves: thoughts on intelligence, identity and consciousness</em>, Oxford, 1987, pp. 19–28</li><li>Derek Parfit,<a href="/works/parfit-1986-comments/">Comments</a>,<em>Ethics</em>, vol. 96, no. 4, 1986, pp. 832–872</li><li><span class="cite-unresolved" title="No work page found for Parfit1986OverpopulationAndQuality">Parfit1986OverpopulationAndQuality</span></li><li>Derek Parfit,<a href="/works/parfit-1984-rationality-time/">Rationality and time</a>,<em>Proceedings of the Aristotelian Society</em>, vol. 84, no. 1, 1984, pp. 47–82</li><li>Derek Parfit,<a href="/works/parfit-1984-reasons-persons/"><em>Reasons and persons</em></a>, Oxford, 1984</li><li>Derek Parfit,<a href="/works/parfit-1983-energy-policy-further/">Energy policy and the further future: the social discount rate</a>, in Douglas MacLean and Peter G. Brown (eds.)<em>Energy and the future</em>, Totowa, New Jersey, 1983, pp. 31–37</li><li>Derek Parfit,<a href="/works/parfit-1983-energy-policy-furthera/">Energy policy and the further future: the identity problem</a>, in Douglas MacLean and Peter G. Brown (eds.)<em>Energy and the future</em>, Totowa, New Jersey, 1983, pp. 166–179</li><li>Daniel Dennett et al.,<a href="/works/dennett-1982-summary-of-discussion/">Summary of discussion</a>,<em>Synthese</em>, vol. 53, no. 2, 1982, pp. 251–256</li><li>Derek Parfit,<a href="/works/parfit-1982-personal-identity-rationality/">Personal identity and rationality</a>,<em>Synthese</em>, vol. 53, no. 2, 1982, pp. 227–241</li><li>Derek Parfit,<a href="/works/parfit-1982-future-generations-further/">Future generations: further problems</a>,<em>Philosophy & Public Affairs</em>, vol. 11, no. 2, 1982, pp. 113–172</li><li>Derek Parfit,<a href="/works/parfit-1981-correspondence/">Correspondence</a>,<em>Philosophy & Public Affairs</em>, vol. 10, no. 2, 1981, pp. 180–181</li><li>Derek Parfit,<a href="/works/parfit-1981-attack-social-discount/">An attack on the social discount rate</a>,<em>Philosophy & public policy quarterly</em>, vol. 1, no. 1, 1980, pp. 8–11</li><li>Derek Parfit,<a href="/works/parfit-1979-commonsense-morality-selfdefeating/">Is common-sense morality self-defeating?</a>,<em>Journal of philosophy</em>, vol. 76, no. 10, 1979, pp. 533–545</li><li>Derek Parfit,<a href="/works/parfit-1979-correspondence/">Correspondence</a>,<em>Philosophy & Public Affairs</em>, vol. 8, no. 4, 1979, pp. 395–397</li><li>Derek Parfit,<a href="/works/parfit-1979-prudence-morality-prisoner/">Prudence, morality, and the prisoner's dilemma</a>,<em>Proceedings of the British Academy</em>, vol. 65, 1979, pp. 539–564</li><li>Derek Parfit,<a href="/works/parfit-1978-innumerate-ethics/">Innumerate ethics</a>,<em>Philosophy & Public Affairs</em>, vol. 7, no. 4, 1978, pp. 285–301</li><li>Derek Parfit,<a href="/works/parfit-1976-lewis-perry-what/">Lewis, Perry, and what matters</a>, in Amélie Oksenberg Rorty (ed.)<em>The identities of persons</em>, Berkeley, California, 1976, pp. 91–107</li><li>Derek Parfit,<a href="/works/parfit-1976-doing-best-our/">On doing the best for our children</a>, in Michael D. Bayles (ed.)<em>Ethics and population</em>, Cambridge,Mass, 1976, pp. 100–115</li><li>Derek Parfit,<a href="/works/parfit-1976-rights-interests-possible/">Rights, interests, and possible people</a>, in Samuel Gorovitz et al. (ed.)<em>Moral problems in medicine</em>, Englewood Cliffs, NJ, 1976, pp. 369–375</li><li>Derek Parfit,<a href="/works/parfit-1973-later-selves-moral/">Later selves and moral principles</a>, in Alan Montefiore (ed.)<em>Philosophy and personal relations: an Anglo-French study</em>, London, 1973, pp. 137–169</li><li>Derek Parfit,<a href="/works/parfit-1971-importance-selfidentity/">On "The importance of self-identity"</a>,<em>Journal of philosophy</em>, vol. 68, no. 20, 1971, pp. 683–690</li><li>Derek Parfit,<a href="/works/parfit-1971-personal-identity/">Personal identity</a>,<em>Philosophical review</em>, vol. 80, no. 1, 1971, pp. 3–27</li><li>Derek Parfit,<a href="/works/parfit-1964-eton-college-chronicle/">The Eton College chronicle</a>, in Anthony Cheetham and Derek Parfit (eds.)<em>Eton microcosm</em>, London, 1964, pp. 100–103</li><li>Derek Parfit,<a href="/works/parfit-1964-fish/">The fish</a>, in Anthony Cheetham and Derek Parfit (eds.)<em>Eton microcosm</em>, London, 1964, pp. 182–183</li><li>Anthony Cheetham and Derek Parfit (eds.),<a href="/works/cheetham-1964-eton-microcosm/"><em>Eton microcosm</em></a>, London, 1964</li><li>Derek Parfit,<a href="/works/parfit-1963-like-pebbles/">Like pebbles</a>,<em>ISIS</em>, 1963, pp. 21–22</li><li>Derek Parfit,<a href="/works/parfit-1962-photograph-of-comtesse/">Photograph of a Comtesse</a>,<em>The New Yorker</em>, 1962, pp. 24</li></ul><p><em>With thanks to David Edmonds, Johan Gustafsson, and Matthew van der Merwe.</em></p><hr><blockquote><p>What now matters most is how we respond to various risks to the survival of humanity. We are creating some of these risks, and we are discovering how we could respond to these and other risks. If we reduce these risks, and humanity survives the next few centuries, our descendants or successors could end these risks by spreading through this galaxy.</p><p>Life can be wonderful as well as terrible, and we shall increasingly have the power to make life good. Since human history may be only just beginning, we can expect that future humans, or supra-humans, may achieve some great goods that we cannot now even imagine. In Nietzsche&rsquo;s words, there has never been such a new dawn and clear horizon, and such an open sea.</p></blockquote><figure><a href="/ox-hugo/venice-lagoon-storm.jpg" target="_blank" rel="noopener"><img src="/ox-hugo/venice-lagoon-storm.jpg" alt="Venice lagoon under storm clouds, photographed by Derek Parfit"/></figure>
]]></description></item><item><title>The most important questions and problems</title><link>https://stafforini.com/notes/the-most-important-questions-and-problems/</link><pubDate>Sun, 20 Aug 2017 00:00:00 +0000</pubDate><guid>https://stafforini.com/notes/the-most-important-questions-and-problems/</guid><description>&lt;![CDATA[<p>What are the most important questions to answer? What are the most important problems to solve? Various people and organizations in the effective altruist community have over the years compiled lists of such questions and problems. This post provides links and brief descriptions of all the lists I&rsquo;m currently aware of. (Note that many of these lists focus on specific causes, such as artificial intelligence, or on specific disciplines, such as moral philosophy.)</p><p><em>Update: This post was originally written in 2017. Michael Aird has more recently compiled a very comprehensive<a href="https://forum.effectivealtruism.org/posts/MsNpJBzv5YhdfNHc9/a-central-directory-for-open-research-questions">list of open research questions</a>, which largely supersedes the present list (though Aird&rsquo;s directory excludes some entries included here).</em></p><p><em>Further update: 80,000 hours has now released an impressive<a href="https://80000hours.org/articles/research-questions-by-discipline/">list of research questions that could have a big social impact, organised by discipline</a></em>.</p><h2 id="hours"><a href="https://80000hours.org/articles/cause-selection/">80,000 Hours</a></h2><p>A ranking of the top 10 most pressing global problems, rated by scale, neglectedness, and tractability.</p><h2 id="hours-1"><a href="https://forum.effectivealtruism.org/posts/xoxbDsKGvHpkGfw9R/">80,000 Hours</a></h2><p>A more extensive list of problem areas outside those listed above.</p><h2 id="ai-impacts"><a href="https://aiimpacts.org/promising-research-projects/">AI Impacts</a></h2><p>A list of tractable and important AI-relevant projects. See also their<a href="https://aiimpacts.org/ai-impacts-key-questions-of-interest/">list of key questions of interest</a> and their<a href="https://aiimpacts.org/possible-investigations/">list of possible empirical investigations</a>.</p><h2 id="center-for-reducing-suffering"><a href="https://centerforreducingsuffering.org/open-research-questions/">Center for Reducing Suffering</a></h2><p>A list of research directions relevant for reducing suffering.</p><h2 id="center-on-long-term-risk"><a href="https://longtermrisk.org/open-research-questions/">Center on Long-Term Risk</a></h2><p>A comprehensive ranking of open research questions, rated by importance.</p><h2 id="future-of-life-institute"><a href="http://futureoflife.org/data/documents/research_survey.pdf">Future of Life Institute</a></h2><p>A survey of research questions for robust and beneficial AI.</p><h2 id="global-priorities-institute"><a href="https://globalprioritiesinstitute.org/wp-content/uploads/gpi-research-agenda.pdf">Global Priorities Institute</a></h2><p>A detailed list of important problems.</p><h2 id="open-philanthropy-project"><a href="http://www.openphilanthropy.org/blog/technical-and-philosophical-questions-might-affect-our-grantmaking">Open Philanthropy Project</a></h2><p>A list of technical and philosophical questions that could influence OpenPhil&rsquo;s grantmaking strategy.</p><h2 id="nick-beckstead"><a href="http://www.nickbeckstead.com/advice/ea-research-topics">Nick Beckstead</a></h2><p>A list of valuable research questions, with a focus on the long term. See also Nick&rsquo;s presentation on &lsquo;<a href="https://drive.google.com/file/d/0B8_48dde-9C3dUNSVUhQWkdtMDlsa3RweE03QnJXYy0za1JN/view">Jobs I wish EAs would do</a>&rsquo;.</p><h2 id="wei-dai"><a href="https://www.alignmentforum.org/posts/rASeoR7iZ9Fokzh7L/problems-in-ai-alignment-that-philosophers-could-potentially">Wei Dai</a></h2><p>A list of problems in AI Alignment that philosophers could potentially contribute to.</p><h2 id="robin-hanson"><a href="https://www.overcomingbias.com/2020/11/join-the-universe.html">Robin Hanson</a></h2><p>A list of 40 or so &ldquo;big&rdquo; questions. See also his<a href="https://www.overcomingbias.com/2017/02/neglected-big-problems.html">list of important and neglected problems</a>.</p><h2 id="jamie-harris"><a href="https://www.sentienceinstitute.org/blog/prioritization-questions-for-artificial-sentience"><strong>Jamie Harris</strong></a></h2><p>A list of possible crucial considerations for artificial sentience.</p><h2 id="holden-karnofsky"><a href="https://forum.effectivealtruism.org/posts/zGiD94SHwQ9MwPyfW/important-actionable-research-questions-for-the-most">Holden Karnofsky</a></h2><p>A list of important, actionable research questions given that the present century could be the most pivotal in history.</p><h2 id="will-macaskill"><a href="https://80000hours.org/2012/10/the-most-important-unsolved-problems-in-ethics/">Will MacAskill</a></h2><p>A list of the most important unresolved problems in moral philosophy.</p><h2 id="luke-muehlhauser"><a href="http://lukemuehlhauser.com/some-studies-which-could-improve-our-strategic-picture-of-superintelligence/">Luke Muehlhauser</a></h2><p>A comprehensive list of potential studies that could, if carried out, illuminate our strategic situation with regard to superintelligence. See also<a href="https://www.lesswrong.com/posts/i2XoqtYEykc4XWp9B/ai-risk-and-opportunity-a-strategic-analysis">this early post</a>.</p><h2 id="richard-ngo"><a href="https://forum.effectivealtruism.org/posts/2e9NDGiXt8PjjbTMC/technical-agi-safety-research-outside-ai">Richard Ngo</a></h2><p>A list of questions whose answers would be useful for technical AGI safety research, but which will probably require expertise outside AI to answer.</p><h2 id="jess-riedel"><a href="https://blog.jessriedel.com/2016/03/15/physicswell/">Jess Riedel</a></h2><p>A list of topics in physics that should be funded on the margin right now by someone trying to maximize positive impact for society.</p><h2 id="anders-sandberg"><a href="http://aleph.se/andart2/human-development/best-problems-to-work-on/">Anders Sandberg</a></h2><p>A short list of the best problems to work on, intended as a supplement to 80,000 Hours&rsquo; ranking. See also Anders&rsquo; final answer in<a href="https://intelligence.org/2014/03/02/anders-sandberg/">this interview</a>, which mentions the research questions that he believes are most relevant to space colonization.</p>
]]></description></item></channel></rss>