<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Skylos</title>
    <link rel="self" type="application/atom+xml" href="https://skylosblog.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://skylosblog.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-06-18T00:00:00+00:00</updated>
    <id>https://skylosblog.com/atom.xml</id>
    <entry xml:lang="en">
        <title>RSS has been added to the blog!!</title>
        <published>2026-06-18T00:00:00+00:00</published>
        <updated>2026-06-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/rss-announcement/"/>
        <id>https://skylosblog.com/posts/rss-announcement/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/rss-announcement/">&lt;p&gt;I finally got around to enabling feed generation in Zola! you can click the RSS Icon in the navbar or click &lt;a href=&quot;&#x2F;atom.xml&quot;&gt;here&lt;&#x2F;a&gt; to go to the atom.xml file!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introductory Concepts of Cyber-security</title>
        <published>2026-06-17T00:00:00+00:00</published>
        <updated>2026-06-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/cybersecurity101/"/>
        <id>https://skylosblog.com/posts/cybersecurity101/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/cybersecurity101/">&lt;div class=&quot;note-container&quot;&gt;
    
            &lt;div class=&quot;note-header&quot;&gt;
                
                    &lt;div class=&quot;note-icon&quot;&gt;&lt;p&gt;Note!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
                
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;note-content&quot;&gt;&lt;p&gt;this post is in progress, but there’s enough stuff that it has utility in its current form&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
        
    &lt;&#x2F;div&gt;
&lt;p&gt;Cyber-security as a field is concerned with protecting digital assets. It may conjure to mind dark rooms and hackers and hoaky 90s CGI imaginations of what the inside of a mainframe looks like ala Tron. In reality Cyber-security has a lot more to do do with the security half of its name rather than the the cyber half. Any digital asset (data bases, web-servers, secret files, etc) still has to exist physically on a computer somewhere and that somewhere has to be physically secure in order for anything on the machine to be secure. The need to be physically secure means that conventional security practices are still relevant when considering digital security, it’s just that when an asset is digital it exists as information that can be transmitted over the internet, so there’s additional aveneues of access we need to control.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-core-vocabulary&quot;&gt;some core vocabulary&lt;&#x2F;h1&gt;
&lt;p&gt;Let’s now take the time to establish some precise vocabulary used within cybersecurity. This whole time I’ve been using the word “&lt;strong&gt;secure&lt;&#x2F;strong&gt;” but what exactly does that mean? There a few definitions of differing level of detail, but the most common definition you’ll see makes use of something called the &lt;strong&gt;CIA triad&lt;&#x2F;strong&gt;, an acronym that covers the three main attributes of security. We consider information secure only when it meets all 3 attributes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Confidentiality&lt;&#x2F;strong&gt;: Private information is kept private. If we have someone’s credit card number, we want tp ensure that information isn’t learned by the public or a third party. Risk factors include data leaks like heart-bleed, intentional espionage, and accidentally publishing internal documents.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Integrity&lt;&#x2F;strong&gt;: All information we have is correct. Potential risk factors include random data corruption as well as intentional altering of records.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Accessibility&lt;&#x2F;strong&gt;: We can always access our information when we need it. We can stop anyone from extracting the data on a usb stick by destroying the usb stick. But, that doesn’t mean we’ve secured the information, since now we can’t access it either. Risk factors include natural disasters shutting down our server, and ransom-ware encrypting our data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In providing the examples above, I’ve introduced a new piece of vernacular: a &lt;strong&gt;risk factor&lt;&#x2F;strong&gt; is any event that could compromise the security of our digital asset, from hackers,to natural disasters, or a trusted member of the organization unintentionally deleting or sharing information.&lt;&#x2F;p&gt;
&lt;p&gt;We create assurance of security by implementing what we call &lt;strong&gt;security controls&lt;&#x2F;strong&gt;. Controls are any policy or infrastructure we use to mitigate risk factors. Some examples include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;badging into a building (by preventing 3rd parties from entering a space we enforce confidentiality)&lt;&#x2F;li&gt;
&lt;li&gt;duplicating data (by creating back-ups we protect accessibility in the case of a server shut-down)&lt;&#x2F;li&gt;
&lt;li&gt;keeping change logs (we can undo any incorrect changes to re-establish integrity).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;(as an aside: notice how we can usually sort controls by how they affect one or more of the items in the CIA triad)&lt;&#x2F;p&gt;
&lt;p&gt;Controls can be divided into preventative and reactive controls. Preventative controls look to prevent a security risk from happening. Reactive controls look to detect, record, and undo a security risk after it’s happened. In general we need a blend of both since prevention is good, but if we cannot detect and recover from a security breach, then we cannot trust our information’s integrity.&lt;&#x2F;p&gt;
&lt;p&gt;Other terms of art include:&lt;&#x2F;p&gt;
&lt;dl&gt;
&lt;dt&gt;adversary&lt;&#x2F;dt&gt;
&lt;dd&gt;a malicious third party actively trying to breach your security, usually used to refer to an imagined person for the sake of thinking through risk factors than an actual real life individual.&lt;&#x2F;dd&gt;
&lt;dt&gt;asset&lt;&#x2F;dt&gt;
&lt;dd&gt;anything we’re trying to protect. In cyber-security, that generally means a &lt;strong&gt;digital asset&lt;&#x2F;strong&gt; or &lt;strong&gt;information asset&lt;&#x2F;strong&gt;.&lt;&#x2F;dd&gt;
&lt;&#x2F;dl&gt;
&lt;h1 id=&quot;risk&quot;&gt;risk&lt;&#x2F;h1&gt;
&lt;p&gt;understanding what can go wrong, and how likely it is, is the first step of security. Technically we can implement security controls without thinking through what could happen, but that’s a good way to end up spending a lot of effort somewhere it’s not needed. Instead, we  can do a &lt;strong&gt;risk assessment&lt;&#x2F;strong&gt; and build up a &lt;strong&gt;risk profile&lt;&#x2F;strong&gt; of risk factors relevant to our asset, the probability of those risks and the magnitude of consequences should those risk factors occur. We can then use our risk profile to decide on our &lt;strong&gt;risk management&lt;&#x2F;strong&gt; strategy and security controls. Thankfully, we don’t need to spend all day catastrophizing and thinking up all the ways thing can go wrong all on our own. There are wonderful organizations that have put together &lt;strong&gt;risk catalogues&lt;&#x2F;strong&gt; or &lt;strong&gt;risk registers&lt;&#x2F;strong&gt;: compendiums of potential risks for us to peruse and think through.&lt;&#x2F;p&gt;
&lt;p&gt;Risk management strategies can be catagorized as follows&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;risk modification (reducing probability)&lt;&#x2F;li&gt;
&lt;li&gt;risk mitigation (reducing the potential damage)&lt;&#x2F;li&gt;
&lt;li&gt;risk acceptance (the risk will just happen, oh well, it’s not worth fixing)&lt;&#x2F;li&gt;
&lt;li&gt;risk sharing&#x2F;distribution (like an insurance plan that pays out, or subcontracting out)&lt;&#x2F;li&gt;
&lt;li&gt;risk avoidance (simply cut off the risk bearing part and stop doing it), used when the asset is low value but high damage.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;note that without proper security practices we’re living with risk acceptance by default.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine we are a small org with lots of field workers, called CommunityCheck. Those workers go out to talk to multiple constituents a day and bring with them a clipboard of information from the org as well as any notes they take in the field. One potential risk factor is that, if they keep all their notes on the clipboard uncovered, they might accidentally show a constituent’s private information to someone else while just walking around.&lt;&#x2F;p&gt;
&lt;p&gt;We could try to avoid the risk completely by either ceasing field work or preventing field workers from bringing any information with them. If field-work isn’t very important to our org that might be worth doing. We could also share risk, ceasing our own field work but contracting it out to another organization. But given we have so many field workers, lets say field-work is essential enough that we have to keep doing it ourselves.&lt;&#x2F;p&gt;
&lt;p&gt;We could modify risk by providing field workers with opaque binders, so that no information is visible until they open the binder while talking to a constituent. We could mitigate the risk by creating policies around what information can be brought into the field and how many constituent’s information a field worker can have on hand at once, so that if an exposure happens the information at risk is less of a privacy violation and less constituents are affected.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;security-principles&quot;&gt;security principles&lt;&#x2F;h1&gt;
&lt;p&gt;Some common best practices to help keep our assets secure include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;security controls need to be simple enough that they can be easily audited and verified.&lt;&#x2F;li&gt;
&lt;li&gt;rely on positively identifying benevolent actors. Adversaries can always pick a new unrecognized strategy, so trying to identify and exclude malicious behavior is a losing game.&lt;&#x2F;li&gt;
&lt;li&gt;security through obscurity&#x2F;secrecy is not security at all.&lt;&#x2F;li&gt;
&lt;li&gt;principle of least privilege: every individual should only have the bare minimum security clearance in order to do their job.&lt;&#x2F;li&gt;
&lt;li&gt;usability: if a security control is too much of a hassle, the people who are meant to use it won’t.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!--## People


## Example
Returning to our CommunityCheck example, lets look at some of our possible security controls with an eye towards our security principles.--&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Items of known dimension</title>
        <published>2026-04-11T00:00:00+00:00</published>
        <updated>2026-04-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/items-of-known-dimension/"/>
        <id>https://skylosblog.com/posts/items-of-known-dimension/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/items-of-known-dimension/">&lt;p&gt;Ever need to measure something and don’t have a ruler or any other tool on hand? Here is a list of common mass produced and standardized objects and their dimensions:&lt;&#x2F;p&gt;
&lt;p&gt;!note: 10mm = 0.3937“,  1“ = 25.4mm&lt;&#x2F;p&gt;
&lt;p&gt;in putting together this list, at the very end, I found this amazing website that’s like this blog post but so much more! Go check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dimensions.com&quot;&gt;Dimensions.com&lt;&#x2F;a&gt;!!!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;batteries&quot;&gt;Batteries&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;AA:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;14.50mm (0.571“) wide&lt;&#x2F;li&gt;
&lt;li&gt;50.50mm (1.988“) from flat to nipple&lt;&#x2F;li&gt;
&lt;li&gt;49.20mm (1.937“) barrel length&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;data.energizer.com&#x2F;pdfs&#x2F;1215.pdf&quot;&gt;data sheet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;AAA:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;10.50mm (0.413“) diameter&lt;&#x2F;li&gt;
&lt;li&gt;44.50mm (1.752“) from flat to nipple&lt;&#x2F;li&gt;
&lt;li&gt;43.30mm (1.705“) excluding the nipple&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;data.energizer.com&#x2F;pdfs&#x2F;aaa-alkaline-power.pdf&quot;&gt;data sheet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;9volt:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;26.50mm (1.043“) wide&lt;&#x2F;li&gt;
&lt;li&gt;17.50mm (0.689“) thick&lt;&#x2F;li&gt;
&lt;li&gt;48.50mm (1.909“) tall from flat to terminals&lt;&#x2F;li&gt;
&lt;li&gt;46.40mm (1.827“) tall from flat to flat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;data.energizer.com&#x2F;pdfs&#x2F;1222-.pdf&quot;&gt;data sheet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- # keys 
## sources
- &lt;https:&#x2F;&#x2F;sweets.construction.com&#x2F;swts_content_files&#x2F;153346&#x2F;657056.pdf&gt; --&gt;
&lt;h1 id=&quot;paper-items&quot;&gt;Paper items&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;iso-sizes&quot;&gt;ISO sizes&lt;&#x2F;h2&gt;
&lt;p&gt;interestingly the ISO A series sizes are defined by all having an aspect ratio that is the square root of two. A0 has an area of 1m sq. A1 half that, and so on. The B series is the same aspect ratio, but is defined as having an area that is the geometric mean between the steps in the A series.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;1&#x2F;16&#x2F;A_size_illustration2.svg&#x2F;500px-A_size_illustration2.svg.png&quot;&gt;A-series chart&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;6&#x2F;66&#x2F;B_size_illustration2.svg&#x2F;500px-B_size_illustration2.svg.png&quot;&gt;B-series chart&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A3: 297mm by 420mm (11.7“ by 16.5“)&lt;&#x2F;li&gt;
&lt;li&gt;A4: 210mm by 297mm (8.3“ by 11.7“)&lt;&#x2F;li&gt;
&lt;li&gt;A5: 148mm by 210mm (5.8“ by 8.3“)&lt;&#x2F;li&gt;
&lt;li&gt;B4: 250mm by 353mm (9.8“ by 13.9“)&lt;&#x2F;li&gt;
&lt;li&gt;B5: 176mm by 250mm (6.9“ by 9.8“)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Paper_size#Overview_of_ISO_paper_sizes&quot;&gt;see the full list on wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usa-common-photo-sizes&quot;&gt;USA common photo sizes&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;4“ by 4“&lt;&#x2F;li&gt;
&lt;li&gt;4“ by 6“ (common post card size also)&lt;&#x2F;li&gt;
&lt;li&gt;5“ by 7“&lt;&#x2F;li&gt;
&lt;li&gt;6“ by 8“&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;other-paper-things&quot;&gt;other paper things&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;USA letter: 216mm by 279mm (8.5“ by 11“)&lt;&#x2F;li&gt;
&lt;li&gt;credit cards: 85.60mm by 53.98mm (3“3&#x2F;8 by 2.125“)&lt;&#x2F;li&gt;
&lt;li&gt;USD dollar: 156mm by 66.3mm (6.14“ by 2.61“)&lt;&#x2F;li&gt;
&lt;li&gt;post it notes: common post it is 3“ by 3“ but some of the special ones like the transparent post-its are 2“7&#x2F;8&lt;&#x2F;li&gt;
&lt;li&gt;receipt paper: 2“1&#x2F;4 (57.15mm) or 3“1&#x2F;8 (79.375mm) wide in the USA&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;other&quot;&gt;Other&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;soda cans
&lt;ul&gt;
&lt;li&gt;12.2cm (4.8“) tall&lt;&#x2F;li&gt;
&lt;li&gt;6.62cm (2.6“) diameter&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;smartphones: see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dimensions.com&#x2F;classifications&#x2F;digital&quot;&gt;this list from dimensions.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- - pill bottles
- pill capsules --&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>looking for an open source inventory management system</title>
        <published>2026-04-08T00:00:00+00:00</published>
        <updated>2026-04-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/inventory-management/"/>
        <id>https://skylosblog.com/posts/inventory-management/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/inventory-management/">&lt;h1 id=&quot;the-problem&quot;&gt;The problem:&lt;&#x2F;h1&gt;
&lt;p&gt;I am moving and need a way to track all my stuff. I also want to help a friend with a garage shop track her tools etc. And want to assemble event kits and track whats in them if I need to.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;candidates&quot;&gt;candidates&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;inventree: simple python based physical asset focussed&lt;&#x2F;li&gt;
&lt;li&gt;shelf.nu: cloud service first physical asset focussed&lt;&#x2F;li&gt;
&lt;li&gt;snipeit: IT focussed&lt;&#x2F;li&gt;
&lt;li&gt;GLPI: IT focussed&lt;&#x2F;li&gt;
&lt;li&gt;ralph: IT focussed&lt;&#x2F;li&gt;
&lt;li&gt;frappe erp: accounting focussed&lt;&#x2F;li&gt;
&lt;li&gt;partkeepr: electronic component focussed&lt;&#x2F;li&gt;
&lt;li&gt;konbase: event equipment focussed&lt;&#x2F;li&gt;
&lt;li&gt;koillection: home library&lt;&#x2F;li&gt;
&lt;li&gt;libre booking: focussed on providing the ability to schedule resource allocation&lt;&#x2F;li&gt;
&lt;li&gt;Homebox asset management: home scale physical items&lt;&#x2F;li&gt;
&lt;li&gt;collective access asset management: musuem physical artifact inventory&lt;&#x2F;li&gt;
&lt;li&gt;koha library software: open source library software&lt;&#x2F;li&gt;
&lt;li&gt;lendengine: lending library software explicitly for tool libraries etc in addition to books&lt;&#x2F;li&gt;
&lt;li&gt;evergreen: open source lending library software&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;inventree&quot;&gt;inventree:&lt;&#x2F;h1&gt;
&lt;p&gt;Inventree is a smaller inventory management project written in Python. It’s relatively simple but has some nice features. Unfortunately, my os isnt supported by their install script and I kept having docker issues that got in the way of testing out the application.&lt;&#x2F;p&gt;
&lt;p&gt;uses postgres as a database.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;konbase&quot;&gt;konbase:&lt;&#x2F;h1&gt;
&lt;p&gt;seems like a very small project, without a lot of features. But it seems like its nicely scoped to running conferences and tracking inventory during events, which is pretty cool. Konbase is very close to my desired use case, but the small size of the project and its tech stack make me apprehensive.&lt;&#x2F;p&gt;
&lt;p&gt;uses fucking supabase and react.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;shelf-nu&quot;&gt;shelf.nu:&lt;&#x2F;h1&gt;
&lt;p&gt;very developed, focussed on providing a platform over providing self-hosting, although self hosting is still possible and there are instructions. The out of the box experience as a free user on their platform is pleasant, but their barcode system is locked behind a paywall (it seems like only part of it is, it will still produce qr codes, just some of the fine toothed tools arent available). It also has team management, and equipment request features, and auditing tools locked behind a paywall.&lt;&#x2F;p&gt;
&lt;p&gt;Assets are filled out with a series of set fields (you can also add custom fields on top of that) and then assets can be bundled into kits. Assets can also be grouped by location, and each location can have a parent location. Assets can also be assigned custody to a specific individual.&lt;&#x2F;p&gt;
&lt;p&gt;The way to configure certain aspects of assets and kits is by entering their detail page, which is different from editing them, and clicking some extra buttons if you’re the admin. That flow isnt intuitive but I did figure it out, so not that bad I guess. Assets in a kit will inherit things like the kit’s location.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I like it. I wish the flow for adding items was faster in order to deal with transient inventory&#x2F;make bulk onboarding easier, but it looks like there is a csv import feature.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;snipeit&quot;&gt;snipeIT&lt;&#x2F;h1&gt;
&lt;p&gt;Seems beloved by its users, but is focussed on IT assets specifically, which could be made to work to my ends, but is probably not worth the hassle.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;frappe-erpnext&quot;&gt;frappe ERPnext&lt;&#x2F;h1&gt;
&lt;p&gt;Frappe ERPnext is actually a software suit aiming to provide full erp support. In general the Frappe project seems cool in its goal to provide open source business support software and they seem to have products meant to meet a lot of different needs which is exciting to me.&lt;&#x2F;p&gt;
&lt;p&gt;Like shelf.nu, they provide a cloud hosting service for their erp software, except they only have a free trial rather than a free service tier. Like shelf.nu self hosting is also an option. You sign up for a frappecloud account and it configures a site for you.&lt;&#x2F;p&gt;
&lt;p&gt;The idea of an asset here isn’t specific to IT but is generalized to the point it may be difficult for a specific application, and seems to be more focussed on tracking the financial aspect of holding onto an asset, with ways to set how to calculate depreciation in value.&lt;&#x2F;p&gt;
&lt;p&gt;They do let you bundle assets together into &lt;em&gt;composite assets&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;my conclusion as of this moment is that erpnext is powerful software focussed on the financial administration aspect of asset management that has kind of a steep learning curve due to the amount of fine grain control available to the user. Unfortunately, a lot of that functionality is irrelevant for my needs. But could be good for someone running a manufacturing business or a whole office.&lt;&#x2F;p&gt;
&lt;p&gt;It does have a bulk import functionality which is nice.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;glpi&quot;&gt;GLPI&lt;&#x2F;h1&gt;
&lt;p&gt;GlPI is another IT focussed asset management system. Has no free tier on their platform, but it is open source. But since it’s focussed on IT I’m deprioritizing it for my use case.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ralph&quot;&gt;ralph&lt;&#x2F;h1&gt;
&lt;p&gt;THEY HAVE A DEB PACKAGE FOR UBUNTU 18.04 OR NEWER!!!! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ralph-ng.readthedocs.io&#x2F;en&#x2F;stable&#x2F;installation&#x2F;installation&#x2F;&quot;&gt;install guide&lt;&#x2F;a&gt; and it runs as a systemd service!!! very cool!!&lt;&#x2F;p&gt;
&lt;p&gt;It is IT focussed so going through the effort of making it run on my machine just to see if I can hammer it into something that works for my needs isnt enticing. Especially since even though it’s a deb package, it’s still an approximately ten step process involving configuring tools I’m not the most familiar with.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;partkeepr&quot;&gt;partkeepr&lt;&#x2F;h1&gt;
&lt;p&gt;designed specifically for tracking electronic components, similar to the IT focussed ones, that’s cool but not really what I’m looking for.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;librebooking&quot;&gt;Librebooking&lt;&#x2F;h1&gt;
&lt;p&gt;The idea seems cool, I like its dedication to open source. It seems a little rough around the edges and focussed more on the being able to reserve time part of things than the item tracking part of things than I’d like.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;collective-access&quot;&gt;Collective access&lt;&#x2F;h1&gt;
&lt;p&gt;The idea behind this one seems cool, I tried to help someone set it up about a year ago and spent hours resolving dependencies until we got it to give us a log-in at which point we fell to a CSRF token verification error that we couldn’t resolve and elected to use spreadsheets instead.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;highlights&quot;&gt;highlights&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;shelf-nu-1&quot;&gt;shelf.nu&lt;&#x2F;h2&gt;
&lt;p&gt;It has a free tier cloud service that lets you dive right in and has decent functionality out the gate that works well for physical assets.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;frappe&quot;&gt;frappe&lt;&#x2F;h2&gt;
&lt;p&gt;The fact that the asset management is part of a larger erp suite means that it has the potential to be an incredibly powerful tool if you centralize all the information in one spot. But there’s no free tier and the learning curve is kind of intense for a use case as small as mine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;konbase-1&quot;&gt;konbase&lt;&#x2F;h2&gt;
&lt;p&gt;really excited by the project scope, just don’t want to use its tech stack.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ralph-1&quot;&gt;ralph&lt;&#x2F;h2&gt;
&lt;p&gt;really excited by the fact it has a deb package and systemd service, unfortunately its scope doesnt seem very aligned with mine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thoughts-and-conclusions&quot;&gt;thoughts and conclusions&lt;&#x2F;h1&gt;
&lt;p&gt;I think for my specific needs a lot of these software solutions may actually be more complexity than their worth. The systems that are developed enough to have a cloud service seem to be targeting cases that are either more complex or just different enough that translating to their system could be a hassle, and those that seem simple enough have an installation process that eats time partially due to complexity of the procedure, and partially due to needing to troubleshoot it in order to make it work on my machine.&lt;&#x2F;p&gt;
&lt;p&gt;It seems like for something small scale, the idea of tracking inventory and a couple spreadsheets might be enough, even if, as a software enthusiast, the desire for better automations and data management is always there.&lt;&#x2F;p&gt;
&lt;p&gt;I really wanted inventree to be the one but I sunk so many hours into solving the docker issue and made very little headway.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;further-reading&quot;&gt;Further Reading&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;linoxide.com&#x2F;best-open-source-library-management-software&#x2F;&quot;&gt;https:&#x2F;&#x2F;linoxide.com&#x2F;best-open-source-library-management-software&#x2F;&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;community.aam-us.org&#x2F;discussion&#x2F;recommendations-for-a-home-library-system-or-app&quot;&gt;https:&#x2F;&#x2F;community.aam-us.org&#x2F;discussion&#x2F;recommendations-for-a-home-library-system-or-app&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Recreating Orbits in APL</title>
        <published>2026-03-20T00:00:00+00:00</published>
        <updated>2026-03-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/orbits-apl-and-math/"/>
        <id>https://skylosblog.com/posts/orbits-apl-and-math/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/orbits-apl-and-math/">&lt;blockquote&gt;
&lt;p&gt;This post contains &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aplmooc.fi&#x2F;course&#x2F;ch0&#x2F;part1&#x2F;&quot;&gt;APL&lt;&#x2F;a&gt; symbols! they may not render correctly on your computer!
APL is a very interesting programming language! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aplmooc.fi&#x2F;course&#x2F;ch0&#x2F;part1&#x2F;&quot;&gt;learn APL here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I recently got into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jaimes.games&#x2F;orbits&#x2F;&quot;&gt;orbits&lt;&#x2F;a&gt;, a game where we are given a 6 by 6 square grid of cells. Some of the cells are empty, and we can place between 1 and 3 dots in these empty cells. Some of the cells have a number that is the sum of dots in the 8 cells adjacent to it. Using these sums we have to deduce the correct distribution of dots. whenever I see a game involving a square grid, especially one which such clear and tight constraints, my mind immediately wonders about representing it in APL, and then goes on to wonder about the specific mathematical properties of the games and algorithmic solving techniques etc.&lt;&#x2F;p&gt;
&lt;p&gt;The purpose of this post is to log all the wonderings and APL snippets so that I can continue having fun with them later.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;generating-board&quot;&gt;Generating board&lt;&#x2F;h1&gt;
&lt;p&gt;I sat down a few weeks ago and wrote a first pass at recreating the board generation in APL. I have since realized this generator isn’t sufficiently constrained to produce unambiguous boards (we consider a board with more than one possible solution ambiguous). I hadn’t taken the time to determine if ambiguous boards were possible or not. Ambiguous boards are possible if there is an empty cell with no adjacent non-empty cells, or we can create one along the lines of a 3x3 grid with a 9-count in the middle.&lt;&#x2F;p&gt;
&lt;p&gt;I hypothesize that a more general case of the 3x3 grid is a grid where every non-empty cell has a value of n+1 where n is the number of adjacent empty cells, that way the extra 1 has 8 possible placements. There is probably a more general and weaker example of ambiguous boards that I can get to with more than the 20s of thought I’m giving right now.&lt;&#x2F;p&gt;
&lt;p&gt;Here is that original board generator: &lt;code&gt;{(0=⍵)×({(+&#x2F;,⍵)}⌺3 3)⍵}{?⍵ ⍵⍴ 3} n&lt;&#x2F;code&gt; it creates an nxn grid then rolls a 4 sided die to randomize each cell with 0-3 dots, each cell with 0 dots is then replaced with a count and all the dotted cells are zeroed out to create the game board. This board code can potentially cluster too many dotted cells together and create an ambiguous board.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;solving-methods&quot;&gt;solving methods&lt;&#x2F;h1&gt;
&lt;p&gt;While playing last night I realized that we can turn any board into linear algebra. say we have a board like&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3 0 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 7 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 3 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where 0 represents an empty cell. Then, we can represent it as a system of linear equations:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3 a b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c 7 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 3 d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a + c = 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a + b + c + d = 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a + b + d = 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c = 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c + d = 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c = 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a + c - c = 3-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c + d - c = 3-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;d = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a + b + d - a - c - d = 7 - 1 - 2 - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;b = 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which we can then represent as an augmented matrix:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a b c d = &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 0 1 0 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 1 1 1 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 1 0 1 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 0 1 0 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 0 1 1 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then convert it to row echelon form to get our answer for each empty cell&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 0 0 0 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 1 0 0 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 0 0 0 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 0 1 0 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 0 0 1 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where the programming comes in is converting our board matrix to the augmented matrix, solving that matrix, and then back filling the board with the correct answer.&lt;&#x2F;p&gt;
&lt;p&gt;I have trouble with APL sometimes, as much as I admire it, translating something I think of very procedurally to a series of filters can be a real challenge for me. So I haven’t figured it out yet, but a good friend wrote an APL program to do it and made some recommendations which I will study and come back to this with.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;further-extensions&quot;&gt;further extensions&lt;&#x2F;h1&gt;
&lt;p&gt;I think it would be really interesting to try to generalize this game to any maximum or minimum dot quantity, and any number of adjacent cells, or any shape of graph, again I say this without putting more than a second’s thought toward it. I suspect it would end up a graph coloring problem, but, proving that it is, in fact exactly as hard as a graph coloring, would still be a fun exercise that I haven’t had to do since college.&lt;&#x2F;p&gt;
&lt;p&gt;I also thought about some sort of iterative flooding approach that could repeat until a stable state. I think it could be interesting to program and I’d learn something from it. Thinking about it, it might be interesting to use a transport algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;There are other grid based games I have wanted to do this for in the past so this would be good practice for that too.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>notes from the mountain side</title>
        <published>2026-02-10T00:00:00+00:00</published>
        <updated>2026-02-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/note-from-the-mountain/"/>
        <id>https://skylosblog.com/posts/note-from-the-mountain/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/note-from-the-mountain/">&lt;p&gt;The constant striving to truly &lt;em&gt;LIVE&lt;&#x2F;em&gt; and milk from life every last dram of experience takes us scrambling up the mountains of agony and suffering. Some of this pain we choose, some of it is thrust upon us; no matter how suffering comes, our endurance is our show of strength, of life. It is our only game to play. The game of life is not without risk of injury. Perhaps, to make a show of willing ourself past these injuries, and drag ourselves up the mountain anyway, is where true admiration and sense-of-life is. But no-one grows up from being beaten to death in the crib, and even Nietzsche says that you must be gentle with those who have not hardened themselves.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most intelligent men, like the strongest, find their happiness where others would find only disaster: in the labyrinth, in being hard with themselves and with others, in effort; their delight is in self-mastery; in them asceticism becomes second nature, a necessity, an instinct. They regard a difficult task as a privilege; it is to them a recreation to play with burdens that would crush all others…
When the exceptional man handles the mediocre man with more delicate fingers than he applies to himself or to his equals, this is not merely kindness of heart—it is simply his duty….&lt;&#x2F;p&gt;
&lt;p&gt;Nietzsche, The Antichrist&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And what about transformation and growth? Harry Haller starts his life as a suicide and a steppenwolf and learns to be an immortal – a man who lives through the thousand slings and arrows of outrageous fortune and laughs. Nietzsche says you must become the camel, the lion, then, the child (I accept it, I refuse it, I choose it). A camel able to bear anything suffers grievous harm whipped by the winds, frozen by the cold, savoring and struggling until exposure takes it, and as it goes it may rage, but it does not mourn itself. A lion, however, says no, casts off chains, bites the hand that whips it, and is no less mighty for it. A lion is able to treat the source of its suffering, but it is not shameful for it to do so, just as it is not shameful for the camel to bear it in peace. And then, the child, who laughs, disregards, and creates its own rules to live by. It does not simply endure the value systems of others or merely refuse to live by them, but creates its own.&lt;&#x2F;p&gt;
&lt;p&gt;There is no shame in protecting yourself from injury to make the climb easier. Part of dancing with boulders is to make them light. That lightness is only partially about strength. Technique, load, and capacity all play a part. In order to “play with burdens that would crush all other men” you must make the boulder unable to crush you. To make the mountain top recreational it cannot kill you on the ascent, even if death on the ascent may have its appeal.&lt;&#x2F;p&gt;
&lt;p&gt;The thing that we seek is not in the “stuff” of what we do. It is not in the damage that we take-on in our pursuits (though, scars and traumas can all become badges of our endurance). What we seek is in our lucid experience. If we accomplish the climb up the mountain but pushed ourselves too hard and retreated into dissociation, we may have endured, but the experience is lost. We were not all there, and we would have been better off taking the easy way and fully inhabiting the experience. The option to take the easy way is the gentleness we all need on the way to becoming who we are. We must never lose sight of the revolt against our own miserable unmaking. We must do our utmost to preserve our lucidity under conditions of absolute reality. That is true endurance.&lt;&#x2F;p&gt;
&lt;p&gt;Ultimately what draws us to scrabbling up the mountain side, cutting our hands, bruising our shins as we – in defiance of our own survival – fling ourselves up slopes of scree, is the unease we find in being comfortable.  Without opposition, without something to press into, how can we feel ourselves? how can we know that “we” are real. (depending on who you ask the answer is that “we” are not real.)&lt;&#x2F;p&gt;
&lt;p&gt;Too many peaceful days and we start to struggle against peace. We nearly always know what is most optimal, most advantageous, most healthy, most proper, and we will not do it. Because obeying simple economics of advantage digusts us. A good life is a wretched hell of boredom that obliterates the thinking mind. And so, we make the bad decision, fuck up our own lives, precisely to know that we can. We prove that we are not bound by what is “good”, “polite”, “civilized”, or “prosperous”, only by our own propensity toward emotion, toward &lt;em&gt;feeling&lt;&#x2F;em&gt;. (see Dostoyevsky’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ia800705.us.archive.org&#x2F;7&#x2F;items&#x2F;nbooks&#x2F;Notes-from-the-Underground.pdf&quot;&gt;&lt;em&gt;Notes from Underground&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;Each of us in our own way finds an acceptable dose of intensity to keep our embers warm. We go out, find something that hurts and say “finally! this is something real!” and if we are not careful we let it draw us in until we again lose sensitivity to ourselves, so consumed by the texture of the boulder as it grinds us into the dirt we forget the roughness of our own calluses, forget the clenching of muscle, and the straining of sinew. This too is a kind of bored hell.&lt;&#x2F;p&gt;
&lt;p&gt;I think if Sisyphus is happy when the boulder rolls down the hill and he must walk down after it alone, it is because in that walk alone, he knows himself. Comfort is only comfort if we can hold everything in focus.&lt;&#x2F;p&gt;
&lt;!-- I started writing this in a haze of burning out and despair. Work was not going well, I felt busy and overwhelmed and unable to do anything about it. I was trying to convince myself it was ok to pull back and protect myself rather than be flagellated. It&#x27;s months later now. --&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>writing code to work with your meshtastic node</title>
        <published>2025-09-04T00:00:00+00:00</published>
        <updated>2025-09-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/meshtastic-client-code/"/>
        <id>https://skylosblog.com/posts/meshtastic-client-code/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/meshtastic-client-code/">&lt;p&gt;This is a post about writing code to run on a computer or server that then connects to a meshtastic node.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h1&gt;
&lt;p&gt;meshtastic supports sending data as either a protobuf (protocol buffer, a universal data standard set by google (it’s basically just a struct)) or as a raw binary. These packets can be directed to certain endpoints. On connection to the node we have a certain expected packet exchange before we enter normal operations where we send messages and listen to messages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;http-endpoints&quot;&gt;HTTP Endpoints&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;endpoint&lt;&#x2F;th&gt;&lt;th&gt;permissions&lt;&#x2F;th&gt;&lt;th&gt;purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;fromradio&lt;&#x2F;td&gt;&lt;td&gt;read&lt;&#x2F;td&gt;&lt;td&gt;this is the endpoint for data travelling from the node to the client. it is a FIFO queue.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;toradio&lt;&#x2F;td&gt;&lt;td&gt;write&lt;&#x2F;td&gt;&lt;td&gt;this is the endpoint for data travelling from the client to the node&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;fromnum&lt;&#x2F;td&gt;&lt;td&gt;read, notify, write&lt;&#x2F;td&gt;&lt;td&gt;this is the number of the message currently waiting in the fromradio endpoint. note that this number should only increase, unless the node is rebooted.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;log&lt;&#x2F;td&gt;&lt;td&gt;notify&lt;&#x2F;td&gt;&lt;td&gt;this is where debug messages go&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;pubsub&quot;&gt;pubsub&lt;&#x2F;h2&gt;
&lt;p&gt;The python library uses a message bus to handle all meshtastic events. We then create a callback and subscribe it to the relevant “topic”. Each topic is a string with dot notation to indicate levels of specificity, for example: &lt;code&gt;&quot;meshtastic.receive.text&quot;&lt;&#x2F;code&gt; is the topic for only text packets, &lt;code&gt;&quot;meshtastic.receive&quot;&lt;&#x2F;code&gt; is the topic for all packets, &lt;code&gt;&quot;meshtastic&quot;&lt;&#x2F;code&gt; is the topic for all events.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; pubsub&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; meshtastic&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;serial_interface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; meshtastic&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;serial_interface&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;SerialInterface&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; we need to establish a connection in order to have the bus receive messages&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; callback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;packet&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;packet&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;subscribe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;callback&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;meshtastic.receive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;callback called on any packet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The packet takes the form of a dictionary, but the fields of that dictionary DON’T APPEAR TO BE DOCUMENTED ANYWHERE since technically anything could be using meshtastic as a transport layer the responsibility to document anything is passed on. (look at the portnums for more details, essentially portnum indicates what protocol the packet is implementing)&lt;&#x2F;p&gt;
&lt;h1 id=&quot;example-packets&quot;&gt;example packets&lt;&#x2F;h1&gt;
&lt;p&gt;below are two example packet dictionaries so you can see the sort of fields they have. Notice that only the &lt;code&gt;&#x27;decoded&#x27;&lt;&#x2F;code&gt; field changes. Also notice that &lt;code&gt;&#x27;portnum&#x27;&lt;&#x2F;code&gt; tells you what kind of data it is (Although the actual list of fields for each portnum isn’t necessarily listed anywhere). See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;buf.build&#x2F;meshtastic&#x2F;protobufs&#x2F;docs&#x2F;main:meshtastic#meshtastic.PortNum&quot;&gt;here&lt;&#x2F;a&gt; for a full list.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TELEMETRY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;from&amp;#39;: &amp;lt;id&amp;gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;to&amp;#39;: &amp;lt;id&amp;gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;decoded&amp;#39;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;portnum&amp;#39;: &amp;#39;TELEMETRY_APP&amp;#39;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;payload&amp;#39;: b&amp;#39;\r*\x02\x11\x00\x12\x13\x08e\x15L7\xc9@\x1d\xb8\x1ee?%\x08et&amp;lt;(B&amp;#39;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;bitfield&amp;#39;: 1,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;telemetry&amp;#39;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;#39;time&amp;#39;: 1114666,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;#39;deviceMetrics&amp;#39;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;#39;batteryLevel&amp;#39;: 101,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;#39;voltage&amp;#39;: 6.288,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;#39;channelUtilization&amp;#39;: 0.895,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;#39;airUtilTx&amp;#39;: 0.014916666,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;#39;uptimeSeconds&amp;#39;: 66&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;#39;raw&amp;#39;: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                time: 1114666&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                device_metrics {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    battery_level: 101,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    voltage: 6.288000106811523,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    channel_utilization: 0.8949999809265137,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    air_util_tx: 0.014916665852069855,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    uptime_seconds: 66&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;id&amp;#39;: &amp;lt;id&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;hopLimit&amp;#39;: 5, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;priority&amp;#39;: &amp;#39;BACKGROUND&amp;#39;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;hopStart&amp;#39;: 5,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;relayNode&amp;#39;: 224,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;raw&amp;#39;: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        from: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        decoded {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            portnum: TELEMETRY_APP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            payload: &amp;quot;\r*\002\021\000\022\023\010e\025L7\311@\035\270\036e?%\010et&amp;lt;(B&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            bitfield: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hop_limit: 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        priority: BACKGROUND&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hop_start: 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        relay_node: 224&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;fromId&amp;#39;: &amp;#39;&amp;lt;id&amp;gt;&amp;#39;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;toId&amp;#39;: &amp;#39;^all&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TEXT MESSAGE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;from&amp;#39;: &amp;lt;id&amp;gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;to&amp;#39;: &amp;lt;id&amp;gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;decoded&amp;#39;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;portnum&amp;#39;: &amp;#39;TEXT_MESSAGE_APP&amp;#39;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;payload&amp;#39;: b&amp;#39;hi&amp;#39;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;bitfield&amp;#39;: 0, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;#39;text&amp;#39;: &amp;#39;hi&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;id&amp;#39;: 944823075, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;rxTime&amp;#39;: 1758739701, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;rxSnr&amp;#39;: 6.5, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;hopLimit&amp;#39;: 7, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;wantAck&amp;#39;: True, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;rxRssi&amp;#39;: -51, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;hopStart&amp;#39;: 7, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;publicKey&amp;#39;: &amp;#39;FyvMvBZ1TRRWUNsZkDPX7JTW4ZuEymOMxiTRSrsu9Bg=&amp;#39;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;pkiEncrypted&amp;#39;: True, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;raw&amp;#39;: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        from: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        to: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        decoded {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            portnum: TEXT_MESSAGE_APP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            payload: &amp;quot;hi&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            bitfield: 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id: &amp;lt;id&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rx_time: 1758739701&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rx_snr: 6.5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hop_limit: 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        want_ack: true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rx_rssi: -51&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        hop_start: 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        public_key: &amp;quot;\027+\314\274\026uM\024VP\333\031\2203\327\354\224\326\341\233\204\312c\214\306$\321J\273.\364\030&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pki_encrypted: true, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;fromId&amp;#39;: &amp;#39;&amp;lt;id&amp;gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;toId&amp;#39;: &amp;#39;&amp;lt;id&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;links&quot;&gt;links&lt;&#x2F;h1&gt;
&lt;p&gt;since I found the documentation pretty frustrating to navigate so here’s a list of documentation pages that have been actually useful.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;meshtastic.org&#x2F;docs&#x2F;configuration&#x2F;radio&#x2F;device&#x2F;&quot;&gt;https:&#x2F;&#x2F;meshtastic.org&#x2F;docs&#x2F;configuration&#x2F;radio&#x2F;device&#x2F;&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;meshtastic&#x2F;python&#x2F;blob&#x2F;master&#x2F;TODO.md&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;meshtastic&#x2F;python&#x2F;blob&#x2F;master&#x2F;TODO.md&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;python.meshtastic.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;python.meshtastic.org&#x2F;&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;buf.build&#x2F;meshtastic&#x2F;protobufs&#x2F;docs&#x2F;main:meshtastic#meshtastic.PortNum&quot;&gt;https:&#x2F;&#x2F;buf.build&#x2F;meshtastic&#x2F;protobufs&#x2F;docs&#x2F;main:meshtastic#meshtastic.PortNum&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>how to host your stuff</title>
        <published>2025-09-02T00:00:00+00:00</published>
        <updated>2025-09-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/hosting-your-stuff/"/>
        <id>https://skylosblog.com/posts/hosting-your-stuff/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/hosting-your-stuff/">&lt;h1 id=&quot;concepts&quot;&gt;concepts&lt;&#x2F;h1&gt;
&lt;p&gt;what is http? what is an IP? what are ports?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IP address: this is a number that identifies a specific device on the network. ISPS only see the router on the internet. The router manages a local network where each device has a local IP address to identify it.&lt;&#x2F;li&gt;
&lt;li&gt;public IP address: this is the IP address used by the ISP to identify a home network. Generally the ISP sets these to be dynamic to avoid hackers or hobbyists exploiting them for nefarious or mundane purposes.&lt;&#x2F;li&gt;
&lt;li&gt;private IP address: these addresses are only for the local network&lt;&#x2F;li&gt;
&lt;li&gt;DHCP: dynamic host configuration protocol. This is when an IP address is assigned randomly each time a computer joins the network&lt;&#x2F;li&gt;
&lt;li&gt;sticky DHCP: refers to DHCP configurations that use heuristics to try to maximize the chances of the same device getting the same address every time it joins the network.&lt;&#x2F;li&gt;
&lt;li&gt;static IP address: this is an address assigned to a specific device that does not change.&lt;&#x2F;li&gt;
&lt;li&gt;NAT: network address translation, this is a layer of indirectness between the local network and another network (usually the internet) that allows traffic to flow correctly from one network to the other. This is what a router provides. It has an IP address on the internet, and translates packets addressed to it to local ip addresses in order to send them to the correct computer.&lt;&#x2F;li&gt;
&lt;li&gt;Firewall: this is a filter layer between the local network and the internet (or other network) that uses various rules and heuristics to identify packets that should not be passed on to the local network.&lt;&#x2F;li&gt;
&lt;li&gt;127.0.0.0: the 127 block of IP addresses is the “loop back” block. These addresses identify resources that live on the same machine as the one accessing them.&lt;&#x2F;li&gt;
&lt;li&gt;192.168.0.0: this is the most commonly used private block of IP addresses. These are addresses not connected to the internet but accessible locally.&lt;&#x2F;li&gt;
&lt;li&gt;reverse DNS lookup: Normally a DNS lookup involves finding the IP address of the server associated with a certain domain name. A reverse lookup involves looking up what domain is associated with a certain IP.&lt;&#x2F;li&gt;
&lt;li&gt;MAC address: Media Access Control address. It’s a unique identifier for each machine that is set during manufacture that includes a number identifying the manufacturer. These are used for addressing data packets from your router to your computer and vice versa.&lt;&#x2F;li&gt;
&lt;li&gt;port: once a packet makes it to a specific computer its data needs to get to the right application. Each port is an address for the computer’s software, many ports have specific application, for example 80 is reserved for http.&lt;&#x2F;li&gt;
&lt;li&gt;port forwarding: this lets us instruct our router to send all incoming traffic bound to a specific port directly to another computer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;security&quot;&gt;security&lt;&#x2F;h1&gt;
&lt;p&gt;Remove all default user accounts and passwords. Make sure that all file permissions are set as restrictively as possible. Don’t expose to the public internet unless you need to. When you register a domain name you are required to provide contact information. This information is usually available for WHOIS lookup but many registrars provide a privacy protection option you can pay for. As for port forwarding, there’s no special concern about port forwarding, the only concern is if the software listening to the forwarded port is itself able to grant someone controlling access to itself.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;hosting&quot;&gt;hosting&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;self-hosting-on-the-internet&quot;&gt;self hosting on the internet&lt;&#x2F;h2&gt;
&lt;p&gt;To host online we need to set up port forwarding on our home router to redirect to our server, allowing requests to our router from the internet to reach our server. The server handles everything else.&lt;&#x2F;p&gt;
&lt;p&gt;you can also use tailscale funnel if it’s something small.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosting-with-an-external-service&quot;&gt;hosting with an external service&lt;&#x2F;h2&gt;
&lt;p&gt;each service is unique but if its a server with a specific purpose (like how neocities only hosts static sites) then it will probably have a unique interface it will explain to you. If its a more general purpose server, the common approach is to ssh into it and port in a docker image for your service.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;docker&quot;&gt;docker&lt;&#x2F;h1&gt;
&lt;p&gt;docker is a way of containerizing your application with its own virtual environment and dependencies making it more portable. It makes use of docker image files to describe that containerized virtual environment. Docker hub is an open repository of docker images that users can push to and pull from in order to transfer image between computers. Docker engine is the server software that runs all these virtual environments for you.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>MAKE YOUR OWN WEBSITE!</title>
        <published>2025-08-22T00:00:00+00:00</published>
        <updated>2025-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/make-a-website/"/>
        <id>https://skylosblog.com/posts/make-a-website/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/make-a-website/">&lt;h1 id=&quot;why-you-should-make-your-own-website&quot;&gt;Why you should make your own website.&lt;&#x2F;h1&gt;
&lt;p&gt;Put simply it’s &lt;em&gt;your&lt;&#x2F;em&gt; website. You own it, you make the decisions, no corporate higher up can rug pull you on it. If whoever hosts the website doesn’t like you, you can move it or even host it yourself. You’re expression is now invincible.&lt;&#x2F;p&gt;
&lt;p&gt;It’s also cute, and if you’ve never done anything like it before you’ll learn something.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-the-hell-does-all-this-work-anyway&quot;&gt;How the hell does all this work anyway?&lt;&#x2F;h1&gt;
&lt;p&gt;If this is your first time doing anything like this you might not really get how websites work and find everything else I’m about to say intimidating. This section is a concept map which hopefully makes how websites work and the vocabulary around them more legible.&lt;&#x2F;p&gt;
&lt;p&gt;All webpages are simply a combination of three types of files: HTML files, CSS files, and JavaScript files. Each is responsible for a different part of the web page’s behavior. The HTML file describes what we call the &lt;strong&gt;content&lt;&#x2F;strong&gt; of a website (all of its text, images, and other media). The CSS file describes the &lt;strong&gt;style&lt;&#x2F;strong&gt; of a website, it’s responsible for all of the visual design aspects of a website. JavaScript files contain code that allows someone visiting the site (we’ll call them the &lt;strong&gt;user&lt;&#x2F;strong&gt; from now on) to interact with the page, examples of interactivity are little animations happening when the user hits a certain key or clicks a button, sometimes people will use JavaScript to make whole games in the browser. Most web calculators use JavaScript to run all the calculations for you.&lt;&#x2F;p&gt;
&lt;p&gt;If you have an HTML file on your computer, you can open it on your computer in a web browser and it will look and feel just like a website on the internet (some of the links might be broken though). When we visit a website, this is exactly how it works. The internet is really just a big list of files and any time we’re “on a website” we’re really just downloading and looking at these HTML files. But in order for our computer to be able to download the files, they need to be stored &lt;em&gt;somewhere&lt;&#x2F;em&gt;; that somewhere is called a server. It’s just another computer that has all of a website’s files on it and when we visit a URL we’re connecting to that computer and downloading the website’s files (this is why servers are called that: they &lt;em&gt;serve&lt;&#x2F;em&gt; you the files). Whenever I refer to &lt;strong&gt;hosting&lt;&#x2F;strong&gt; in a web context I’m talking about who or whatever is holding the website files for us.&lt;&#x2F;p&gt;
&lt;p&gt;That’s probably the minimal context needed to proceed to the tutorial, but I’m about to get into the weeds because I think it’s cool and because I found it useful when I was figuring out how to make my own site. You have my full permission to skip ahead to the tutorial. (Really you have full permission to skip everything, as a reader I have no control over you and you should take from any text only what you need, as efficiently as you can. Don’t bother reading stuff that will tire you out and not help you with your goal unless you think it’s fun.)&lt;&#x2F;p&gt;
&lt;p&gt;So, how does visiting a url get us to the right computer to download the right file to view a website? And how does buying a website work anyway? Well, as I hinted earlier, the internet is actually just a bunch of computers, and whenever we access anything on the internet we’re just downloading stuff from a specific computer. A URL is just a unique name that lets us look up the right computer. So whenever we visit a URL our computer reaches out to a DNS (distributed name service) which is a database of every URL and every computer that can serve files for that URL, it then tells us the IP address of a computer that has the files we need and will hopefully have the fastest connection for us. We then connect to the address that the DNS gave us and download the files. When we buy our own domain name&#x2F;url, in order to see a website when we visit that URL, we need both a computer that can serve the files for us, and to tell the DNS where that computer is, so that when people visit our domain, the DNS has a server in its database it can direct visitors to connect to. It should be noted that none of these connections I’ve talked about are live, streaming, connections. The connection exists only as long as it takes us to download the HTML and any other files we need.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;list-of-terms&quot;&gt;list of terms&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;term&lt;&#x2F;th&gt;&lt;th&gt;explanation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;HTML&lt;&#x2F;td&gt;&lt;td&gt;HTML stands for hyper text markup language. It consists of a text file annotated with tags that break the document into sections. The different tags usually have semantic information, such as denoting paragraphs and headings&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HTML tag&lt;&#x2F;td&gt;&lt;td&gt;tags are little bits of annotation in html that look like &lt;code&gt;&amp;lt;p&amp;gt;this is a paragraph!&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt; they denote page sections, have anchors for spplying styles and carry meta information such as link addresses and page titles.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CSS&lt;&#x2F;td&gt;&lt;td&gt;stands for cascading style sheet. These are documents that describe the look of any given web page, they contain information about what font to use, what color to use, and how wide different sections should be&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;!-- # A specific tutorial on setting up a blog hosted on neocities.org

Neocities itself has a basic HTML tutorial so I won&#x27;t cover that in any great detail. Instead this tutorial will be focussed on using a static site generator to create all the files for our website and then using neocities to host all those files for the world to see. 

The first post on this blog actually goes into this a little bit. --&gt;
&lt;h1 id=&quot;tutorial&quot;&gt;tutorial&lt;&#x2F;h1&gt;
&lt;p&gt;see &lt;a href=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;first&#x2F;&quot;&gt;my first post&lt;&#x2F;a&gt; for a quick explanation of how to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&quot;&gt;Zola, the static site generator,&lt;&#x2F;a&gt; to create a website.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-notes&quot;&gt;Some notes&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;If you like having the ability to edit your content from anywhere and have it backed up on the web, a solution like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;github&lt;&#x2F;a&gt; is free and enables remote syncing and back up.&lt;&#x2F;li&gt;
&lt;li&gt;If you don’t like Zola there’s lots of other static site generators out there such as Hugo and Jekyll&lt;&#x2F;li&gt;
&lt;li&gt;If you don’t like Neocities there’s plenty of other host services, especially if you’re paying for a domain anyway&lt;&#x2F;li&gt;
&lt;li&gt;You can always just handwrite all the html, I’ve done that in the past.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>how to use twilio for automated texting</title>
        <published>2025-08-21T00:00:00+00:00</published>
        <updated>2025-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/twilio/"/>
        <id>https://skylosblog.com/posts/twilio/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/twilio/">&lt;h1 id=&quot;concept-map&quot;&gt;Concept Map&lt;&#x2F;h1&gt;
&lt;p&gt;You have a &lt;strong&gt;Twilio account&lt;&#x2F;strong&gt; with which one or more phone numbers are associated. These associated numbers are the ones you can send messages from. Your account has an &lt;strong&gt;Auth token&lt;&#x2F;strong&gt; that you will use to confirm ownership of a given telephone number when making an API request to Twilio servers to send a text using one of your numbers. This account ID and token should only be used in testing. For production you need to create an &lt;strong&gt;API key&lt;&#x2F;strong&gt; to use instead. Twilio also provides a &lt;strong&gt;virtual phone&lt;&#x2F;strong&gt; that you can view in their test interface, this allows easy texting, but also avoids any permission&#x2F;licensing&#x2F;etc issues with sending automated texts for the sake of testing.&lt;&#x2F;p&gt;
&lt;p&gt;The web interface that Twilio provides is called the &lt;strong&gt;Twilio console&lt;&#x2F;strong&gt; in their documentation. It holds API information, Access to the virtual phone for testing, etc.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;important-notes&quot;&gt;Important Notes&lt;&#x2F;h1&gt;
&lt;p&gt;Before you can send messages you must verify your given toll-free number, this requires providing legal identifying information for the entity that is using the service (your company or you personally).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;basic-message-request&quot;&gt;Basic message request&lt;&#x2F;h1&gt;
&lt;p&gt;You can send a text via a simple http request containing the message, the target number, and your authorization. From their tutorial:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;curl &amp;#39;https:&#x2F;&#x2F;api.twilio.com&#x2F;2010-04-01&#x2F;Accounts&#x2F;[Account ID]&#x2F;Messages.json&amp;#39; -X POST \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--data-urlencode &amp;#39;To=+&amp;lt;NUMBER&amp;gt;&amp;#39; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--data-urlencode &amp;#39;From=+&amp;lt;NUMBER&amp;gt;&amp;#39; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--data-urlencode &amp;#39;Body=Hello, World!&amp;#39; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-u [Account ID]:[Auth Token]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;receiving-messages&quot;&gt;receiving messages&lt;&#x2F;h1&gt;
&lt;p&gt;When Twilio gets a message to your number it will make a webhook request to your applicationa. In order for Twilio to call a webhook you need to provide a webhook url to associate with your number which can be done in the number’s configuration settings in the Twilio console.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;flow-charts&quot;&gt;Flow Charts&lt;&#x2F;h1&gt;
&lt;p&gt;Twilio supports a flowchart automation system that allows you to build complex sms response systems, including making http requests to set up appointments etc.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Get Violent.</title>
        <published>2025-08-12T00:00:00+00:00</published>
        <updated>2025-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/get-violent/"/>
        <id>https://skylosblog.com/posts/get-violent/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/get-violent/">&lt;p&gt;Imagine a small child playing by the stream, maybe 3 maybe 9 years old. As she splashes around and giggles she sees a frog, or a salamander, or maybe a minnow, and delighted by all such small things and believing in friendship between herself and all creatures she goes to pick it up and coo over it and give it a sweet and affectionate hug or to rub it against her cheek and then she runs off and takes it to show her mother who will no doubt be delighted to see she’s discovered a new type of friend in the world. But when she gets to her mother and beams with pride, she opens her hands and finds them slick with red and her new friend has become slippery and limp. Delight gives way to confusion which explodes into terrible comprehension. She has just learned what harm is, she has learned by killing something alive and beautiful, she knows this and she weeps and she will mourn it for the next month and well into adulthood she will find her self back there with the smell of grass and the revelation of harm.&lt;&#x2F;p&gt;
&lt;p&gt;I think we all go through that same loss of innocence. That moment of realizing that we can hurt things we don’t want to hurt, that we have hurt things we don’t want to hurt, is traumatizing. For me, I was 9 years old at a school outing where we learned to shoot bows and as I was collecting arrows I spotted a frog in the grass behind one of the targets, an arrow had grazed its leg and split the skin like a balloon. I watched it limp til the whistle of the instructor pulled me away. When I went to the market and for the first time I realized that the animals I loved were the same ones I ate. I couldn’t look at meat for a month.&lt;&#x2F;p&gt;
&lt;p&gt;That fear never really goes away. In adulthood it makes us small, tender, over yielding, unable to stand up for ourselves for fear of harming someone else. This might look like not asserting personal boundaries, being over-helpful, taking on too much responsibility, grinding through lunch hours, throwing yourself into activism without a thought to your own preservation or if your course of action is effective for your ends. It looks like living a life set out by your parents because you can’t bear to bruise their hearts.&lt;&#x2F;p&gt;
&lt;p&gt;It also looks like a fear of intimacy. I spent the early years of adulthood terrified of physical contact, every un-negotiated touch felt as if I had committed assault, the prospect of hugging someone would make me break into a cold sweat, the simple desire to reach out and connect with another living being felt as if I was admitting to being a rapist. The truth is that all it takes to harm someone is to exist. You don’t even need to be alive. By the time the first life forms came to be they were at risk of being crushed by falling rocks, punctured by sharp debris, or asphyxiated in something they couldn’t breathe. Harm does not require intent, emotion, or even awareness, it just requires that you &lt;em&gt;are&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The answer, is to get violent.&lt;&#x2F;p&gt;
&lt;p&gt;I am afraid of the unknown. I shy away from my own life, from my own well-being because I don’t know what could happen. I imagine countless catastrophes that could befall me, all of them beyond my ability to cope. I imagine my friends terrified faces, I imagine them ashamed, scared, disgusted, angry; I imagine that I will be hated because I have fired chekhov’s gun. The violence that stained my past has born fruit and now I exist as a threat, a butcher among gentle sheep, shamefully asking them to be his friend. The only way to treat that fear is to face it. When I play Jiu Jitsu I am realizing the capacity for harm that everyone fears. I shove my knee into my friend’s neck, drive my thumb into their pressure points, grip their arm so tight it threatens to tear their ligaments and straddle my crotch into their chest. No matter the outcome of a match, I am liberated. When I lose, I’m relieved that I am not the unstoppable beast that I feared. When I win, the final curtain raises, the person I just violently ripped away control from smiles, compliments me on my effort, we shake hands and play together again. No matter what happens I am forgiven for the original sin of being corporeal.&lt;&#x2F;p&gt;
&lt;p&gt;Do that enough and I believe you learn that taking up space is ok, you learn that confrontation is ok, that touch is ok. If I can wring the blood from a stranger’s neck and be forgiven, be welcomed, then maybe I can hug my friend without being subject to a tribunal.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>postgresql on arch brief note</title>
        <published>2025-08-12T00:00:00+00:00</published>
        <updated>2025-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/postgresql-on-arch/"/>
        <id>https://skylosblog.com/posts/postgresql-on-arch/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/postgresql-on-arch/">&lt;p&gt;I decided to get some experience using postgresql this week and had some trouble getting it to start on my machine. What follows is a brief explanation of how to get it working for myself and anyone like me.&lt;&#x2F;p&gt;
&lt;p&gt;when postgresql is installed it creates a postgres user that you will use when setting up the database server. postgresql also creates multiple commands. You will be using &lt;code&gt;initdb&lt;&#x2F;code&gt;, &lt;code&gt;createuser&lt;&#x2F;code&gt; and &lt;code&gt;pg-ctl&lt;&#x2F;code&gt; you will also want to use &lt;code&gt;sudo -i -u postgres&lt;&#x2F;code&gt; or an equivalent in order ot execute commands as the postgres user.&lt;&#x2F;p&gt;
&lt;p&gt;Following a normal tutorial you will create a database in &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;postgres&#x2F;data&lt;&#x2F;code&gt; as the postgres user. The init command will then inform you that you can start the server using &lt;code&gt;pg_ctl -D &#x2F;var&#x2F;lib&#x2F;postgres&#x2F;data -l logfile start&lt;&#x2F;code&gt; (note: you will have to be in the postgres user still, since you’re normal account doesn’t own the files) once you run that command, the server will instantly quit and when you check the logs it will tell you something like &lt;code&gt;FATAL:  could not create lock file &quot;&#x2F;run&#x2F;postgresql&#x2F;.s.PGSQL.5432.lock&quot;: No such file or directory&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, when I see something like that, I’m prone to thinking that there must be some elegant solution or some flag I forgot to set that I have to go read a tutorial for. After a few hours it doesn’t seem to be the case (though I think this issue might be patched in future releases actually based on a github discussion I saw). Instead you should manually create the file and make sure it’s owned by the postgres user and group permissions are also set to postgres.&lt;&#x2F;p&gt;
&lt;p&gt;Once that’s done you can start the server and now you can create a user for your normal account (make sure it matches) so if my user is called “foo” I will run &lt;code&gt;createuser --interactive foo&lt;&#x2F;code&gt; and be sure to set it as a super user unless I want to have to escalate permissions again when creating databses etc.&lt;&#x2F;p&gt;
&lt;p&gt;I messed that up the first time and had to remove the user by doing &lt;code&gt;dropuser foo&lt;&#x2F;code&gt; and re create it with superuser permissions.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>sms and mms from the computer</title>
        <published>2025-08-05T00:00:00+00:00</published>
        <updated>2025-08-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/sms-mms-from-computer/"/>
        <id>https://skylosblog.com/posts/sms-mms-from-computer/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/sms-mms-from-computer/">&lt;h1 id=&quot;what-is-sms-mms&quot;&gt;what is sms mms?&lt;&#x2F;h1&gt;
&lt;p&gt;We tend to think of sms as simply a synonym for texting. In reality texting has been multiple protocols over the years. SMS was the early days, text only, limited to 160 characters. MMS (multimedia messaging service) added the ability to send photos, and today RCS (rich communication service) has been continually rolling out since ~2017.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;anatomy-of-messaging&quot;&gt;Anatomy of messaging:&lt;&#x2F;h1&gt;
&lt;p&gt;There is all the typical cell infrastructure used to make calls, in addition we have messaging service centers that improve the network’s ability to deliver messages by saving the data and resending it in the case that a target phone does not acknowledge receipt of the message. These service centers can have different forwarding policies and make no guarantee of transmission since texting is a “best effort” service. We also have sms&#x2F;mms&#x2F;rcs gateways that enable interoperability between communication formats&#x2F;devices for example: email to text conversion. This is also how we can send a text without a mobile handset. Each gateway has one or more SIM numbers that it can use to send messages along the network on behalf of its users. Occasionally a particular business can make a contract with a network provider to connect directly to their messaging center as a gateway rather than using an intermediary, this is really only done in the case of extreme message volumes. There is also the Home Location Registry which is a central database of every SIM and its service information, including its current service area.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gateway-options&quot;&gt;Gateway options&lt;&#x2F;h1&gt;
&lt;p&gt;There are many SMS gateway options, but not all of them are suitable for every purpose. For example: JMP offers an XMPP to SMS gateway as part of their service, but that their network contract restricts that gateway to purely personal use, no automated messages. There are also tools that allow you to connect to your phone and use it as an sms gateway. If a target number’s carrier is known, many carriers offer a free email gateway that we can use.&lt;&#x2F;p&gt;
&lt;p&gt;The options we’ll examine are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;kannel&lt;&#x2F;li&gt;
&lt;li&gt;playsms&lt;&#x2F;li&gt;
&lt;li&gt;jasmin&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The above tools let us run a server that we can connect to in order to forward messages (the gateway) but they themselves are unable to send an sms directly, they need a connections to some sort of smsc&#x2F;gsm modem. To use any of these we may need to obtain a gsm modem, it looks like we can find one online for less than $20, though we probably still need to pay for a SIM plan. Ideally I’d like to use a pre-existing phone as the smsc&#x2F;modem.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;other-tools&quot;&gt;Other tools&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;gammu&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;some-other-commercial-products-that-could-be-used&quot;&gt;Some other commercial products that could be used:&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;google messages&lt;&#x2F;li&gt;
&lt;li&gt;apple message sync&lt;&#x2F;li&gt;
&lt;li&gt;twilio&lt;&#x2F;li&gt;
&lt;li&gt;plivo&lt;&#x2F;li&gt;
&lt;li&gt;infobip&lt;&#x2F;li&gt;
&lt;li&gt;maybe kde connect&lt;&#x2F;li&gt;
&lt;li&gt;mautrix-imessage&lt;&#x2F;li&gt;
&lt;li&gt;straight up ios shortcuts has texting capabilities&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;try looking some stuff in the app store too.
twilio charges per message and is about 1 cent.&lt;&#x2F;p&gt;
&lt;!-- # Avoiding spam flagging
Maybe you can send messages staggered to avoid filters. Action network is a tool used for text-banking. 

# A-T commands --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Summary of three shorthand systems</title>
        <published>2025-03-27T00:00:00+00:00</published>
        <updated>2025-03-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/shorthand-systems/"/>
        <id>https://skylosblog.com/posts/shorthand-systems/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/shorthand-systems/">&lt;h1 id=&quot;teeline&quot;&gt;Teeline&lt;&#x2F;h1&gt;
&lt;p&gt;First, we have Teeline which is designed for easy adoption by virtue of using simplified letterforms to gain speed rather than phonetic spelling. Though it does introduce its own family of abbreviations.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;shorthand-systems&#x2F;Teeline.jpeg&quot; alt=&quot;Teeline&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gregg&quot;&gt;Gregg&lt;&#x2F;h1&gt;
&lt;p&gt;Next we have Gregg, a phonetic system. While Theoretically this allows faster transcription since one doesn’t need to retrieve exact spelling from their mind, in fact phonetic shorthand systems almost always rely on consistent phoneticization and come with whole dictionaries of transcriptions for common words. So in addition to learning a new way of writing you must learn the Gregg Accent.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;shorthand-systems&#x2F;Gregg.jpeg&quot; alt=&quot;Gregg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pitman&quot;&gt;Pitman&lt;&#x2F;h1&gt;
&lt;p&gt;This is the oldest of the three and shows its age. It is designed to be written using a pen with a flexible nib such that the writer can precisely control the thickness of their line. It uses phonetic spelling, but like gregg it’s phonetic to a specific accent, in this case one that’s a little old fashioned.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;shorthand-systems&#x2F;Pitman.jpeg&quot; alt=&quot;Pitman&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A foray into woodcut printing</title>
        <published>2025-03-01T00:00:00+00:00</published>
        <updated>2025-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/foray-into-woodcut/"/>
        <id>https://skylosblog.com/posts/foray-into-woodcut/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/foray-into-woodcut/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;nick_test_print.png&quot; alt=&quot;&quot; &#x2F;&gt;
This week, thanks to my friend’s help reorganizing my workspace I dipped my toes into woodcut block printing. I’d previously avoided print methods that involved carving because I didn’t like the equipment threshold it required, but I recently got a nice and relatively cheap carving set and have a bunch of doorskin lying around so I decided to give it a shot to make a little gift for my friend’s birthday.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-design-process&quot;&gt;The Design Process&lt;&#x2F;h1&gt;
&lt;p&gt;The project scope was to creat a business card print for a sort of indiana jones type character. I started by tracing out a business card onto a sheet of paper, marking out the margins, and then iterating on the design.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;nick_designs.png&quot; alt=&quot;design sheet featuring multiple design iterations&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I liked the idea of using a heavy western font that really dominated the space so I went with that design and drafted the letters as evenly as I could with my limited experience. I then needed to fill the interior space and experimented with a couple ideas. After some carving tests I realized I wouldn’t be able to handle the small details of fine text and stuck with a simple “ESQ.”&lt;&#x2F;p&gt;
&lt;p&gt;In order to fix alignment, I traced my winning draft onto a new piece of paper, offsetting it slightly as I went in order to bring everything into place.&lt;&#x2F;p&gt;
&lt;p&gt;I spent quite a while drafting out different takes on the little “ESQ” title. I needed it to be squat enough to not butt up against the top or bottom text while still being legible and carvable. I originally wanted to do a sans serif monoline font with an oval outline. I ended up scrapping that idea because the fine carving required between the oval and the letters seemed too risky and time consuming since I didn’t want to have to start over and didn’t want the project to stretch out more than the time I’d budgeted. From a design perspective I also wanted to lend more weight to “NICK DANGER” and putting “ESQ” in an oval meant that it became dark and detailed and pulled too much attention. It also left too much negative space on either side. I added back some slight serif to the letters because without them it didn’t seem to fit the retro style quite as well.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;esq%20tests.png&quot; alt=&quot;some esquire letter drafts&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;mor_%20esq_tests.png&quot; alt=&quot;some more esquire drafts&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I then traced out a little block for the space ESQ would take and iterated a bunch of times. I really struggled with finding a “Q” that was legible and fit in the space, ultimately I don’t think I quite succeeded, in retrospect I think extending the beginning of the tail past the left edge of the round part could have helped legibility. While the letters fit stylistically, looking at the finished prints I think they still take too much visual weight and aren’t clearly distinct enough from “NICK DANGER” I would say that it should have been smaller, except given this was my first time using these tools I was already working at the edge of my abilities without risking needing to start over. perhaps thinner line weights or making the name white on black instead could have helped.&lt;&#x2F;p&gt;
&lt;p&gt;In order to add more black around the letters I added in the border stripes above and below. I also began experimenting with different decorations to take up the negative space in the middle and around “NICK”. I used another sheet of tracing paper to overlay these designs and swap them around. Eventually I settled on some lines and interpuncts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;overlay_test.png&quot; alt=&quot;design overlay testing&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-carving-process&quot;&gt;The Carving Process&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;violet_block.png&quot; alt=&quot;a test piece showing a hypothetical business card for me&quot; &#x2F;&gt;
The above is a test piece I did in a small piece of doorskin plywood with a design drawn directly onto the surface of the wood. From here I realized that I had forgotten about mirroring the design for block printing. I also discovered exactly how difficult smaller text was to carve.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;violet_print.png&quot; alt=&quot;a test print of the test block&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While talking about the project someone with woodburning experience suggested using basswood instead, I got a small 1&#x2F;8“ piece on my way home and it carved much easier so I used that for the final version.&lt;&#x2F;p&gt;
&lt;p&gt;I painted the wood surface white, and then used a stylus to transfer the graphite from my tracing paper to the wood.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;transfer.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I used double sided tape to hold the workpiece down and started my carving by scoring around each of the letters as a guide and then wherever possible using a flat chisel up to the score line. I also made ample use of a wide U-gouge and an angle gouge for tight spaces.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve since learned that the tradition is primarily to ship carve around linework and obly use gouges for bulk removal or texturing.&lt;&#x2F;p&gt;
&lt;p&gt;The last step was to glue the basswood onto a plywood backing since on its own a thin sheet of basswood is not stable and would warp from the moisture of the printing ink.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;foray-into-woodcut&#x2F;glue_up.png&quot; alt=&quot;the finished block clamped up for gluing&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Keeping your soul alive</title>
        <published>2024-12-16T00:00:00+00:00</published>
        <updated>2024-12-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/keep-your-soul-going/"/>
        <id>https://skylosblog.com/posts/keep-your-soul-going/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/keep-your-soul-going/">&lt;p&gt;Life is hard, and you may find yourself fundamentally anxious and exhausted and broken. When this happens, untangling yourself is horrid and difficult work. No matter what, coming out of the haze will be slow.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tip-1-use-your-microwave&quot;&gt;tip #1 use your microwave&lt;&#x2F;h1&gt;
&lt;p&gt;A microwave is a beautiful tool that can cook you oatmeal, a potato, broccoli or reheated lasagna in less than 5 minutes. This will keep you alive. Sometimes it can even look really good. If you don’t eat for a while eating will, 1 spike your blood sugar, 2, make you even more hungry. It might make you feel broken, you are not, this is part of the operation of the body, try to eat more if you can.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;you-will-do-less-than-you-think-you-should-you-are-doing-way-more-than-you-think-you-are&quot;&gt;you will do less than you think you should, you are doing way more than you think you are.&lt;&#x2F;h1&gt;
&lt;p&gt;I kept a log for about two weeks of every activity I did in a day, including watching tv, even on days when I felt like I did nothing I still usually hit about 15 things with 30 on a high energy day. On a day where it feels like you can’t do anything let your body rest, you are doing lots of things you just don’t think they count.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;take-control&quot;&gt;take control&lt;&#x2F;h1&gt;
&lt;p&gt;Be loud, take up space, modify your environment, anything to prove you are real.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;build-self-trust&quot;&gt;build self trust&lt;&#x2F;h1&gt;
&lt;p&gt;This means QUIT. This means EAT. This means REWARDS. Inside you is a horribly scared little toddler mouse, it is impossibly weak, it relies on you for everything. Every time it’s hungry and you refuse to feed it because you haven’t earned the right, every time you tell yourself you’ll stop working and then keep going, every time it says “that was hard I want a lollipop now” and you don’t let it have one because you don’t deserve a lollipop, it will throw up and cry and bawl and beat against your chest. “BUT YOU PROMISED!!!! BUT I WANT TO GO HOME!!!! BUT I WANT TO GO TO BED!!!! BUT IM HUNGRY NOW!!!” and if you let it cry it out every single time, eventually it will fight you, and it will win. Because, that little mouse is your core and it will cut off energy to everything to make you stop and take a break and eat nice food and get a hug if it needs to.&lt;&#x2F;p&gt;
&lt;p&gt;When it does the nuclear option, that’s burnout. And when, you try to fight through burnout and bargain with the mouse it will not listen because you have never held up your end of the bargain anyway and so it won’t trust you anymore. You have to prove to the mouse that you can be trusted. You have to stop when its time to stop, and eat when you’re hungry, and get as many hugs as you can, and celebrate any time you achieve your goals.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;making-learning-easy&quot;&gt;making learning easy&lt;&#x2F;h1&gt;
&lt;p&gt;A huge part of inescapable malaise is we feel stagnant. Learning staves off stagnation. Practice new skills to feel like you’re making progress. The quick and dirty version of learning quick is:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;try out the simplest version to get a feel&lt;&#x2F;li&gt;
&lt;li&gt;maybe look some stuff up if you have specific questions&lt;&#x2F;li&gt;
&lt;li&gt;play around a bit more feeling your way toward some small, tangible goal&lt;&#x2F;li&gt;
&lt;li&gt;change your goal and go again&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;DO NOT FOCUS ON THE END PRODUCT OF COMPETENCY. Focussing on some imagined final competency is a ticket to comparison hell. Focus on the process, let your mind relax and try stuff out, you want to explore the possibility space and, in doing so, you will discover a bunch of different ways to do the little thing you want.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;help-other-people-when-you-can&quot;&gt;help other people when you can&lt;&#x2F;h1&gt;
&lt;p&gt;This one’s the hardest one for me. It can be really hard to believe you have anything to offer to other people, but you do. Even if its just a friendly presence. Being able to help others gives you evidence of your own worth, allows you to feel wanted, and to form positive connections.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;unfortunately-you-are-in-charge-of-fun-now&quot;&gt;unfortunately you are in charge of fun now&lt;&#x2F;h1&gt;
&lt;p&gt;There’s no official recess time anymore, you have to give that to yourself. Go out and chase geese, play tag, climb a tree. These are all things we do as kids and stop doing at some point when we “mature”. unfortunately, a lot of us aren’t taught any replacements. If you don’t have any replacements, keep doing the kid stuff. Some more “adult” replacements are: folk dancing, martial arts classes, rock climbing, any field sport.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;your-day-in-the-sun&quot;&gt;your day in the sun&lt;&#x2F;h1&gt;
&lt;p&gt;Forcing yourself to go outside is hard. especially when people act like a twenty minute walk every day is going to cure depression somehow. It won’t. But, Seasonal Affective Disorder is at least partially because of lack of sunlight, so if nothing else try to sit by a window, I try to walk to lunch or breakfast once a day.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;be-around-people&quot;&gt;be around people&lt;&#x2F;h1&gt;
&lt;p&gt;When you are alone too long, your brain’s threat model gets really out of whack and it starts interpreting almost everyone as a threat. It’s also no longer getting regular proof that people are totally fine. You don’t have to socialize, but find an excuse to be in an area where you are likely to see at least 8 other people across the time you’re there, and let your body observe that none of them tried to stab you or call you a stinky doodoo head.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;your-friends-are-not-your-parents&quot;&gt;your friends are not your parents&lt;&#x2F;h1&gt;
&lt;p&gt;Unlike your family, your friends didn’t just wake up one day with you stuck in their lives. It can be hard to believe you are attractive to anyone, but your friends choose to hang out with you and they do that because they get something satisfying out of it. Your friends are more than ok with the version of you right here right now, and they will be happy to see you happier too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sometimes-anger-is-really-useful&quot;&gt;sometimes anger is really useful&lt;&#x2F;h1&gt;
&lt;p&gt;Anger and dread are your body’s way of saying something is wrong. Listen to it and try to eliminate or reduce your exposure to the problem. Maybe that means blocking someone on twitter, maybe that means dropping a college class, maybe that means breaking up with someone.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;listen-to-the-mountain-goats&quot;&gt;listen to the mountain goats&lt;&#x2F;h1&gt;
&lt;p&gt;It’s a good band and John Darnielle is a good song writer.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>how to learn stuff</title>
        <published>2024-12-14T00:00:00+00:00</published>
        <updated>2026-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/learning-skills/"/>
        <id>https://skylosblog.com/posts/learning-skills/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/learning-skills/">&lt;h1 id=&quot;where-i-got-this-from&quot;&gt;Where I got this from&lt;&#x2F;h1&gt;
&lt;p&gt;This post is primarily a way for me to summarize and consolidate what I’ve learned from Barbara Oakley’s “Learning How to Learn”. I also incorporate advice I’ve gotten from professors, from personal reading, and experience.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-to-do-and-why&quot;&gt;what to do and why&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;learn-in-building-blocks&quot;&gt;learn in building blocks&lt;&#x2F;h2&gt;
&lt;p&gt;Everything we know is built out of mental chunks. These chunks are bits of mental data bound together by shared use, context, or meaning - think microskills or phonemes to words. Once disparate pieces of knowledge have conglomerated into a chunk it is treated as a single unit by the brain and it takes little effort to recall and use it. Chunks take so little effort to use that they can become part of the base knowledge that the brain links together into another chunk.&lt;&#x2F;p&gt;
&lt;p&gt;When you learn how to skateboard, you don’t just “learn how to skateboard.” First, you learn how to position your feet, you learn how to squat, you learn how to shift your feet; then you learn how to use all those skills to push forward and to brake. Then, when learning to skate switch you don’t start with learning how to swap feet while moving. You start with learning how to balance while leading with your non-dominant leg.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mix-up-your-learning&quot;&gt;Mix up your learning&lt;&#x2F;h2&gt;
&lt;p&gt;When reading documentation for a software product I often find myself frustrated by the fact that I can’t understand how the part I’m reading about fits into the whole, or form even a vague systematic view of the knowledge base. By jumping around the target knowledge area, we can interleave many sub areas of knowledge and begin to see how they fit together before any one part is fully congealed, allowing us to form a clearer more systemic understanding of the whole. Think of it like loading an interlaced image vs an uninterlaced image. The interlaced one loads a lower resolution of the image faster, and then refines it as more data comes in, as a result we can view and understand the image well before it’s done loading. An un-interlaced image that loads line by line may load each segment in perfect detail, but it takes much longer for that detail to become legible, since we have less of the image to work with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;connect-your-knowledge&quot;&gt;Connect your knowledge&lt;&#x2F;h2&gt;
&lt;p&gt;Knowing things is a snowball process. The more you know, the easier it becomes to learn something new. By looking for way’s we can analogize or relate what we’re learning to what we’re already familiar with we can help ourselves organize our knowledge for retrieval and build that snowball. Metaphors, mnemonics, and visualizations are all useful tools here.  We can also link knowledge by context. Learn about the historical context of what we’re learning about and what it was a response to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;process-over-product&quot;&gt;Process over product&lt;&#x2F;h2&gt;
&lt;p&gt;We’ve all heard some aphorism about loving the journey not the destination, the doing more than the achieving, so on and so forth. These aphorisms are often presented as some sort of moral truism to follow. Such a presentation annoys me and I’m not in the habit of following advice that annoys me. Here’s the amoral case: THE BRAIN IS LAZY. Thinking is calorically intense and our body wants to save energy on every occasion. A process can become a low energy routine, an outcome cannot.&lt;&#x2F;p&gt;
&lt;p&gt;We talked earlier about how chunks convert the hard work of recalling lots of information into the low effort work of recalling one unit of information. Routines are another example of this same chunking. We can chunk a process, making it easy. We can’t chunk a product, in fact by focussing on the product we’re making it even harder for ourselves because we constantly need to evaluate how close we are to our goal and what needs to be done. By focussing on the doing we can learn and chunk out a routine that lets us offload action to our subconscious.&lt;&#x2F;p&gt;
&lt;p&gt;In other words: if you want to learn to play guitar, focus on playing notes and chords and stringing them together, don’t focus on nailing a perfect rendition of “through the fire and flames”.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;have-a-quitting-time&quot;&gt;have a quitting time&lt;&#x2F;h2&gt;
&lt;p&gt;A common piece of productivity advice is to just work on something for a few minutes and then the momentum will carry you through, this is often paired with mentioning the Pomodoro method and how 25 minutes of work followed by a 5 minute break will make you somehow crush your deadlines. If you’re like me, this is not true. In fact it is actively detrimental to building your capacity.&lt;&#x2F;p&gt;
&lt;p&gt;Any act of self deception is going to hurt us, even if we do it to protect ourselves, even if it does protect us. If you tell yourself, as I once tried to, that “oh I’m only going to work for 5 minutes and then stop” while secretly hoping and planning on momentum kicking in and carrying through, some part of you will know you are lying to it, and it will stop trusting you. Some part of you will feel betrayed when you keep working past the five minutes. Some part of you may say 5 minutes isnt enough of a break, it will say “I can’t even get to the break room and back in 5 minutes” and will grow resentful that it works with no reward.&lt;&#x2F;p&gt;
&lt;p&gt;I spent years ignoring these parts and as a result they stopped listening to me. I had lost my ability to trust myself and my own psyche was in active rebellion against me. Loss of self trust makes us anxious, it makes us second guess and agonize over every decision, it shatters self confidence, it makes accomplishing even basic tasks hard because we no longer truly believe in our ability to achieve any of the requisite steps.&lt;&#x2F;p&gt;
&lt;p&gt;Once we are in a place of low to no self trust, if we want to be able to feel functional again, we have to pick a time when the work ends and we have to stick to it. Over and over again. If we say I will work on this for two minutes and then stop. We stop after 2 minutes, even if we think we got nothing done. we stop at 2 minutes and we do this over, and over, and over, until all those worn out distrusting parts can trust us again, and we have to keep that trust.&lt;&#x2F;p&gt;
&lt;p&gt;Any hardship is easier to endure if we know exactly when it will end.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-real-not-torture-pomodoro-method&quot;&gt;The real, not torture Pomodoro method&lt;&#x2F;h3&gt;
&lt;p&gt;The power of the Pomodoro method is that it gives us a quitting time. We can tell ourselves that, “after two pomodoro cycles I will not have to do this again today” and mean it. If after those cycles we’re not done, do two more tomorrow. The other power is we get to reward ourselves for our work. That doesn’t mean a 5 minute break. A lot of the time what we’re trying to do is hard and draining work, a short break seems profoundly unsatisfying. If our reward feels unsatisfying, then it’s not going to generate the dopamine that actually rewards our brain. So ignore the break and find an actual reward, maybe go get a coffee, or play a level of a video game or something.&lt;&#x2F;p&gt;
&lt;p&gt;The loosest version of this system is pick a time period that feels light and manageable, work for that long, recuperate, and reward yourself for a job well done. Repeat that until your quitting time for the day, then QUIT.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;consult-other-people-whenever-you-can&quot;&gt;Consult other people whenever you can&lt;&#x2F;h2&gt;
&lt;p&gt;There’s lots of institutional knowledge out there that very sadly (and sometimes for malicious reasons) cannot be acquired from a book. A lot of that knowledge is very useful and will save us a lot of trouble. There is no way to learn it without consulting with other, more experienced, people, people who remember learning what we’re now trying to learn. If we try to learn everything ourselves from scratch, we will trip and fall many times before we learn to walk, get lost in the woods before we stumble onto the path and so on. We are all greatly advantaged by having someone to consult with even for just a few moments that can point out ruts we might fall in, guide our technique, and provide a roadmap of what we need to learn.&lt;&#x2F;p&gt;
&lt;p&gt;If we try to learn everything on our own, we might by chance discover a few things in the process of fumbling in the dark that noone has seen before, but, by and large we will find ourselves laying the foundations to a cathedral already built elsewhere. Whenever possible, go to the built cathedral and climb the stairs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;experiential-learning-can-only-be-learned-by-experience&quot;&gt;Experiential learning can only be learned by experience&lt;&#x2F;h2&gt;
&lt;p&gt;In the world of sports coaching there is a paradigm referred to as Environmental Dynamics or the Constraint Lead Approach. The problem with conventional coaching that CLA aims to solve is one, that any conceivable drill regimen can’t capture the infinite possibility space of an actual game, two, controlling the body’s movement with the speed and precision necessary for sports performance is incredibly difficult to capture in language.&lt;&#x2F;p&gt;
&lt;p&gt;What a constraints lead approach proposes is: that we have an automatic understanding of how to move our body and build fine motor skills through subconscious neurological adaptations, therefore we train a player not by telling them how to play better, or by telling them what better play looks like, we train them by altering the constraints of the game and its environment to encourage developing the skills they need to improve. For example, if we have a baseball player that is hitting the ball too low, avoid instructing them in the minutiae of how to tense their shoulders or where on the ball they should aim to make contact. Put a wall in front of them and tell them to hit the ball over it. The player now has a way to instantly and intuitively evaluate their performance and can automatically explore their movement space to find an efficient solution. Another example might be to eliminate part of an athlete’s movement. If a swimmer’s kicks seem weak we might give them a flotation device to hold with their hands and tell them to only move by kicking until their speed improves.&lt;&#x2F;p&gt;
&lt;p&gt;Note that this approach only works in a situation where the fundamentals of our domain come to us automatically. We don’t learn to code by typing into a text document until we chance into writing valid Python. But, once we are familiar enough with Python’s syntax, keywords, and standard library that we can begin to easily and automatically explore solutions to problems without having to consult a syntax guide, we can improve our code style and efficiency through similar constraint lead exercises. For example, we might practice eliminating nesting by telling ourselves we aren’t allowed to use an if-statement in our solution, or we might force ourselves to work purely within an object oriented or functional paradigm for a while.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practice-retrieval&quot;&gt;practice retrieval&lt;&#x2F;h2&gt;
&lt;p&gt;What we call skill acquisition is at its core, automatic memory retrieval. When the neural pathway for a certain memory is so burned in that activating and using that information happens unconsciously. Immediately after learning something, try to remember it. Maybe we read a book chapter, before going to take notes we should take thirty seconds to recall as much of what we read as possible. This applies to meetings, coaching, and anything else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;take-days-off&quot;&gt;Take days off&lt;&#x2F;h2&gt;
&lt;p&gt;Information enters long term memory from short term memory via a process called consolidation. Consolidating a memory once isn’t enough to wear in the neural pathways and retrieval will still be difficult and inefficient. If we want to build up automatic recall we have to practice retrieving the memory from long term storage and then reconsolidating it. What this means is we have to let information leave short term memory, and then recall it back and let it leave short term memory over and over again to build up the pathways for that information. Typically, this retrieval practice is called spaced repetition, this often looks like using flash cards once a week or once a month, or drilling our sport of choice on a regular basis. If you’re like me, doing something at the same time once a week or once a month outside of work can be intimidating, difficult, or soul crushingly boring. Instead I would recommend re-framing from spaced repetition to taking breaks.&lt;&#x2F;p&gt;
&lt;p&gt;We can spend a few hours practicing a skill one day, then take a few days off, and come back to it. By thinking about it as a break we prevent ourselves from getting locked into a set schedule, side-stepping some of the intimidating overhead and fear of stagnation, while, still remembering to come back to our skill every now and then.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-it-short&quot;&gt;Keep it short&lt;&#x2F;h2&gt;
&lt;p&gt;We can only maintain focus for a few hours at a time at most. Many professional athlete’s have short, focussed training sessions of around 40 minutes focussing on one skill. They might do more than one session in a day, but one session at a time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practice-deliberately&quot;&gt;Practice deliberately&lt;&#x2F;h2&gt;
&lt;p&gt;Deliberate practice is a bit of a buzzword. What it means is to avoid simply showing up and unconsciously do the actions of your target skill. Instead we want to be attentive, mindful, and focussed on developing specific chunks of our target knowledge. If I’m practicing archery I want to show up and work on having consistent shoulder tension for twenty minutes, then take a break and evaluate my form by shooting at the target and paying attention to where my inconsistencies are.&lt;&#x2F;p&gt;
&lt;p&gt;The other part of deliberate practice is that we must run towards our weaknesses. To build a full skill set we can’t just do the parts we’re good at, we have to locate our points of failure and strengthen them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pick-the-most-minimal-example-you-can-then-do-it&quot;&gt;Pick the most minimal example you can, then do it&lt;&#x2F;h2&gt;
&lt;p&gt;When reading a math paper, it’s good practice to find the simplest example of the principle being described and work through it to see how the machinery works. It’s also a good idea pretty much everywhere else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;celebrate&quot;&gt;Celebrate&lt;&#x2F;h2&gt;
&lt;p&gt;We have reward circuits built into us! We are allowed to use them! Whenever we have a success, we celebrate to re-inforoce that success. Jump! Cheer! Douse yourself in gatagorade! Hug your friends! Go buy some pie! If we only celebrate on big milestones, at best our overall impression of learning becomes neutral labor, at worst it becomes tagged with all the misery of our set backs. We need to make sure that our successes are at &lt;em&gt;least&lt;&#x2F;em&gt; as rewarding as the efforts and setbacks are discouraging.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pre-visualize&quot;&gt;Pre-visualize&lt;&#x2F;h2&gt;
&lt;p&gt;I hesitate to call this necessary or always applicable but sometimes sitting down and mapping out what you want can be exactly what we need. It can give us a north star to look to in times of uncertainty. Pre-visualizing success can make the moment things work feel familiar rather than panicky and unsure. It can smooth out decision making and make skill acquisition feel at hand rather than miles off.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;connect-with-pleasure&quot;&gt;Connect with pleasure&lt;&#x2F;h2&gt;
&lt;p&gt;Learning feels good. There is a deep satisfaction in unlocking a new part of ourselves, in experiencing ourselves in a whole new way, whether that’s with new language, new knowledge, or new ways of moving our bodies. Every time we learn a new skill we become more of who we are; ee unlock more of the potential from our lives.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;take-notes-after-you-ve-digested-the-information&quot;&gt;Take notes, after you’ve digested the information&lt;&#x2F;h2&gt;
&lt;p&gt;Making our own reference material feels great and allows us to test how well we know our stuff. But, If we do it too early we might feel like we’re learning without actually committing anything to memory. We need to let the knowledge percolate, organize and be recalled once or twice before we start writing notes, otherwise we’re simply copying information down without thought. The other danger of making reference notes too early is we don’t have a good understanding of the material yet and can’t organize our thoughts in a way that will be useful to our future selves.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn’t mean we can’t take notes during the learning process. We just need to be sure we’ve considered and practiced retrieving the material first. And, unless our learning notes are exceptionally well organized, we should probably come back to do a second pass to produce our actual reference material.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;notes-and-tips&quot;&gt;Notes and tips&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Write your to-do list the night before, that way you have time to brace and prepare in our sleep&lt;&#x2F;li&gt;
&lt;li&gt;make notes indexable and useable. Use headings, subheadings, accent colors, and even tables of contents to make it easy to find and retrieve the information you need when you need it.&lt;&#x2F;li&gt;
&lt;li&gt;Leave lots of empty space in your notes so that you can annotate and correct anything you write down.&lt;&#x2F;li&gt;
&lt;li&gt;use a mind palace to store ordered sequences&lt;&#x2F;li&gt;
&lt;li&gt;use odd images full of vivid sensory details as mnemonic devices to remember and cluster concepts.&lt;&#x2F;li&gt;
&lt;li&gt;If reading a document, know that the author is trying to guide us through a specific thought process, if we pay attention to the conventions they use to present something to us, and where else we’ve seen them used, it can help us find new associations that help us better understand the subject.&lt;&#x2F;li&gt;
&lt;li&gt;Learn with other people, what clicks with one person won’t click with another, by discussing, even amongst newcomers everyone comes away with a more well rounded understanding.&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes after making progress for a while, we will feel like we plateued or got worse, this is actually a normal phase of learning and can occur when our brain is going through the process of reanalyzing and restructuring our knowledge.&lt;&#x2F;li&gt;
&lt;li&gt;If you can turn learning into a game, do it. Play not only encourages exploration, but lowers our mental barriers to acquiring new information and rules.&lt;&#x2F;li&gt;
&lt;li&gt;You are under no obligation to read the entirety of a textbook or article. Everything on earth is just reference material. Skip to the part that interests you right now, digest it, then leave the book behind until you need it again.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;proposed-procedure&quot;&gt;proposed procedure&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;try it out: its difficult to know what people are talking about if you have no experience. Don’t try to do it well, just try to get a feel for it.&lt;&#x2F;li&gt;
&lt;li&gt;research: remember to skip around the knowledge area to build a holistic picture and look for ways to relate the knowledge back to things we already know.&lt;&#x2F;li&gt;
&lt;li&gt;take a break&lt;&#x2F;li&gt;
&lt;li&gt;set goals and drills: once we know a little bit more about the domain we can start setting up small and achievabel practice goals and drills. For example, learning to make websites:
&lt;ol&gt;
&lt;li&gt;make a single static page with no styling&lt;&#x2F;li&gt;
&lt;li&gt;make a single static page with styling&lt;&#x2F;li&gt;
&lt;li&gt;add javascript interactions to some of the elements&lt;&#x2F;li&gt;
&lt;li&gt;make a multipage website&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;deliberate practice
&lt;ol&gt;
&lt;li&gt;do project or drill&lt;&#x2F;li&gt;
&lt;li&gt;evaluate&lt;&#x2F;li&gt;
&lt;li&gt;take a break&lt;&#x2F;li&gt;
&lt;li&gt;research&lt;&#x2F;li&gt;
&lt;li&gt;repeat&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;example-taking-up-running&quot;&gt;example: taking up running&lt;&#x2F;h1&gt;
&lt;p&gt;I bounced off running a couple times, but then I started playing tag with a friend and got competitive about it. I took up running to improve my stamina and better my odds. Day 1 I picked a trail near my home and ran it without any prior running research. I realized that my stamina was worse than I thought, but also found myself frustrated with how heavy my foot-falls felt and how much my body shook with each step.&lt;&#x2F;p&gt;
&lt;p&gt;The next day I watched some videos and read some articles about running focussed on fixing my heavy footfalls and jostling gait. I learned that the primary variable affecting the smoothness of my run is cadence (how many steps per minute) and that how heavy a footfall feels is primarily a factor of how far ahead of the center of gravity the foot contacts the ground. With these in mind on my next few runs I evaluated how my feet and body felt while trying out different cadences and postures until I found a way to run comfortably and stay acceptably light on my feet.&lt;&#x2F;p&gt;
&lt;p&gt;I then realized I still wasn’t satisfied with my endurance, after each run I was exhausted and I didn’t feel closer to being able to meet my distance goals even if each run was no longer horribly uncomfortable. I did a little more research and learned that the exhaustion I felt was likely a result of poor pacing. I started setting challenges for my runs like “run as slow as possible without walking” or “run twenty minutes without walking or stopping, slow down the run instead”. My goal shifted from improving my time to reducing exhaustion. Now, I’m working on alignment and technique, my goal has shifted to making my weight distribution neutral to forward heavy and I will walk long distances adjusting my torso and feet, looking for a stance that feels like it draws me forward.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>liquid soap for icecast</title>
        <published>2024-12-06T00:00:00+00:00</published>
        <updated>2024-12-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/liquidsoap/"/>
        <id>https://skylosblog.com/posts/liquidsoap/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/liquidsoap/">&lt;p&gt;Liquid soap is a scripting language for programming and controlling live broadcasts.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;concepts&quot;&gt;concepts&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;classes-of-objects&quot;&gt;classes of objects&lt;&#x2F;h2&gt;
&lt;p&gt;Liquidsoap consists of four components&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;requests&lt;&#x2F;strong&gt; which are an abstraction of a file. They take in a uri (a url or file path) and resolve it to media and metadata.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;sources&lt;&#x2F;strong&gt; which provide media data, i.e audio from a file.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;filters&lt;&#x2F;strong&gt; these are functions that take in and output an audio source.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;outputs&lt;&#x2F;strong&gt; these are the endpoints that we send our audio data to, such as an icecast mountpoint.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;clocks&quot;&gt;clocks&lt;&#x2F;h2&gt;
&lt;p&gt;clocks are the secret 5th object, but are largely obscured from us except when liquidsoap’s automation cannot infer a clock on its own. In real time networks there cannot be a universal clock, each computer and potentially each process will be running at its own rate. To account for any discrepancy and maintain a simple model liquidsoap makes the rule that each source has its own clock.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallibility&quot;&gt;fallibility&lt;&#x2F;h2&gt;
&lt;p&gt;If a source is fallible that means that it can stop sending audio data, breaking the chain of audio data. We can fix this with a fallback filter that switches over to another generator if the primary generator fails. By using fallback we can make our source infallible, meaning that it will always be sending audio data. Outputs will error&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-streaming-works&quot;&gt;how streaming works&lt;&#x2F;h1&gt;
&lt;h1 id=&quot;snippets-and-examples&quot;&gt;snippets and examples&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;working-with-the-shell&quot;&gt;working with the shell&lt;&#x2F;h2&gt;
&lt;p&gt;https:&#x2F;&#x2F;www.liquidsoap.info&#x2F;doc-2.3.0&#x2F;cookbook.html#unix-interface-dynamic-requests&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speech-synthesis&quot;&gt;speech synthesis&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;say&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$(time)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;set-metadata&quot;&gt;set metadata&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;annotate:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;sources&quot;&gt;sources&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;single(&amp;quot;path&#x2F;to&#x2F;file.mp3&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;creates a source that repeats the same audio forever&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;playlist(&amp;quot;path&#x2F;to&#x2F;file.m3u&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;playlist(&amp;quot;~&#x2F;Music&#x2F;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;creates a source that plays songs in sequence. It can take any file that’s just a newline separated list of uris but also more advanced playlist formats like pls or m3u.
playlist has 3 modes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;normal: plays in order&lt;&#x2F;li&gt;
&lt;li&gt;randomize: shuffles playlist and then plays in order&lt;&#x2F;li&gt;
&lt;li&gt;random: picks a random song after each track ends&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;By default once a playlist is created it doesn’t update itself if the file&#x2F;directory it was generated from changes. The &lt;code&gt;reload&lt;&#x2F;code&gt; argument allows us to update the playlist on file change with &lt;code&gt;reload=&quot;watch&quot;&lt;&#x2F;code&gt; or after a certain period of time or after every time it completes a round.The playlist’s reload method can also be called by another function.&lt;&#x2F;p&gt;
&lt;p&gt;for remote sources we need to use &lt;code&gt;input&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;input.&amp;lt;protocol&amp;gt;(&amp;lt;URI&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;programming-the-radio-kind&quot;&gt;programming (the radio kind)&lt;&#x2F;h2&gt;
&lt;!-- ### scheduled programming --&gt;
&lt;h3 id=&quot;play-next&quot;&gt;play next&lt;&#x2F;h3&gt;
&lt;p&gt;by default source combinators are &lt;em&gt;track sensitive&lt;&#x2F;em&gt; meaning that they will wait for the currently playing track to end before switching to the next one. We can make them switch instantly if we use the keyword argument &lt;code&gt;track_sensitive=false&lt;&#x2F;code&gt;. Note that some sources don’t have track data and so will never have an “end” for a switch to take place at.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;random([source1, source2])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will randomly pick between the provided sources&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sequence([source1, source2, source3])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will play one track from each source in order and  then play from the final source.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interrupt-now&quot;&gt;interrupt now&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fallback(track_sensitive=false, [primary, secondary, tertiary])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will play whichever source is active and highest priority. If primary is normally off, and secondary is regular programming, you can override secondary by activating the primary source&lt;&#x2F;p&gt;
&lt;p&gt;the &lt;code&gt;track_sensitive&lt;&#x2F;code&gt; option lets us do instant fallback. If we don’t set it false it will wait for the track to finish before switching. If the track is infinite then it will never switch!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;outputting&quot;&gt;outputting&lt;&#x2F;h2&gt;
&lt;p&gt;This is actually the last step. We create an output object with any log in information we need and pass it our programming source.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output.file(%mp3, &amp;quot;out.mps&amp;quot;, source)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;read-more&quot;&gt;read more&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.liquidsoap.info&#x2F;book&#x2F;book.pdf&quot;&gt;http:&#x2F;&#x2F;www.liquidsoap.info&#x2F;book&#x2F;book.pdf&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;liquidsoap&#x2F;tour.liq&quot;&gt;language tour&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>useful css details</title>
        <published>2024-11-26T00:00:00+00:00</published>
        <updated>2024-11-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/css-notes/"/>
        <id>https://skylosblog.com/posts/css-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/css-notes/">&lt;h1 id=&quot;css-selectors&quot;&gt;css selectors&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Select a tag of object by writing just its name ie &lt;code&gt;h1{color: red;}&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Select multiple tags using a &lt;em&gt;selector list&lt;&#x2F;em&gt;, for instance &lt;code&gt;h1, p {color red}&lt;&#x2F;code&gt; selects all headers and all paragraphs.&lt;&#x2F;li&gt;
&lt;li&gt;Attribute selectors allow you to select elements by their attributes, for example selecting all the links to a specific website with `a[href=“specialsite.com”]. MDN has a full list of selector operators.&lt;&#x2F;li&gt;
&lt;li&gt;Combinators allow you to select by hierarchy, for example all links that follow an image with &lt;code&gt;img + a{}&lt;&#x2F;code&gt;. MDN has a full list of combinators. The most useful combinator is a space which lets you select children for example &lt;code&gt;.content-container img&lt;&#x2F;code&gt; selects all images in the &lt;code&gt;.content-container&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;pseudo-classes-and-pseudo-elements&quot;&gt;pseudo-classes and pseudo-elements&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Pseudoclasses&lt;&#x2F;strong&gt; select elements by state such as being hovered over. They are represented with a preceding colon ie &lt;code&gt;:hover&lt;&#x2F;code&gt; and can be combined with other selectors like &lt;code&gt;a:hover&lt;&#x2F;code&gt;. &lt;strong&gt;Pseudo-elements&lt;&#x2F;strong&gt; are preceded with two colons (&lt;code&gt;::&lt;&#x2F;code&gt;). They are used to select based on things that can only be determined at run-time, for example &lt;code&gt;::first-line&lt;&#x2F;code&gt; which is dependant on screen width. There’s also the &lt;code&gt;::before&lt;&#x2F;code&gt; and &lt;code&gt;::after&lt;&#x2F;code&gt; pseudo-elements which when paired with the &lt;code&gt;content&lt;&#x2F;code&gt; attribute allow us to insert text and visuals before or after our target element.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;at-rules&quot;&gt;at rules&lt;&#x2F;h1&gt;
&lt;p&gt;At rules are meta statements used for defining custom variables, importing other style sheets, declaring resources, and more.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;variables-custom-properties&quot;&gt;variables&#x2F;custom properties&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;syntax&quot;&gt;– syntax&lt;&#x2F;h2&gt;
&lt;p&gt;Within a ruleset we can use &lt;code&gt;--&lt;&#x2F;code&gt; to declare a variable, for instance &lt;code&gt;.article{ --primary-color:red;}&lt;&#x2F;code&gt; but then its scoped in to only be referenceable within the article class. We can put the declaration under the &lt;code&gt;:root&lt;&#x2F;code&gt; pseudoclass to give it global scope. Our variable is then dereferenced using the &lt;code&gt;var()&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    --primary-color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt; red&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;--primary-color&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;property-syntax&quot;&gt;@property syntax&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;@property&lt;&#x2F;code&gt; rule is the more powerful older sister of &lt;code&gt;--custom-properties&lt;&#x2F;code&gt;. It allows us to define bahavior such as inheritance and default values, and it comes with type checking. It’s still dereferenced with the &lt;code&gt;var()&lt;&#x2F;code&gt;function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span&gt; primary-color&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    syntax: &amp;quot;&amp;lt;color&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;this is a type annotation so css can error if given a non-color type &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inherits: false;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;always true for `--` declared variables&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    initial-value&lt;&#x2F;span&gt;&lt;span&gt;: red;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;value before inheriting&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you may have noticed some mention of inheritance. We can override variable definitions within a ruleset and any children will inherit that value unless inherits is set to false.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;functions&quot;&gt;functions&lt;&#x2F;h1&gt;
&lt;p&gt;CSS also comes with lots of functions which mostly fall into the category of geometric functions like &lt;code&gt;sin()&lt;&#x2F;code&gt; and responsive functions that allow us to set attributes in response to the user settings, for example &lt;code&gt;light-dark()&lt;&#x2F;code&gt; which allows us to give one of two values depending on if the user prefers light or dark mode. Theres also a bunch of visual effect functions like the family of gradient functions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;precedence&quot;&gt;precedence&lt;&#x2F;h1&gt;
&lt;p&gt;CSS precedence order:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;most specific relevant selector&lt;&#x2F;li&gt;
&lt;li&gt;last written rule&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Rules properties also usually inherit from their parents unless over ridden. Not all properties inherit, for example width does not inherit since that would be less useable.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;box-model&quot;&gt;box model&lt;&#x2F;h1&gt;
&lt;p&gt;The three display types:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;block: starts on a new line and width and height properties are respected&lt;&#x2F;li&gt;
&lt;li&gt;inline: height and width properties ignored&lt;&#x2F;li&gt;
&lt;li&gt;flex: stretches to fill the space&lt;&#x2F;li&gt;
&lt;li&gt;grid: defines a set of columns and rows that it’s children will stick to&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>how to flask</title>
        <published>2024-11-24T00:00:00+00:00</published>
        <updated>2024-11-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/flask-notes/"/>
        <id>https://skylosblog.com/posts/flask-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/flask-notes/">&lt;h1 id=&quot;flask&quot;&gt;flask&lt;&#x2F;h1&gt;
&lt;p&gt;flask is a framework used for building web apps.
it uses the jinja template engine&lt;&#x2F;p&gt;
&lt;p&gt;It primarily operates via an &lt;code&gt;app&lt;&#x2F;code&gt; object.&lt;&#x2F;p&gt;
&lt;p&gt;flask is built on the WSGI spec, what this means is that the server hardware is running a WSGI server, that server receives an HTTP request, transforms it into a WSGI environ dict, calls a WSGI application (flask) with that environ dict, the application processes the dict and returns a WSGI response which the server translates to an HTTP response and sends it to the client.&lt;&#x2F;p&gt;
&lt;p&gt;what this means is that we never actually touch a raw request we simply set up responses for different cases our flask app might get.&lt;&#x2F;p&gt;
&lt;p&gt;Flask also makes use of the jinja template engine and the workzeug module to provide a bunch of handy functionality such as input sterilization.&lt;&#x2F;p&gt;
&lt;p&gt;We can connect our own database layer but flask doesn’t come with one. That said, there is a version of SQLAlchemy, a popular database abstraction layer, preconfigured to work with flask called &lt;code&gt;Flask-SQLAlchemy&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;objects&quot;&gt;objects&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;app&quot;&gt;app&lt;&#x2F;h3&gt;
&lt;p&gt;the app object represents the WSGI application the server will call with a request dict. It holds all the configuration information and all the request handlers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;request&quot;&gt;request&lt;&#x2F;h3&gt;
&lt;p&gt;represents the request dict. Stores query string variables and cookies. Access query vars with &lt;code&gt;request.args&lt;&#x2F;code&gt; and cookies with &lt;code&gt;request.cookies&lt;&#x2F;code&gt;. Both are stored as dictionaries. It’s reccomended to use &lt;code&gt;request.cookies.get(&quot;key&quot;)&lt;&#x2F;code&gt; to avoid keyerrors. Access request form data with &lt;code&gt;request.form[&quot;field_name&quot;]&lt;&#x2F;code&gt;. to access JSON data we use &lt;code&gt;request.json[&quot;field_name&quot;]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;session&quot;&gt;session&lt;&#x2F;h3&gt;
&lt;p&gt;Holds user specific data between requests. we can add and remove data from it. An example would be adding a username to the session on login.&lt;&#x2F;p&gt;
&lt;p&gt;The session object is serialized into a cookie on the client, so you have to be conscious of size to avoid truncating it. The session cookie is encrypted with the secret key that you can configure in flask.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;g&quot;&gt;g&lt;&#x2F;h3&gt;
&lt;p&gt;this is a proxy object for you to store stuff in that can then be acessed by any function in the app, it does not persist between instances. You can set a new member simply by doing &lt;code&gt;g.foo = data&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blueprint&quot;&gt;blueprint&lt;&#x2F;h3&gt;
&lt;p&gt;a blueprint is essentially a middle layer between an app and some views. It allows you to group a bunch of related views together into one blueprint which can then be added to the app. as far as writing views for a blueprint is concerned it exposes an identical interface as the app object.
to integrate a blueprint into the app use&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; create_app&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    from&lt;&#x2F;span&gt;&lt;span&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; blueprint_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;your blueprint is defined in blueprint_name.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Flask&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;__name__&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; instance_relative_config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;register_blueprint&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;blueprint_name&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To initialize a blueprint in your &lt;code&gt;blueprint_name.py&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Blueprint&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;blueprint_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; url_prefix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;url_prefix&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;application-phases&quot;&gt;application phases&lt;&#x2F;h2&gt;
&lt;p&gt;this is analogous to compile time and run time. In the set up phase we are defining our routing and logic etc. In the serving phase we the programmer do nothing. Our flask app should not be self modify and flask should error if we try to make it do so.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;set up&lt;&#x2F;strong&gt; is where we do our app configuration and define all our views etc, essentially building our app instance.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;serving&lt;&#x2F;strong&gt; is our run time when the flask app object we created is receiving requests&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;set-up&quot;&gt;set up&lt;&#x2F;h3&gt;
&lt;p&gt;we need to configure the app object with a couple things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the name of the file&lt;&#x2F;li&gt;
&lt;li&gt;a secret key for session data&lt;&#x2F;li&gt;
&lt;li&gt;a path to a db&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;app = Flask(__name__, instance_relative_config=True)&lt;&#x2F;code&gt; creates the Flask instance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;__name__&lt;&#x2F;code&gt; is the name of the current Python module. The app needs to know where it’s located to set up some paths, and &lt;code&gt;__name__&lt;&#x2F;code&gt; is a convenient way to tell it that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;instance_relative_config=True&lt;&#x2F;code&gt; tells the app that configuration files are relative to the instance folder. The instance folder is located outside the app package and can hold local data that shouldn’t be committed to version control, such as configuration secrets and the database file.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;views&quot;&gt;views&lt;&#x2F;h2&gt;
&lt;p&gt;these are either functions or classes bound to a url. See routing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;directory-structure&quot;&gt;directory structure&lt;&#x2F;h2&gt;
&lt;p&gt;The flask app crawls its local directory looking for templates and static files to include.
a typical structure looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;project_dir&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+- app&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  +- templates&#x2F; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  +- static&#x2F; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  +- __init__.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  +- app.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+- tests&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+- venv&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;request-handling&quot;&gt;request handling&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;routing&quot;&gt;routing&lt;&#x2F;h3&gt;
&lt;p&gt;by placing a decorator on a function we can bind a part of the app object’s request interface to that function as a request handler.&lt;&#x2F;p&gt;
&lt;p&gt;we can include parameters in the route path using &lt;code&gt;&#x2F;&amp;lt;foo&amp;gt;&lt;&#x2F;code&gt; then binding to a function that takes &lt;code&gt;foo&lt;&#x2F;code&gt; as an arg.&lt;&#x2F;p&gt;
&lt;p&gt;we can also bind post requests with a decorator&lt;&#x2F;p&gt;
&lt;p&gt;instead of returning raw http we can return the result of a &lt;code&gt;render_template(&#x27;template.html&#x27;, foo=&#x27;bar&#x27;, baz=&#x27;bat&#x27;)&lt;&#x2F;code&gt; call&lt;&#x2F;p&gt;
&lt;h3 id=&quot;http-methods-in-routes&quot;&gt;HTTP methods in routes&lt;&#x2F;h3&gt;
&lt;p&gt;specify what methods a route supports with &lt;code&gt;@app.route(&#x27;&#x2F;&#x27;, methods=[&#x27;GET&#x27;,&#x27;POST&#x27;])&lt;&#x2F;code&gt;. Note that &lt;code&gt;&#x27;GET&#x27;&lt;&#x2F;code&gt; is the default and methods is always a list. We can specify the method in the function body with &lt;code&gt;if request.method == &#x27;POST&#x27;:&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can also do &lt;code&gt;@app.get(&#x27;&#x2F;&#x27;)&lt;&#x2F;code&gt; and &lt;code&gt;@app.post(&#x27;&#x2F;&#x27;)&lt;&#x2F;code&gt; to have separate functions for common http methods.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reading-query-strings&quot;&gt;reading query strings&lt;&#x2F;h3&gt;
&lt;p&gt;Query strings are what comes after a &lt;code&gt;?&lt;&#x2F;code&gt; in a url, for example &lt;code&gt;site.com&#x2F;query&#x2F;?foo=0&amp;amp;bar=something&lt;&#x2F;code&gt; we can then access these in flask via &lt;code&gt;request.args&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;models-with-sqlalchemy&quot;&gt;Models with SQLAlchemy&lt;&#x2F;h2&gt;
&lt;p&gt;SQLAlchemy is a python abstraction layer on top of SQL, it allows us to interact with an SQL database only using python. SQLAlchemy’s interface is handled through a &lt;code&gt;database&lt;&#x2F;code&gt; object. We initialize the database by defining model classes that represent the table structure and then calling &lt;code&gt;db.create_all()&lt;&#x2F;code&gt; to make the tables in the actual sql database. We then interact with the database using the &lt;code&gt;database.session()&lt;&#x2F;code&gt; onject Like with mysqlconnector we then query the database with &lt;code&gt;database.session.execute(command)&lt;&#x2F;code&gt; followed by &lt;code&gt;database.session.commit()&lt;&#x2F;code&gt; which guarantees all changes are made before moving on to the next piece of code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;models&quot;&gt;Models&lt;&#x2F;h3&gt;
&lt;p&gt;Models are essentially a way of representing data tables with object orientation, referred to as ORM (Object Relational Mapping).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sessions&quot;&gt;Sessions&lt;&#x2F;h3&gt;
&lt;p&gt;Sessions are how we interact with the database object. It represents a queue of commads we’ve sent and we can ensure they’re all executed using the &lt;code&gt;commit()&lt;&#x2F;code&gt; method, which blocks until the last query is completed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;json&quot;&gt;JSON&lt;&#x2F;h2&gt;
&lt;p&gt;gets returned if we send back a data object&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication-and-verification&quot;&gt;authentication and verification&lt;&#x2F;h2&gt;
&lt;p&gt;this can be done with workzeug or&lt;&#x2F;p&gt;
&lt;h1 id=&quot;hosting&quot;&gt;hosting&lt;&#x2F;h1&gt;
&lt;p&gt;to run the app locally use &lt;code&gt;flask --app foo run&lt;&#x2F;code&gt;. to host on the local network add &lt;code&gt;--host 0.0.0.0&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;jinja&quot;&gt;jinja&lt;&#x2F;h1&gt;
&lt;p&gt;the three types of placeholders are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{% statement %}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{{expression}}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{# comment #}&lt;&#x2F;code&gt;
&lt;code&gt;{{ foo.bar }}&lt;&#x2F;code&gt; and &lt;code&gt;{{ foo[&#x27;bar&#x27;] }}&lt;&#x2F;code&gt; are equivalent. you can escape using &lt;code&gt;{%raw%} ... {%endraw%}&lt;&#x2F;code&gt; or &lt;code&gt;{{ &#x27;{{&#x27; }}&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The big power of templates is that it enables code reuse and parametric page generation. Meaning we can set up a template for the main page structure including our nav bar and footer and then load in different content for every page. We can also make a macro that represents a small component we can reuse multiple times a page or reuse in multiple pages across the site. We also have filters which are like fucntions.
The prime functionality of jinja is template blocks. Each block has a scope and expressions cannot climb out of their local scope unless the block is declared with a &lt;code&gt;scoped&lt;&#x2F;code&gt; modifier like &lt;code&gt;{%block foo scoped%}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We pass data to jinja via keyword arguments to flask’s &lt;code&gt;render_template&lt;&#x2F;code&gt; function, which we can then access by name.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;render_template&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;test.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then accessed by the keyword name &lt;code&gt;{{data}}&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Objects in the “standard flask context” are also accessible from within jinja, most importantly &lt;code&gt;session&lt;&#x2F;code&gt;, &lt;code&gt;request&lt;&#x2F;code&gt; and, &lt;code&gt;g&lt;&#x2F;code&gt;. We can then key into object by for example doing &lt;code&gt;{{session[&#x27;username&#x27;]}}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;include&quot;&gt;include&lt;&#x2F;h2&gt;
&lt;p&gt;renders the entire included template&lt;&#x2F;p&gt;
&lt;h2 id=&quot;import&quot;&gt;import&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% import &amp;quot;macros.html&amp;quot; as macros%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;adds declarations into scope, useful for macros&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inheritance&quot;&gt;inheritance&lt;&#x2F;h2&gt;
&lt;p&gt;First we define a base template. Inside the template we define blocks for a child template to override.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% block foo %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    default content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endblock %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In our child template we inherit from another template via &lt;code&gt;{% extends &quot;foo.html&quot; %}&lt;&#x2F;code&gt;. We then redefine the blocks to overwrite&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% block foo %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    new content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endblock %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we can also keep the old default behaviour by calling &lt;code&gt;\{\{super()\}\}&lt;&#x2F;code&gt; inside our new block.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;macros&quot;&gt;macros&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% macro input(name, value=&amp;#39;&amp;#39;, type=&amp;#39;text&amp;#39;, size=20) -%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ type }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ name }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        value|e }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ size }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endmacro %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ input(&amp;#39;username&amp;#39;) }}&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ input(&amp;#39;password&amp;#39;, type=&amp;#39;password&amp;#39;) }}&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;filters&quot;&gt;filters&lt;&#x2F;h2&gt;
&lt;p&gt;we can call filters a number of ways:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{var|filter1|filter2}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{filter2(filter2(var))}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% filter filtername%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    content to be filtered&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfilter %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;iterating-over-lists&quot;&gt;iterating over lists&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% for item in items %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;mysql&quot;&gt;MYSQL&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;I WILL BE USING MARIADB SINCE THAT’S WHAT ARCH LIKES&lt;&#x2F;strong&gt;
on arch you must start he server using &lt;code&gt;systemctl start mysqld&lt;&#x2F;code&gt; before connecting to the server with the &lt;code&gt;mariadb&lt;&#x2F;code&gt; command. By default mariadb stores its files in a default directory like &lt;code&gt;usr&#x2F;mysql&#x2F;&lt;&#x2F;code&gt;. The root user will have the same log in as the root computer account. You can use mariadb as root by doing &lt;code&gt;sudo mariadb&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;SQL is a relational database system. It uses tables where every row is a record and every column is a field. We can then set up relations between tables in a database. Meaning we link the rows of one table to the rows of another.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sql-commands&quot;&gt;SQL commands&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SQL syntax order is:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;HAVING&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;UNION&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;sometimes you may need to select a database by running &lt;code&gt;use db_name;&lt;&#x2F;code&gt; you can then select a different database later or quit the whole session to go back to having non selected.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-a-new-user&quot;&gt;setting up a new user&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; user&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;@localhost&lt;&#x2F;span&gt;&lt;span&gt; identified (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;with&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;policy&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;by&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;grant&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;privileges&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;db&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;@localhost&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;with&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; grant&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;privileges are stuff like &lt;code&gt;create&lt;&#x2F;code&gt;, &lt;code&gt;alter&lt;&#x2F;code&gt;, &lt;code&gt;drop&lt;&#x2F;code&gt;, &lt;code&gt;insert&lt;&#x2F;code&gt;, &lt;code&gt;update&lt;&#x2F;code&gt;, &lt;code&gt;delete&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linking-tables&quot;&gt;linking tables&lt;&#x2F;h3&gt;
&lt;p&gt;we use joins to link tables. The join returns a new table with records concatenated based on some foreign key, for example customer IDs from the customer table and customer IDs from the order table.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;select&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; orders&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;order_id&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;customers&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;customer_name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;orders&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;date&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;orders &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt; customers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;on&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; orders&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;customer_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; customers&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;customer_id&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;using left or right join returns all the records of the left or right table even if there is nothing to join it to.&lt;&#x2F;p&gt;
&lt;p&gt;we can also union two tables or selects together using either &lt;code&gt;union&lt;&#x2F;code&gt; or &lt;code&gt;union all&lt;&#x2F;code&gt; to include duplicates.&lt;&#x2F;p&gt;
&lt;p&gt;a field we can join on is referred to as a key. A primary key is a unique value to identify a certain record, something like &lt;code&gt;customer_id&lt;&#x2F;code&gt; in the &lt;code&gt;customer&lt;&#x2F;code&gt; table and a foreign key is something like the &lt;code&gt;customer_id&lt;&#x2F;code&gt; field in the &lt;code&gt;orders&lt;&#x2F;code&gt; table that we can use to link orders to customers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-tables&quot;&gt;creating tables&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; table&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    column_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    column_name2 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt;,....&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;some examples of types are &lt;code&gt;text&lt;&#x2F;code&gt;, &lt;code&gt;integer&lt;&#x2F;code&gt;, &lt;code&gt;date&lt;&#x2F;code&gt;. Some constraints are &lt;code&gt;primary key&lt;&#x2F;code&gt;, &lt;code&gt;auto_increment&lt;&#x2F;code&gt;, &lt;code&gt;not null&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;entering-data&quot;&gt;entering data&lt;&#x2F;h3&gt;
&lt;p&gt;We add data to a table using&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;insert into&lt;&#x2F;span&gt;&lt;span&gt; table_name (column1, column2, ...) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt; (value1a, value2a, ...), (value1b, value2b, ...);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where the column tuple indicates which fields the values are tied to, and each value tuple is a new record to be inserted.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;getting-data&quot;&gt;getting data&lt;&#x2F;h3&gt;
&lt;p&gt;The fundamental way to query data is with the &lt;code&gt;select _ from table&lt;&#x2F;code&gt; command. We can select everything using &lt;code&gt;select * from table&lt;&#x2F;code&gt; or we can do &lt;code&gt;select field1, field2,... from table;&lt;&#x2F;code&gt; to only return the data from certain fields rather than the whole row. We can use &lt;code&gt;select distinct name from employees;&lt;&#x2F;code&gt; to get all the unique names of employees. But what if we want to filter out whole rows using &lt;code&gt;where&lt;&#x2F;code&gt;. For example &lt;code&gt;select name from friends where name like &#x27;j%&#x27;;&lt;&#x2F;code&gt; to get all friends whose name starts with J.&lt;&#x2F;p&gt;
&lt;p&gt;You can concatenate columns in your query by doing&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt; lastname &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; firstname &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; fullname &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; friends;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;updating-data&quot;&gt;updating data&lt;&#x2F;h3&gt;
&lt;p&gt;we update the structure of a table using the &lt;code&gt;ALTER&lt;&#x2F;code&gt; keyword. To update records we use the &lt;code&gt;UPDATE&lt;&#x2F;code&gt; and &lt;code&gt;SET&lt;&#x2F;code&gt; keyword filtered using &lt;code&gt;WHERE&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ALTER&lt;&#x2F;code&gt; lets us add and remove columns to a table or rename them, for example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;alter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; table&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt; email &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;alter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; table&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt; column email;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;alter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; table&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rename column f_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt; full_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To update records do:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uodate customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; lastname &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hapsburg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, city &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;berlin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; customerID &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;deleting-data&quot;&gt;deleting data&lt;&#x2F;h3&gt;
&lt;p&gt;we can delete a table by doing &lt;code&gt;drop table table_name&lt;&#x2F;code&gt; we can also clear all the data from a table via &lt;code&gt;truncate table table_name&lt;&#x2F;code&gt;. To remove specific records from a table use &lt;code&gt;delete from table_name where column_name=value&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-procedures&quot;&gt;creating procedures&lt;&#x2F;h2&gt;
&lt;p&gt;An unparametrized procedure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; procedure&lt;&#x2F;span&gt;&lt;span&gt; getCustomerIds &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    select&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;go&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span&gt; getCustomerIds;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;a parametrized procedure&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; procedure&lt;&#x2F;span&gt;&lt;span&gt; getIdsByNameAndCity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @name&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; text&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @city&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    select&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    where&lt;&#x2F;span&gt;&lt;span&gt; city &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; @city&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; and&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; @name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;go&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span&gt; getIdsByNameAndCity &lt;&#x2F;span&gt;&lt;span&gt;@city&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;seattle, &lt;&#x2F;span&gt;&lt;span&gt;@name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; henry;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you can set specific data to be returned using the &lt;code&gt;output&lt;&#x2F;code&gt; keyword&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; procedure&lt;&#x2F;span&gt;&lt;span&gt; getIdsByNameAndCity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @name&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; text&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @city&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; text&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @output_data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    select&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; customers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    where&lt;&#x2F;span&gt;&lt;span&gt; city &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; @city&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; and&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; @name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;go&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span&gt; getIdsByNameAndCity &lt;&#x2F;span&gt;&lt;span&gt;@city&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;seattle, &lt;&#x2F;span&gt;&lt;span&gt;@name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; henry;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;connecting-to-the-server&quot;&gt;connecting to the server&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; mysql&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mydb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; mysql&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connector&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;localhost&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yourusername&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yourpassword&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mydb&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;executing-on-the-server&quot;&gt;executing on the server&lt;&#x2F;h3&gt;
&lt;p&gt;To do stuff on the server we use an object called a cursor &lt;code&gt;cursor = mydb.cursor()&lt;&#x2F;code&gt; then we execute sql with &lt;code&gt;cursor.execute(&quot;SQL CODE&quot;)&lt;&#x2F;code&gt;. The data returned from the query will be stored in &lt;code&gt;cursor&lt;&#x2F;code&gt; as an iterator, we use &lt;code&gt;cursor.fetchall()&lt;&#x2F;code&gt; to see everything. If we modify the databse in anyway we then have to commit the change using &lt;code&gt;connection.commit()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;javascript-http-requests&quot;&gt;Javascript http requests&lt;&#x2F;h1&gt;
&lt;p&gt;in order to build extra functionality into our website we may need to make our webpage do calculations that need execution on the server side, to accomplish that, we use javascript to send an http request to the server and display the response. We can use the &lt;code&gt;fetch&lt;&#x2F;code&gt; function or a&lt;code&gt;XMLHttpRequest&lt;&#x2F;code&gt; object. Fetch is newer but not yet featureful enough to deprecate the request object.&lt;&#x2F;p&gt;
&lt;p&gt;note that refreshing a page in javascript is finicky so if you want changes to update the whole page rather than a specific element after the request is sent its best to send the request using a form submission, either via html with &lt;code&gt;&amp;lt;form method=&quot;POST&quot; action=&quot;url&quot;&amp;gt;&lt;&#x2F;code&gt; or by overriding the submit button in javascript if we want to enrypt the data client side first, for example. After encrypting the data we can then call &lt;code&gt;form.submit()&lt;&#x2F;code&gt;. Note, that if using &lt;code&gt;form.submit()&lt;&#x2F;code&gt; we need to make sure we’ve updated the form data or are using a hidden form with the encrypted data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xmlhttprequest-object&quot;&gt;XMLHttpRequest object&lt;&#x2F;h2&gt;
&lt;p&gt;the &lt;code&gt;XMLHttpRequest&lt;&#x2F;code&gt; object represents the request across its full lifetime, first we build the request into the object, then we send it, then we read the response from the request object’s attributes. We can also read the request’s progress before it’s complete using a callback.
steps of use:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;construct with &lt;code&gt;xhr =new XMLHttpRequest()&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;initialize&#x2F;configure with &lt;code&gt;xhr.open(&amp;lt;&quot;GET&quot;&#x2F;&quot;POST&quot;&amp;gt;, &amp;lt;URL&amp;gt;, [optional: async, user, password])&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;set up callbacks for:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;xhr.onload = function&lt;&#x2F;code&gt; executes on completion of request&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;xhr.onerror = function&lt;&#x2F;code&gt; executes if request couldnt be made&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;xhr.onprogress = function(event)&lt;&#x2F;code&gt; executes periodically with an event object containing download progress information&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;send the request &lt;code&gt;xhr.send(&amp;lt;request body&amp;gt;)&lt;&#x2F;code&gt; (can be empty, like if we’re doing a get request)&lt;&#x2F;li&gt;
&lt;li&gt;callbacks execute&lt;&#x2F;li&gt;
&lt;li&gt;read response data from object attributes such as &lt;code&gt;xhr.status&lt;&#x2F;code&gt; which holds an http status code such as &lt;code&gt;200&lt;&#x2F;code&gt; or &lt;code&gt;404&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;note in step 2 if we set async to false, execution will pause until the request response is received after we send it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sending-data-in-a-request&quot;&gt;sending data in a request&lt;&#x2F;h3&gt;
&lt;p&gt;We now know how to make a request, but how should we include data in that request?&lt;&#x2F;p&gt;
&lt;h4 id=&quot;url&quot;&gt;url&lt;&#x2F;h4&gt;
&lt;p&gt;We can use the url as a variable and simply request a url that the server then does a calculation on. For example we can make a request to &lt;code&gt;site.com&#x2F;math&#x2F;sin&#x2F;&amp;lt;number&amp;gt;&lt;&#x2F;code&gt; and the server will respond with the sin of &lt;code&gt;&amp;lt;number&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;querystring&quot;&gt;querystring&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;code&gt;site.com&#x2F;math&#x2F;addition?x=&amp;lt;m&amp;gt;&amp;amp;y=&amp;lt;n&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;request-body&quot;&gt;request body&lt;&#x2F;h4&gt;
&lt;p&gt;When we send a request we can send it with a jason or form data body.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;xhr&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;field1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; field2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;xhr&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FormData&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;querySelector&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#form&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;readystate&quot;&gt;readystate&lt;&#x2F;h3&gt;
&lt;p&gt;the &lt;code&gt;xhr.readystate&lt;&#x2F;code&gt; attribute represents the request state.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;state code&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;initial state, object just was just created&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;request has been initialized&#x2F;configured by calling &lt;code&gt;xhr.open()&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;response headers received&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;response is loading (set every time we receive a data packet)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;request complete, response fully loaded&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;we can then  set up a callback for &lt;code&gt;xhr.onreadystatechange = function&lt;&#x2F;code&gt; that handles each state.&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;response-type&quot;&gt;response type&lt;&#x2F;h3&gt;
&lt;p&gt;we can request the server send its response in a specific format via &lt;code&gt;xhr.respoonseType&lt;&#x2F;code&gt;, our options are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;text&quot;&lt;&#x2F;code&gt; (this is the default         )&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&quot;arraybuffer&quot;&lt;&#x2F;code&gt; (binary data)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&quot;blob&quot;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&quot;document&quot;&lt;&#x2F;code&gt; (xml,html, etc)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&quot;json&quot;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;bootstrap&quot;&gt;bootstrap&lt;&#x2F;h1&gt;
&lt;p&gt;Bootstrap is premade css and js that implements a whole bunch of common design patterns. By including it in your html document you can rapidly flesh out and prototype a useable website without having to build your buttons, forms, etc from scratch. The base document with bootstrap should look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;doctype&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; html&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;viewport&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; content&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;width=device-width, initial-scale=1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;npm&#x2F;bootstrap@5.3.3&#x2F;dist&#x2F;css&#x2F;bootstrap.min.css&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;  crossorigin&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;anonymous&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {{content}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;npm&#x2F;@popperjs&#x2F;core@2.11.8&#x2F;dist&#x2F;umd&#x2F;popper.min.js&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;  crossorigin&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;anonymous&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;npm&#x2F;bootstrap@5.3.3&#x2F;dist&#x2F;js&#x2F;bootstrap.min.js&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; crossorigin&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;anonymous&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;to style elements bootstrap coms with a bunch of prebuilt classes, for example to make a button look like a button we might do &lt;code&gt;&amp;lt;button type=&quot;button&quot; class=&quot;btn btn-primary&quot;&amp;gt;click here!&amp;lt;&#x2F;button&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ideally we don’t need to write any css we just compose bootstrap classes for example &lt;code&gt;&amp;lt;div class=&quot;jumbotron text-center&quot;&amp;gt;centered large text&amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We can also cheat a little bit and use prebuilt themes from other people.&lt;&#x2F;p&gt;
&lt;p&gt;All responsive webdesign really means is that everything is defined relative to the display dimensions so that its always legible. Mobile first means that it prioritizes and is developed for use on phones, with the larger displays largely derived from the mobile design.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;layout-classes&quot;&gt;Layout classes&lt;&#x2F;h2&gt;
&lt;p&gt;At its core Bootstrap is a resonsive, mobile first framework. We use container classes that embed behavior and relations between content blocks. For example having a top bar above a column layout.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;containers&quot;&gt;containers&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;container&quot;&gt;&lt;code&gt;.container&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;is a fixed width container meaning it sticks to a set dimension.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;container-fluid&quot;&gt;&lt;code&gt;.container-fluid&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;is full width meaning it expands to fill the space its given.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-grid&quot;&gt;the grid&lt;&#x2F;h3&gt;
&lt;p&gt;Bootstrap is built around a 12 column grid system. These columns can then be merged to make larger cells, they dont have to be evenly divided.
to divide the grid we do&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;row&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;col-x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;col-y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;col-z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;x&lt;&#x2F;code&gt;, &lt;code&gt;y&lt;&#x2F;code&gt;, &lt;code&gt;z&lt;&#x2F;code&gt; add up to 12. Note that we can have up to 12 columns and arbitrary rows.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;widgets&quot;&gt;widgets&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;icons&quot;&gt;icons&lt;&#x2F;h3&gt;
&lt;p&gt;theres a lot of icons and glyphs built into bootstrap. most of them are accessible via &lt;code&gt;glyphicon-&amp;lt;glyph&amp;gt;&lt;&#x2F;code&gt; applied to an empty span or other object.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dropdowns&quot;&gt;dropdowns&lt;&#x2F;h3&gt;
&lt;p&gt;Bootstrap also has dropdowns and stuff prebuilt using a combination of js functions and css.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dropdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;button&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;btn btn-primary dropdown-toggle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;button&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; data-toggle&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dropdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Dropdown Example&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;caret&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;button&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dropdown-menu&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;HTML&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;CSS&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;JavaScript&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;buttons&quot;&gt;buttons&lt;&#x2F;h3&gt;
&lt;p&gt;We have &lt;code&gt;.btn&lt;&#x2F;code&gt; as our basic and stuff like &lt;code&gt;.btn-success&lt;&#x2F;code&gt; and &lt;code&gt;btn-danger&lt;&#x2F;code&gt; as extensions. We can modify the button with &lt;code&gt;btn-block&lt;&#x2F;code&gt; and &lt;code&gt;active&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;disabled&lt;&#x2F;code&gt; and &lt;code&gt;btn-lg&#x2F;sm&#x2F;xs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tables&quot;&gt;tables&lt;&#x2F;h3&gt;
&lt;p&gt;HTML already comes with markup for tables but bootstrap comes with extra classes to define table styles and behavior. &lt;code&gt;.table&lt;&#x2F;code&gt; is the base class and some of the extensions are &lt;code&gt;table-striped&lt;&#x2F;code&gt; and &lt;code&gt;table-compact&lt;&#x2F;code&gt;. The tables also have highlighting classes like &lt;code&gt;.success&lt;&#x2F;code&gt;, &lt;code&gt;.danger&lt;&#x2F;code&gt; etc.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;forms&quot;&gt;forms&lt;&#x2F;h3&gt;
&lt;p&gt;There’s not really much to say in terms of styling but we have classes that control layout &lt;code&gt;form-inline&lt;&#x2F;code&gt; and vertical is the default. We can build nicer inputs using input groups.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;form&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;form-inline&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;input-group&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;input-group-addon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;glyphicon glyphicon-user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;form-control&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;form&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;styling-classes&quot;&gt;styling classes&lt;&#x2F;h2&gt;
&lt;p&gt;Bootstrap implements all of htmls semantic markup as well as extending it with additional classes largely geared towards alerting the user and communicating status alerts.&lt;&#x2F;p&gt;
&lt;p&gt;some notable examples are&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;html&lt;&#x2F;th&gt;&lt;th&gt;description&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;mark&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;highlights cenclosed text&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;kbd&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;highlights and uses monowidth fonts, meant to be used to diplay hotkeys&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;code&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;monowidth font with background and color change, used for code snippets&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;blockquote&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;pre&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;verbatim environment&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;.text-muted&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;greyed out text&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;.text-success&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;green text for success messages&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;.text-danger&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;red text for errors etc&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;.bg-danger&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;red background&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;js-tools&quot;&gt;js tools&lt;&#x2F;h2&gt;
&lt;h1 id=&quot;python-knowledge&quot;&gt;python knowledge&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;decorators&quot;&gt;decorators&lt;&#x2F;h2&gt;
&lt;p&gt;Decorators are synctactic sugar on wrapper functions. If you write a function &lt;code&gt;wrap:func -&amp;gt; func&lt;&#x2F;code&gt; that takes a function as an argument and returns a function that does some stuff, then calls the argument function, then does some stuff, then it can be used as a decorator.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; wrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; wrapped&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preamble&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        f&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;postamble&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;wrapped&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; wrapped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;amble&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;prints: preamble &#x2F;&#x2F; amble &#x2F;&#x2F; postamble as expected&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;returns &amp;quot;wrapped&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;mysqlconnector&quot;&gt;mysqlconnector&lt;&#x2F;h2&gt;
&lt;p&gt;all you really need to know is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; mysql&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connector&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cursor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cursor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cursor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sql query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cursor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cursor&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fetchall&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;connection&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>a constraints lead approach to coding</title>
        <published>2024-11-23T00:00:00+00:00</published>
        <updated>2024-11-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/cla-coding/"/>
        <id>https://skylosblog.com/posts/cla-coding/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/cla-coding/">&lt;p&gt;I stumbled across the phrases environmental dynamics and Constraint Lead Approach earlier this week in the context of teaching grappling and self defense skills via play. The idea seemed interesting and so after reading up on it I want to consider what it would mean to adapt the same philosophy to teaching non-motor skills like programming.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-environmental-dynamics-constraints-lead-approach&quot;&gt;What is Environmental Dynamics &#x2F; Constraints Lead Approach&lt;&#x2F;h1&gt;
&lt;p&gt;CLA is a pedagogical philosophy that seems to exist almost entirely in the realm of athletic coaching. The essential idea is that rather than lecturing students about how they should move their body or observing their play and providing verbal feedback and instruction, a coach should engineer or constrain the “environment” of a player to encourage exploration and learning. In &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adaptivemovement.net&#x2F;blog&#x2F;brief-introduction-to-the-constraints-led-approach&#x2F;&quot;&gt;this article&lt;&#x2F;a&gt; we’re given the example of, instead of explaining to baseball players how to position their bodies, or where to hit the ball, put a wall in front of them that they must hit the ball over. The athletes body then enters an exploratory space in this newly constrained environment and automatically learns how to hit the ball so it clears the obstacle. In short: we need to de-emphasize procedural education and create opportunities for experiential learning.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-could-we-apply-this-to-in-coding-education&quot;&gt;What could we apply this to in coding education?&lt;&#x2F;h1&gt;
&lt;p&gt;Many newcomers to the world of programming get studk in a local minima where, having overcome the initial frustration of learning to interact with a new computer system, will only engage with their limited knowledge area in order to achieve their goals. An example I see in many classes is students avoiding the effort of learning how to use loops in favor of repeating the same few instructions as many times as they need. As their teacher I can instruct them as to how loops work and even demonstrate their usefulness, but if the challenge I give them accepts any program that ends in the desired state most won’t bother shifting their approach. But, what if I gave them a code budget that made over redundant solutions impossible?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-possible-constraints&quot;&gt;Some possible constraints&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;limited lines&#x2F;characters&#x2F;blocks&lt;&#x2F;li&gt;
&lt;li&gt;limited nesting (you can only have 1 layer of ifs)&lt;&#x2F;li&gt;
&lt;li&gt;remove a piece of syntax (solve this without using explicit conditionals)&lt;&#x2F;li&gt;
&lt;li&gt;solutions must take less than x milliseconds&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;a-wrench-in-the-works&quot;&gt;A wrench in the works&lt;&#x2F;h1&gt;
&lt;p&gt;the CLA methodology assumes that being able to explore the solutionspace is automatic. In the world of sports you don’t need to look up how to move your legs, you just move them, and adjust their movement without conscious effort. Disciplines that have very little to do with motor skills usually don’t have that same ability. For example if I don’t know Rust and am told to make a hello world program I’m not very likely to guess my way to&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello, world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;in anything close to an efficient timeline.&lt;&#x2F;p&gt;
&lt;p&gt;But, if I’m already fluent in Rust, in terms of having a strong grasp of the syntax, keywords, and standard library, I can then learn how to apply that language in the most efficient manner.&lt;&#x2F;p&gt;
&lt;p&gt;At the moment this isn’t a fully fleshed out thought but I think it could be interesting. Perhaps best paired with a web tool that lets an educator push puzzles and restrictions to students’ IDEs to externalize the constraint and reduce verbal explanation time.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>We&#x27;re back!</title>
        <published>2024-11-02T00:00:00+00:00</published>
        <updated>2024-11-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/welcome-back/"/>
        <id>https://skylosblog.com/posts/welcome-back/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/welcome-back/">&lt;p&gt;Hello! Hello!
You might have noticed this site didn’t update for almost a year, that’s because I lost the entire Zola directory and it wasn’t backed up in a non-compiled state anywhere. Thanks to BeautifulSoup I’ve just finished decompiling all the pages back to markdown and I’ve recreated the site in Zola too. You might notice things look a little different –I’m using a newer version of the same theme as before, and the decompilation may have left artifacts which hopefully I can solve as they come up.
but for now here’s a quick little list of some stuff I’ve done:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;got way better at archery&lt;&#x2F;li&gt;
&lt;li&gt;taught some kids scratch and python&lt;&#x2F;li&gt;
&lt;li&gt;built a lambda calculus compiler study in python&lt;&#x2F;li&gt;
&lt;li&gt;built a compiler from a sort of Logo-like language to python for Edison Robots&lt;&#x2F;li&gt;
&lt;li&gt;built out a nicer demo page for the beat maker&lt;&#x2F;li&gt;
&lt;li&gt;a static site generator built in bash (I think this is before the site was lost, but I never published the post about it)&lt;&#x2F;li&gt;
&lt;li&gt;I made large scale collography project&lt;&#x2F;li&gt;
&lt;li&gt;I made some metal hairpins&lt;&#x2F;li&gt;
&lt;li&gt;played a lot of petanque&lt;&#x2F;li&gt;
&lt;li&gt;watched all of evangelion and the reboot&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>peglib quick ref</title>
        <published>2024-01-18T00:00:00+00:00</published>
        <updated>2024-01-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/peglib-quick-ref/"/>
        <id>https://skylosblog.com/posts/peglib-quick-ref/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/peglib-quick-ref/">&lt;p&gt;these are some quick notes for my own reference of the  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yhirose&#x2F;cpp-peglib&quot;&gt;peglib&lt;&#x2F;a&gt;  readme&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;PEG uses both  &lt;code&gt;&#x2F;&lt;&#x2F;code&gt;  and  &lt;code&gt;|&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;A&#x2F;B&lt;&#x2F;code&gt;  indicates a prioritized choice, meaning  &lt;code&gt;A&lt;&#x2F;code&gt;  takes precedence over  &lt;code&gt;B&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;|&lt;&#x2F;code&gt;  is only used as a delimiter between terminal character strings&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&quot;&lt;&#x2F;code&gt; , &lt;code&gt;&#x27;&lt;&#x2F;code&gt; , ```  are used to encase literals&lt;&#x2F;li&gt;
&lt;li&gt;the  &lt;code&gt;?&lt;&#x2F;code&gt; ,  &lt;code&gt;*&lt;&#x2F;code&gt; ,  &lt;code&gt;+&lt;&#x2F;code&gt;  operators exist and consume maximally&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;.&lt;&#x2F;code&gt;  is a wild card&lt;&#x2F;li&gt;
&lt;li&gt;character classes are denoted by  &lt;code&gt;[]&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; ,  &lt;code&gt;!&lt;&#x2F;code&gt;  are syntactic predicates,  &lt;code&gt;&amp;amp;A&lt;&#x2F;code&gt;  consumes a character if pattern  &lt;code&gt;A&lt;&#x2F;code&gt;  is matchable,  &lt;code&gt;!A&lt;&#x2F;code&gt;  consumes if pattern  &lt;code&gt;A&lt;&#x2F;code&gt;  isn’t matchable.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;()&lt;&#x2F;code&gt;  can be used as embedded options. i.e  &lt;code&gt;(A&#x2F;B)C&lt;&#x2F;code&gt;  matches  &lt;code&gt;A C&lt;&#x2F;code&gt;  and  &lt;code&gt;B C&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&amp;gt;&lt;&#x2F;code&gt;  is used to denote token boundaries, for example if you want to use multiple regexp tokens.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;using-the-library&quot;&gt;using the library&lt;&#x2F;h1&gt;
&lt;p&gt;there is a parser type that takes in a grammar string for its constructor &lt;code&gt;R&quot;(...)&quot;&lt;&#x2F;code&gt;  every rule consists of a line of the form  &lt;code&gt;foo &amp;lt;- bar&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;then for every variable in the grammar you can set up a lambda&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; variable &amp;lt;- A \ B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;variable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SemanticValues&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; vs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    switch&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;vs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;choice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the first match, A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        default&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;you-can-set-up-an-error-handler-with&quot;&gt;you can set up an error handler with&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;set_logger&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;size_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; line&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; col&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; msg&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rule&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;it will then be called when parsing fails. You can set a specific error message by adding  &lt;code&gt;{error_msg &quot;foo&quot;}&lt;&#x2F;code&gt;  after a rule. error messages have the  &lt;code&gt;%t&lt;&#x2F;code&gt;  and  &lt;code&gt;%c&lt;&#x2F;code&gt;  placeholders for tokens and characters that the parser fails on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-make-an-ast&quot;&gt;to make an ast&lt;&#x2F;h2&gt;
&lt;p&gt;use&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;enable_ast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;shared_ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;peg&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;Ast&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ast&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;text&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ast&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is also a  &lt;code&gt;ast_to_s(ast)&lt;&#x2F;code&gt;  method. By default the ast includes every variable the parser goes through in generating the provided source code. To make the tree more minimal we can use  &lt;code&gt;parser.optimize_ast(ast)&lt;&#x2F;code&gt;  and we can flag certain variable in our grammar not to be optimized out using a  &lt;code&gt;{no_ast_opt}&lt;&#x2F;code&gt;  flag.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-ast&quot;&gt;using the AST&lt;&#x2F;h2&gt;
&lt;p&gt;each ast node has the following members:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;string path&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; line &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; column &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;string name&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;size_t&lt;&#x2F;span&gt;&lt;span&gt; position&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;size_t&lt;&#x2F;span&gt;&lt;span&gt; length&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; choice_count&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; choice&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;string original_name&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; original_choice_count&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span&gt; original_choice&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; tag&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; original_tag&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; is_token&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;string_view token&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;shared_ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;AstBase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Annotation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; nodes&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span&gt;weak_ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;AstBase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Annotation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; parent&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; token_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; const&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;assert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;is_token&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;token&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; token_to_number&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; const&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; token_to_number_&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;token&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using Dyalog APL outside of RIDE</title>
        <published>2023-12-04T00:00:00+00:00</published>
        <updated>2023-12-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/apl-in-vscode/"/>
        <id>https://skylosblog.com/posts/apl-in-vscode/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/apl-in-vscode/">&lt;p&gt;I decided I was going to participate in this year’s advent of code,  &lt;em&gt;and&lt;&#x2F;em&gt;  I decided I wanted to do it with APL. Now I already have Dyalog RIDE installed but I don’t want to create a new workspace for every problem so instead decided I would take advantage of the dyalogScript feature to write small executables in order to solve each problem. Now, VScode does have language support extensions for APL, including a language server client. However, I ran into some problems getting the language server running so instead I decided it would be easier to download an APL keyboard and run each executable from the command line.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;install-the-keyboard&quot;&gt;install the keyboard&lt;&#x2F;h1&gt;
&lt;p&gt;Go  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dyalog.com&#x2F;apl-font-keyboard.htm&quot;&gt;here&lt;&#x2F;a&gt;  to download the keyboard. (for macos click the flag associated with your keyboard ie american layout) then go  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dfns.dyalog.com&#x2F;n_keyboards.htm&quot;&gt;here&lt;&#x2F;a&gt;  to view the layout. Press  &lt;code&gt;alt&lt;&#x2F;code&gt;  to use the apl unicode keybinds.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-basic-example&quot;&gt;a basic example&lt;&#x2F;h1&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;apl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;#!&#x2F;usr&#x2F;local&#x2F;bin&#x2F;dyalogscript&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;←&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;⎕&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;⎕&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;←&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;∊&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;what-to-know-about-shell-scripts&quot;&gt;what to know about shell scripts&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;⎕←val&lt;&#x2F;code&gt;  outputs to stdout&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⍞←val&lt;&#x2F;code&gt;  outputs to stderr&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;val←⎕&lt;&#x2F;code&gt;  evaluates stdin as apl code, thus strings must be ‘quoted’ or they will be used as names&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;val←⍞&lt;&#x2F;code&gt;  pulls from stdin as a string&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As far as I can tell, you cannot give a dyalogscript arguments like you would another script. However, you can pipe them in and your first read of stdin will receive whatever was piped in. If you try to read an argument this way it will simply ignore it and wait for user input.&lt;&#x2F;p&gt;
&lt;p&gt;if we really want to we can always use a bash wrapper&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; .&#x2F;foo.apl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There might be a system command to get something like argv but I looked over the release notes and language reference and didn’t notice it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>an extended beatmaker</title>
        <published>2023-10-31T00:00:00+00:00</published>
        <updated>2023-10-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/extended-beatmaker/"/>
        <id>https://skylosblog.com/posts/extended-beatmaker/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/extended-beatmaker/">&lt;h1 id=&quot;the-beatmaker&quot;&gt;the beatmaker&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;,&lt;&#x2F;code&gt;  light beat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;.&lt;&#x2F;code&gt;  heavy beat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:&lt;&#x2F;code&gt;  cha-cha beat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt;  rest&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;*comment*&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;variable_name=beats;&lt;&#x2F;code&gt;  for example  &lt;code&gt;foo=,:,:..,:&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[variable_name]&lt;&#x2F;code&gt;  to reference it in a beat&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;input autocomplete=&quot;off&quot; id=&quot;beat_code&quot; type=&quot;text&quot; value=&quot;A=[,,,.]B=[,,?.]2[A]:,:.2[B]&quot;&#x2F;&gt;    
 &lt;button id=&quot;play_pause&quot; onclick=&quot;toggle()&quot;&gt;play! 🔁&lt;&#x2F;button&gt; 
 &lt;input id=&quot;bpm_slider&quot; max=&quot;800&quot; min=&quot;20&quot; type=&quot;range&quot; value=&quot;120&quot;&#x2F;&gt; 
 &lt;label for=&quot;bpm&quot; id=&quot;bpm_label&quot; style=&quot;&quot;&gt;120 BPM&lt;&#x2F;label&gt;
&lt;div style=&quot;margin-bottom: 6cm&quot;&gt;&lt;&#x2F;div&gt;
&lt;script src=&quot;https:&#x2F;&#x2F;unpkg.com&#x2F;tone&quot;&gt;&lt;&#x2F;script&gt;
&lt;script src=&quot;tokenise.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;script src=&quot;parsetree.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;script src=&quot;execution.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;script src=&quot;interface.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;h1 id=&quot;development-intro-and-goals&quot;&gt;development intro and goals&lt;&#x2F;h1&gt;
&lt;p&gt;I started improving my earlier beatmaker design to include rests and allow for variable reference and quickly ended up doing another post’s worth of work. So here it is in another post.&lt;&#x2F;p&gt;
&lt;p&gt;my main goals were to add a rest beat, and to add variables nd loops to enable more complex rhythms.&lt;&#x2F;p&gt;
&lt;p&gt;you can also check this project out on  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;P-skylos&#x2F;js-beat-tester&quot;&gt;github&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;notes&quot;&gt;notes&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;adding-a-rest&quot;&gt;adding a rest&lt;&#x2F;h2&gt;
&lt;p&gt;This is actually what started everything. Unfortunately I can’t just “play” a silent note. Tone.js doesn’t allow notes of 0Hz, 0 velocity, or 0 duration. Gain is an envelope applied to the whole instrument and so would be annoying to trigger.&lt;&#x2F;p&gt;
&lt;p&gt;Instead we use a different part of the Tone.js toolkit to manually schedule notes rather than automatically, thus we can simply delay the note after the rest. Works great, but I had to change my implementation to a case statement from a lookup table.&lt;&#x2F;p&gt;
&lt;p&gt;OH WAIT! what if its a trailing rest? now what note’s gonna get extended? (trailing rests are still “played” since they should delay when the next loop of the beat starts) well thankfully, Tone.js lets us push back the end of the loop. But now we need to know when we’re a trailing rest.
So now we have a big switch block thats peeking at the next letter in the code to see if we’re at the end. Well, this is nearly like the parsers i made in college, so lets just make one since we’ve done so much of it already, that way we can have variables and stuff too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;designing-the-parse&quot;&gt;designing the parse&lt;&#x2F;h2&gt;
&lt;p&gt;I ended up going with a simple recursive descent parser since its what I’m familiar with and this project has set on the shelf long enough. There weren’t any notable challenges in its creation. except for the fact that currently self reference causes infinite recursion. To fix it I decided to crawl each assignment and expand any lookups to their value such that, internally, there are no lookups inside an assignment. I wouldn’t describe this as necessarily the most elegant option but it lets me get this project out the door quickly and out of my head, while still allowing a pleasing amount of flexibility.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>rough bash notes</title>
        <published>2023-10-16T00:00:00+00:00</published>
        <updated>2023-10-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/bash-notes/"/>
        <id>https://skylosblog.com/posts/bash-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/bash-notes/">&lt;p&gt;Bash is a shell with a scripting language that allows you to do things like concatenating commands. to make a script write your bash commands in a file. the first line of the file must contain a shebang:  &lt;code&gt;#!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;code&gt;  which tells the shell how to run the file.&lt;&#x2F;p&gt;
&lt;p&gt;This article uses primarily the  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;bash.html&quot;&gt;gnu bash manual&lt;&#x2F;a&gt;  and the  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learnxinyminutes.com&#x2F;docs&#x2F;bash&#x2F;&quot;&gt;x in y minutes guide&lt;&#x2F;a&gt;  as sources and is meant to be an approximate overview.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;streams&quot;&gt;streams&lt;&#x2F;h1&gt;
&lt;p&gt;bash has three standard streams: stdin, stdout, and stderr. stdin is naturally where what the user types to console goes. stderr and stdout often both write to console. stdout is represented as the number 1 in certain cases and stderr as 2.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;variables&quot;&gt;variables&lt;&#x2F;h1&gt;
&lt;p&gt;variable assignment looks like  &lt;code&gt;name=&quot;value&quot;&lt;&#x2F;code&gt;  but crucially cannot have spaces or bash will interpret the name as a command.&lt;&#x2F;p&gt;
&lt;p&gt;to dereference a variable and use its value write it as  &lt;code&gt;&quot;$name&quot;&lt;&#x2F;code&gt;  it must use double quotes and  &lt;em&gt;not&lt;&#x2F;em&gt;  single quotes, omitting the quotes is technically possible but not recommended.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;arrays&quot;&gt;arrays&lt;&#x2F;h1&gt;
&lt;p&gt;you create an array much like a variable&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and index into it like you expect  &lt;code&gt;array[0]&lt;&#x2F;code&gt;  but you can also return the whole array  &lt;code&gt;array[@]&lt;&#x2F;code&gt;  and index into a range of that array  &lt;code&gt;array[@]:0:2&lt;&#x2F;code&gt; . You can also get the length of an array with  &lt;code&gt;#array[@]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;arithmetic&quot;&gt;arithmetic&lt;&#x2F;h1&gt;
&lt;p&gt;check out  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;bash.html#Shell-Arithmetic&quot;&gt;the gnu manual&lt;&#x2F;a&gt;  for a full breakdown. I will just say its mostly what you expect. I will note that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;**&lt;&#x2F;code&gt;  is power&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&amp;gt; &amp;lt;&amp;lt;&lt;&#x2F;code&gt;  are bitwise shifts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;| &amp;amp;&lt;&#x2F;code&gt;  are bitwise OR and AND while  &lt;code&gt;|| &amp;amp;&amp;amp;&lt;&#x2F;code&gt;  are logical&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;^&lt;&#x2F;code&gt;  is XOR&lt;&#x2F;li&gt;
&lt;li&gt;there is a ternary operator:  &lt;code&gt;condition?expr:expr&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;~=&lt;&#x2F;code&gt;  lets you check a string against a regex&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;expansion&quot;&gt;expansion&lt;&#x2F;h1&gt;
&lt;p&gt;Is the process by which a pattern is expanded out into all the words it describes. (for example a regular expression expanded into the language it describes). See  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;bash.html#Shell-Expansions&quot;&gt;the gnu manual on expansion&lt;&#x2F;a&gt; .&lt;&#x2F;p&gt;
&lt;h2 id=&quot;command-substitution&quot;&gt;command substitution&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;commands&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Command substitution allows a command to be treated as its output. In other words you can execute a command in place and use its data as if it were a dereferenced variable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parameter-expansion&quot;&gt;parameter expansion&lt;&#x2F;h2&gt;
&lt;p&gt;parameter expansion lets you modify a command’s argument on the fly, as well as indirection, for instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;indirect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; hey world&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;indirect&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; hello world&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:-&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;default&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;# default value if var is missing or empty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;brace-expansion&quot;&gt;brace expansion&lt;&#x2F;h2&gt;
&lt;p&gt;Brace expansion is used to generate ranges of characters and numbers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{1..5} #=&amp;gt; 1 2 3 4 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{a..e} #=&amp;gt; a b c d e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you cannot use variables inside the brace expansion.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;built-in-and-environment-variables&quot;&gt;built in and environment variables&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$?&lt;&#x2F;code&gt;  is the last program’s return variable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$$&lt;&#x2F;code&gt;  is the script’s PID&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$#&lt;&#x2F;code&gt;  number of arguments&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$@&lt;&#x2F;code&gt;  all arguments passed to the script&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$1, $2 ...&lt;&#x2F;code&gt;  are the numbered arguments&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$PWD&lt;&#x2F;code&gt;  is the working directory as a variable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$USER&lt;&#x2F;code&gt; current user’s name&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$PATH&lt;&#x2F;code&gt;  is a list of paths the shell will search for command executables&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-&lt;&#x2F;code&gt;  is the previous working directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;..&lt;&#x2F;code&gt;  is the parent directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;.&lt;&#x2F;code&gt;  is the current directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;~&lt;&#x2F;code&gt;  is the home directory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;pipelines&quot;&gt;pipelines&lt;&#x2F;h1&gt;
&lt;p&gt;The  &lt;code&gt;|&lt;&#x2F;code&gt;  character is called a  &lt;strong&gt;pipe&lt;&#x2F;strong&gt;  and directs the output of its left hand command into the input of the right hand command.  &lt;code&gt;|&amp;amp;&lt;&#x2F;code&gt;  is another type of pipe that also connects the left hand error to the right hand input. A series of commands connected by pipes is called a  &lt;strong&gt;pipeline&lt;&#x2F;strong&gt; .&lt;&#x2F;p&gt;
&lt;h1 id=&quot;redirection&quot;&gt;redirection&lt;&#x2F;h1&gt;
&lt;p&gt;Redirects are similar to pipes but instead of hooking output into input, it hooks a file or stream into a command’s input or output.  &lt;code&gt;&amp;gt; file&lt;&#x2F;code&gt;  allows an output to be written to a file, and  &lt;code&gt;&amp;lt; file&lt;&#x2F;code&gt;  allows a file to be used as input.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt;  and  &lt;code&gt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt;  do the same but append rather than overwrite.&lt;&#x2F;p&gt;
&lt;p&gt;see more details at  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;bash.html#Redirections&quot;&gt;the gnu manual&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;lists&quot;&gt;lists&lt;&#x2F;h1&gt;
&lt;p&gt;Lists are series of commands or pipelines connected together by list operators.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;||&lt;&#x2F;code&gt;  is the OR operator. It will execute its LHS and then execute its RHS if the LHS has a non-zero exit status (the command failed).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;  is the AND operator. It will execute its LHS and then execute its RHS if the LHS exited with a zero exit status (the command succeeded).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;;&lt;&#x2F;code&gt;  is the sequence operator. It will run the LHS then the RHS regardless of exit status, it can be replaced with a newline.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;&lt;&#x2F;code&gt;  is like  &lt;code&gt;;&lt;&#x2F;code&gt;  by executes the LHS in an asynchronous shell&lt;&#x2F;p&gt;
&lt;h1 id=&quot;process-substitution&quot;&gt;process substitution&lt;&#x2F;h1&gt;
&lt;p&gt;Process substitution allows you to treat the input or output of a process as a file name while running the process asynchronously.  &lt;code&gt;&amp;gt;(list)&lt;&#x2F;code&gt;  allows you to write to the input as a file.  &lt;code&gt;&amp;lt;(list)&lt;&#x2F;code&gt;  allows you to read the output of list as a file. there cannot be a space between the angle bracket and the left paren.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;compound-commands&quot;&gt;compound commands&lt;&#x2F;h1&gt;
&lt;p&gt;These are code blocks that can hold multiple commands. Each compound command is begun and terminated by a reserved word or character.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looping-commands&quot;&gt;looping commands&lt;&#x2F;h2&gt;
&lt;p&gt;Bash has three loops: until, while, for.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;until&quot;&gt;until&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;until&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;condition command&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The until loop goes until the condition command has zero exit status. The block inherits the status of its last executed command or zero if no commands were executed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;while&quot;&gt;while&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;while&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;condition command&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The While loop goes until the condition command has a non-zero exit status. The exit status of the block is the status of the last run command of the do block or zero if no commands were run.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;for&quot;&gt;for&lt;&#x2F;h3&gt;
&lt;p&gt;for loops have two forms:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;iterator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; ((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;named variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; in &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;note that the array here can also be an expansion&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conditional-commands&quot;&gt;conditional commands&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;arithmetic-commands&quot;&gt;arithmetic commands&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;((arithmetic expression))&lt;&#x2F;code&gt;
evaluates the math and gives an exit status of zero if the arithmetic expression evaluates to a non-zero value and zero otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;[[conditional expression]]&lt;&#x2F;code&gt;
evaluates a conditional expression and returns a 0 or 1 based on the result(0 is true and 1 is false).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;if&quot;&gt;if&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;condition command&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;elif&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;condition&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that  &lt;code&gt;elif&lt;&#x2F;code&gt;  and  &lt;code&gt;else&lt;&#x2F;code&gt;  are optional.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;case&quot;&gt;case&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;case&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    pattern3&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;default&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; comman&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;esac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;patterns can be regular expressions, or numbers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;select&quot;&gt;select&lt;&#x2F;h3&gt;
&lt;p&gt;Select is useful for creating menus. It prints all the options with in the given list with numbers to std err and waits for a number over std in. it then runs that commands and loops until a break command is selected&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;select&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;lt;name&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; in &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;see  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;bash.html#Conditional-Constructs&quot;&gt;the gnu manual on conditional commands&lt;&#x2F;a&gt;  for more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;groups&quot;&gt;groups&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;(list)&lt;&#x2F;code&gt;  causes all the listed commands to be executed in a subshell.
&lt;code&gt;{list;}&lt;&#x2F;code&gt;  executes the listed commands without a subshell. the trailing semicolon is required.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;functions&quot;&gt;functions&lt;&#x2F;h1&gt;
&lt;p&gt;define a function with&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; exit_status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;return is not required&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;or&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;note that in this case () is optional&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; exit_status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we don’t actually put arguments in the parentheses since we refer to them with  &lt;code&gt;$1 $2&lt;&#x2F;code&gt;  etc&lt;&#x2F;p&gt;
&lt;p&gt;to call a function we simply write its name and any arguments&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; arg1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; arg2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;functions are scoped and have access to their parent scopes. However, local variables must be declared with the  &lt;code&gt;local&lt;&#x2F;code&gt;  keyword like so&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;baz&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func1&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    local&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; var1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; bar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    func2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; bar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt; foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func3&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; var2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;func4&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    func3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;var2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;=&amp;gt;bat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;some-commands-utils&quot;&gt;some commands&#x2F;utils&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cd path&lt;&#x2F;code&gt;  changes your working directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;&#x2F;code&gt;  lists the directories in the working directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;touch name&lt;&#x2F;code&gt;  creates a new file with name&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mkdir name&lt;&#x2F;code&gt;  creates a new directory with name&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mv path1 path2&lt;&#x2F;code&gt;  moves the file at path1 to path2&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cp&lt;&#x2F;code&gt;  same as move but doesn’t delete the original&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pwd&lt;&#x2F;code&gt;  prints working directory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;echo&lt;&#x2F;code&gt;  prints its argument&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;&#x2F;code&gt;  allows you to search using pattern matching&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;sed&lt;&#x2F;code&gt;  allows you to match with pattern matching&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;uniq&lt;&#x2F;code&gt;  allows you to omit repeated lines&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;head&lt;&#x2F;code&gt;  and  &lt;code&gt;tail&lt;&#x2F;code&gt;  allows you to cat the first or last n lines of a file&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cut&lt;&#x2F;code&gt;  prints a column of text from a file limited by a given delimiter.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;jobs&lt;&#x2F;code&gt;  shows all running async jobs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cat path&lt;&#x2F;code&gt;  prints file to console&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;read var&lt;&#x2F;code&gt;  lets you read user input and store it in a variable&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;alias&lt;&#x2F;code&gt;  lets you name a specific command e.g  &lt;code&gt;alias hi=echo &quot;hey&quot;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;trap&lt;&#x2F;code&gt;  allows you to execute a command on a given signal&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;you can end processes with  &lt;code&gt;ctrl+c&lt;&#x2F;code&gt;  and pause them with  &lt;code&gt;ctrl+z&lt;&#x2F;code&gt; .  &lt;code&gt;ctrl+d&lt;&#x2F;code&gt;  sends an EOF token.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>how to git, rough notes</title>
        <published>2023-10-16T00:00:00+00:00</published>
        <updated>2026-03-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/git-notes/"/>
        <id>https://skylosblog.com/posts/git-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/git-notes/">&lt;p&gt;Git is a history and versioning tool used for storing and examining the history of a collection of files. It should be noted that git, is not github. You can use it to view and update project histories. When viewing a history it will update your local directory to match.&lt;&#x2F;p&gt;
&lt;p&gt;This article is primarily a compressed version of the  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;user-manual.html&quot;&gt;git user manual&lt;&#x2F;a&gt;  and the  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&quot;&gt;git reference&lt;&#x2F;a&gt; .&lt;&#x2F;p&gt;
&lt;h1 id=&quot;vocabulary&quot;&gt;vocabulary&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;a  &lt;strong&gt;repository&lt;&#x2F;strong&gt;  is where all the files for a project live. A git  &lt;em&gt;repository&lt;&#x2F;em&gt;  also tracks change history.&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;commit&lt;&#x2F;strong&gt;  is a (snapshot of a) specific version of the code stored in a  &lt;em&gt;repository&lt;&#x2F;em&gt; .&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;branches&lt;&#x2F;strong&gt;  are different timelines of  &lt;em&gt;commits&lt;&#x2F;em&gt; .&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;head&lt;&#x2F;strong&gt;  is (a pointer to) the latest  &lt;em&gt;commit&lt;&#x2F;em&gt;  on a given  &lt;em&gt;branch&lt;&#x2F;em&gt; .&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;tag&lt;&#x2F;strong&gt;  is a pointer to specific commit.&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;merge&lt;&#x2F;strong&gt;  is when two branches become one.&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;blob&lt;&#x2F;strong&gt;  is the git object that holds file data&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;tree&lt;&#x2F;strong&gt;  is the object that holds directory structure for  &lt;em&gt;blobs&lt;&#x2F;em&gt;  and sub-trees. A  &lt;em&gt;commit&lt;&#x2F;em&gt;  is a snapshot of tree history.&lt;&#x2F;li&gt;
&lt;li&gt;to  &lt;strong&gt;push&lt;&#x2F;strong&gt;  is to update a remote repository you have write authority on with your new commits.&lt;&#x2F;li&gt;
&lt;li&gt;to  &lt;strong&gt;pull&lt;&#x2F;strong&gt;  is to take commits from a remote repository and apply them to your own.&lt;&#x2F;li&gt;
&lt;li&gt;when you use git to view a certain commit we say you’ve  &lt;strong&gt;checked it out&lt;&#x2F;strong&gt;  since git updates your working directory to be a copy of that commit.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;staged&lt;&#x2F;strong&gt;  changes are changes that are marked to be added to your next commit.&lt;&#x2F;li&gt;
&lt;li&gt;the  &lt;strong&gt;index&lt;&#x2F;strong&gt;  how git represents what files are being tracked in your working directory.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;some-git-theory&quot;&gt;Some git theory&lt;&#x2F;h1&gt;
&lt;p&gt;Git is &lt;em&gt;snapshot based&lt;&#x2F;em&gt; not delta based. This means that instead of simply recording changes to individual files, it stores a duplicate of the entire project directory in its change database. It takes these snapshots by hashing each file based on its content. If that hash matches previous hash, it just points to the previous snapshot instead of duplicating the file. If that hash doesn’t match a previous snapshot, it saves a new copy of the file. see the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Getting-Started-What-is-Git%3F&quot;&gt;git manual article on how git works&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are 3 ways of unifying two branches: a fast-forward merge, a 3-way merge, and a rebase. Geeks for geeks has a great article explaining them &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.geeksforgeeks.org&#x2F;git&#x2F;git-merge&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.git-init.com&#x2F;the-magic-of-3-way-merge&#x2F;&quot;&gt;this blog post is a great explanation of three-way merge specifically&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-commands&quot;&gt;some commands&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;commit&quot;&gt;commit&lt;&#x2F;h2&gt;
&lt;p&gt;The commit command is naturally what you use to create a new commit. There are multiple ways of telling the commit command what changes to commit.&lt;&#x2F;p&gt;
&lt;p&gt;If you run  &lt;code&gt;git commit&lt;&#x2F;code&gt;  it will simply commit all changes in the index. You can edit the index using  &lt;code&gt;git add&lt;&#x2F;code&gt;  and  &lt;code&gt;git rm&lt;&#x2F;code&gt; .&lt;&#x2F;p&gt;
&lt;p&gt;If you run  &lt;code&gt;git commit &amp;lt;file1&amp;gt; &amp;lt;file2&amp;gt;...&lt;&#x2F;code&gt;  then it will ignore the index and only commit the listed files.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git commit -a&lt;&#x2F;code&gt;  will automatically  &lt;code&gt;git rm&lt;&#x2F;code&gt;  any files in the index that are removed form the working directory and then do a normal  &lt;code&gt;git commit&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;you can use the  &lt;code&gt;-m &amp;lt;msg&amp;gt;&lt;&#x2F;code&gt;  flag to attach an explanation of your changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;branch&quot;&gt;branch&lt;&#x2F;h2&gt;
&lt;p&gt;Branch is used to create and manage your branches. use  &lt;code&gt;git branch&lt;&#x2F;code&gt;  to list all existing branches.  &lt;code&gt;git branch &amp;lt;name&amp;gt; &amp;lt;opt:start_point&amp;gt;&lt;&#x2F;code&gt;  to create a new branch, optionally naming a previous commit as a start point, rather than the head.  &lt;code&gt;git branch -d &amp;lt;name&amp;gt;&lt;&#x2F;code&gt;  will delete the named branch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;switch&quot;&gt;switch&lt;&#x2F;h2&gt;
&lt;p&gt;Switch is used to check out different branches of your repository.  &lt;code&gt;git switch &amp;lt;branch&amp;gt;&lt;&#x2F;code&gt;  will update your working directory to match that branch. you can also create a new branch using  &lt;code&gt;git switch -c &amp;lt;new branch&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;merge&quot;&gt;merge&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;git merge &amp;lt;branch&amp;gt;&lt;&#x2F;code&gt; is used to join the named branch with the current working branch. It requires that the named branch derived from the working branch. It replays all changes made in the named branch since it diverged from the currently checked out branch onto the checked out branch and then makes a commit of those changes.  &lt;strong&gt;Any uncommitted changes will be lost.&lt;&#x2F;strong&gt;  The commit contains the names of the parent branches and a log message.&lt;&#x2F;p&gt;
&lt;p&gt;If the merge results in conflict  &lt;code&gt;git merge --abort&lt;&#x2F;code&gt;  will attempt to undo the merge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rebase&quot;&gt;rebase&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;git rebase &amp;lt;host branch&amp;gt; &amp;lt;moving branch&amp;gt;&lt;&#x2F;code&gt;  replays all commits in the moving branch onto the host branch’s head. This does not destroy the moving branch, it simply moves its start point to a different commit.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;things-you-may-want-to-do&quot;&gt;things you may want to do&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;make-a-fresh-repository&quot;&gt;make a fresh repository&lt;&#x2F;h2&gt;
&lt;p&gt;run  &lt;code&gt;git init&lt;&#x2F;code&gt;  in the top directory of your project. Make sure all your files are added to your first commit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;track-down-bugs&quot;&gt;track down bugs&lt;&#x2F;h2&gt;
&lt;p&gt;If you know some previous commit worked, but your current head doesn’t you can use  &lt;em&gt;bisect&lt;&#x2F;em&gt;  to slowly figure out what commit is at fault through binary search. Bisect will take you through your commit history 1 commit at a time. You will test every commit and tell git if it is bad or good, until it can figure out which commit started the problem.&lt;&#x2F;p&gt;
&lt;p&gt;For detailed instructions, see  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;user-manual.html#exploring-git-history&quot;&gt;exploring-git-history&lt;&#x2F;a&gt;  in the git user manual.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;look-at-a-different-branch&quot;&gt;look at a different branch&lt;&#x2F;h2&gt;
&lt;p&gt;use  &lt;code&gt;git switch &amp;lt;branch name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;get-a-local-copy-of-a-remote-repository&quot;&gt;get a local copy of a remote repository&lt;&#x2F;h2&gt;
&lt;p&gt;use  &lt;code&gt;git clone &amp;lt;repository&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-your-local-copy-of-a-repository-up-to-date&quot;&gt;keep your local copy of a repository up to date&lt;&#x2F;h2&gt;
&lt;p&gt;use  &lt;code&gt;git fetch&lt;&#x2F;code&gt;  to update all remote tracked branches to the latest version of the remote repository.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;track-changes-to-repositories-other-than-the-one-you-cloned-from&quot;&gt;track changes to repositories other than the one you cloned from&lt;&#x2F;h2&gt;
&lt;p&gt;use  &lt;code&gt;git remote add &amp;lt;name&amp;gt; &amp;lt;url&amp;gt;&lt;&#x2F;code&gt;  to add another repository to your list of tracked repositories. You can later remove a tracked repository with  &lt;code&gt;git remote remove &amp;lt;name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;work-on-something-else-and-come-back&quot;&gt;work on something else and come back&lt;&#x2F;h2&gt;
&lt;p&gt;you can set aside a commit you’re working on by running  &lt;code&gt;git stash push&lt;&#x2F;code&gt;  which will push all your current work into the stash and then revert you back to the most recent commit. When you’re done you can run  &lt;code&gt;git stash pop&lt;&#x2F;code&gt;  to reapply your stashed changes&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>the real detector</title>
        <published>2023-10-13T00:00:00+00:00</published>
        <updated>2023-10-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/real-or-cringe/"/>
        <id>https://skylosblog.com/posts/real-or-cringe/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/real-or-cringe/">&lt;p&gt;a silly lil toy that tells you if something is real or not!&lt;&#x2F;p&gt;
&lt;style&gt;
.verdict_display
{
    font-size:5ex;
    padding:10px;
}
&lt;&#x2F;style&gt;
&lt;div class=&quot;verdict_display&quot;&gt;&lt;&#x2F;div&gt;
&lt;div class=&quot;file_display&quot;&gt;&lt;&#x2F;div&gt;
&lt;div id=&quot;machine_container&quot;&gt;
&lt;form id=&quot;form&quot;&gt;
&lt;input id=&quot;candidate&quot; type=&quot;text&quot;&#x2F;&gt;
&lt;button id=&quot;submit&quot; onclick=&quot;make_analysis(event)&quot;&gt;is it real?&lt;&#x2F;button&gt;
&lt;&#x2F;form&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;verdict_display&quot;&gt;&lt;&#x2F;div&gt;
&lt;script src=&quot;machine.js&quot;&gt;&lt;&#x2F;script&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>the importance of citing sources</title>
        <published>2023-10-13T00:00:00+00:00</published>
        <updated>2023-10-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/search-for-the-sea/"/>
        <id>https://skylosblog.com/posts/search-for-the-sea/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/search-for-the-sea/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;search-for-the-sea&#x2F;original_drowning.png&quot; alt=&quot;the sea is more honest with those willing to drown&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A few years ago I saw this quote online, noticing that it appeared in what I assumed was a chapter heading I was curious to see the rest of the book.
I did not find the rest of the book that year. A cursory google will quickly pull up multiple people attributing it to someone named “Urtiqa Nabi” with some slight variations on spelling. Googling Urtiqa Nabi only yields a couple social media profiles and some more images of the same quote.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;search-for-the-sea&#x2F;reddit_search.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point I thought ok well its not a particularly english name maybe I’m mis-spelling it, maybe the book is a not particularly well known translation. I went to my local library and asked the librarian for help. They were able to use some of their own search tools to attempt a couple different pattern matches without any results, and I decided to let my search sit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;search-for-the-sea&#x2F;the_clue.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Recently I was seized by my curiosity again, with the hope that maybe it would turn out to be a fun sci-fi novel I could dive into or something. I did some more googling, reaching the same dead ends. However, by pure dumb luck I happened to click through to duck duck go’s related images and found one attributed to a different name: JH Hard. As luck would have it, JH Hard  &lt;em&gt;does&lt;&#x2F;em&gt;  have a book out (War, Over Easy). But if we look inside, none of the headings in the table of contents mention anything about the sea. But hey if we go to the start of part 1 there’s our quote! A year and change later we’ve got our source.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;search-for-the-sea&#x2F;image.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now the reason I’m making this post is because of the wild goose chase I had to go down to find the book. Why? because almost no-one that posted a copy of the quote provided an attribution, and those that  &lt;em&gt;did&lt;&#x2F;em&gt;  mostly repeated one person’s lie. Who originated the lie I don’t know.&lt;&#x2F;p&gt;
&lt;p&gt;But the important thing to note is how easy it is to take at first glance what comes up in a quick search and run with it if its not something crucial to whatever it is your doing. If I’m trying to learn how to cook a dish I will find out pretty quickly if I’ve been lied to. But something like a quote source is very easy to lie about and no-ones going to check it unless they happen to really care about finding the source for some reason.&lt;&#x2F;p&gt;
&lt;p&gt;The moral of the story I suppose, is to have an updated idea of which things you believe are likely to be based on misinformation.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>a lil js beat maker</title>
        <published>2023-08-27T00:00:00+00:00</published>
        <updated>2023-08-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/js-pulse/"/>
        <id>https://skylosblog.com/posts/js-pulse/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/js-pulse/">&lt;h1 id=&quot;background&quot;&gt;background&lt;&#x2F;h1&gt;
&lt;p&gt;I was inspired by the contents of  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;astrakanproject.com&#x2F;2013&#x2F;12&#x2F;26&#x2F;a-curious-rhythm-notation&#x2F;&quot;&gt;this blog post&lt;&#x2F;a&gt;  and so to help myself investigate the concept a little more I’ve decided to make a lil beat-maker.
&lt;em&gt;THAT BLOG POST IS THE ONLY DOCUMENTATION FOR THE NOTATION IT DESCRIBES IVE BEEN ABLE TO FIND&lt;&#x2F;em&gt;   &lt;strong&gt;please email me if you know more&lt;&#x2F;strong&gt;  (you can click the lil mail icon for my email address)&lt;&#x2F;p&gt;
&lt;p&gt;My approach is also partially shaped by my experience in folk dancing with my unorthodox instructor. He had some out-there and not entirely true ideas about the history of the dances he taught. But, more importantly, he had an elegantly mechanical way of describing the dances.&lt;&#x2F;p&gt;
&lt;p&gt;dances were split into 4-tuples of actions where each of the elements were performed on the beat. We could then talk about wether these tuples were odd or even by defining even tuples as ones where we end with our weight on the same foot we started with. Our instructor defined a step as a movement that switched which foot was supporting our weight. For example, while a stomp expressed the beat, it kept our weight on the non-stomping foot that was already holding our weight and so didn’t count as a step. This led him to define a hora as a 4-tuple in which one or more of the beats are not steps; with a 3-hora being 3 steps and one non-step and a 2 hora 2 steps and so on. A cha-cha on the other hand is a 4-tuple where one or more of the elements is doubled such that there are two steps in rapid succession for one beat.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-beat-maker&quot;&gt;the beat maker&lt;&#x2F;h1&gt;
&lt;p&gt;input some beat sets to here the pulser play it!
our beat code consists of sets of tokens enclosed where all other characters are ignored.
our meaningful symbols consist of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;,&lt;&#x2F;code&gt;  beat note 1&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;.&lt;&#x2F;code&gt;  beat note 2 for emphasized beats&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:&lt;&#x2F;code&gt;  a cha-cha beat&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt;  an unplayed beat&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;if you change the text you will need to pause and play for changes to take effect. All non-beat characters are ignored.&lt;&#x2F;p&gt;
&lt;input autocomplete=&quot;off&quot; id=&quot;beat_code&quot; type=&quot;text&quot; value=&quot;(,:,:)(.,.,)&quot;&#x2F;&gt;    
 &lt;button id=&quot;play_pause&quot; onclick=&quot;toggle()&quot;&gt;play! 🔁&lt;&#x2F;button&gt; 
 &lt;input id=&quot;bpm&quot; max=&quot;400&quot; min=&quot;50&quot; type=&quot;range&quot; value=&quot;120&quot;&#x2F;&gt; 
 &lt;label for=&quot;bpm&quot; id=&quot;bpm_label&quot; style=&quot;&quot;&gt;120 BPM&lt;&#x2F;label&gt;
&lt;div style=&quot;margin-bottom: 6cm&quot;&gt;&lt;&#x2F;div&gt;
&lt;script src=&quot;https:&#x2F;&#x2F;unpkg.com&#x2F;tone&quot;&gt;&lt;&#x2F;script&gt;
&lt;script src=&quot;pulse.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;h1 id=&quot;some-thoughts-on-making-this-lil-toy&quot;&gt;some thoughts on making this lil toy&lt;&#x2F;h1&gt;
&lt;p&gt;I used Tone.js to do all the sound. Its a little synth tool built on top of Web Audio API.&lt;&#x2F;p&gt;
&lt;p&gt;It’s composed of&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a scheduling clock called the transport&lt;&#x2F;li&gt;
&lt;li&gt;instrument objects&lt;&#x2F;li&gt;
&lt;li&gt;sequence objects&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Sequence objects are provided with an instrument object and an array of notes. When the scheduler emits a start signal the sequence object will use its instrument to play through its array of notes. until the transport emits its pause signal.&lt;&#x2F;p&gt;
&lt;p&gt;I gotta say I wish the documentation was either more verbose or more well indexed bc it was pretty difficult to get a mental map of the api together. Total info-shock trying to learn how to use the tool, particularly since I don’t know anything about music terminology. I only have a partial gross-scale map at the moment. For example, Tone.js implements its one time units which I haven’t found much explanation for in the documentation.&lt;&#x2F;p&gt;
&lt;p&gt;Adding the unplayed beat option was wicked annoying since Tone.js won’t let you take a normal beat and turn some aspect of it down all the way to zero to make it silent.&lt;&#x2F;p&gt;
&lt;p&gt;Instead I had to keep track of time for each note manually and then increment the time by the necessary amount. If you inspect the code you’ll see some bits that feel more bodgy than I’m generally comfortable with. However, I started a version 2 with the goals of being more powerful and well written which I should hopefully have done by end of month.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>quick tips for naturalistic cg renders</title>
        <published>2023-08-17T00:00:00+00:00</published>
        <updated>2023-08-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/blender-realism/"/>
        <id>https://skylosblog.com/posts/blender-realism/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/blender-realism/">&lt;h1 id=&quot;add-imperfections&quot;&gt;add imperfections&lt;&#x2F;h1&gt;
&lt;p&gt;The perfect cube cannot exist in real life. When you open blender the first thing you are greeted with is the perfect cube. Break it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;most-things-in-life-don-t-have-razor-sharp-edges&quot;&gt;most things in life don’t have razor sharp edges&lt;&#x2F;h2&gt;
&lt;p&gt;Add even a slight bevel to everything to help it catch the light in a more natural manner. This is where its useful to have nice geometry. automatic bevelling tools don’t play nice with over-complicated geometry and are more likely to mess up the normals, thus creating lots of weird artifacts if you try to use normal smoothing, if its even able to produce an ok mesh to begin with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;most-things-in-life-aren-t-perfectly-flat-or-smooth&quot;&gt;most things in life aren’t perfectly flat or smooth&lt;&#x2F;h2&gt;
&lt;p&gt;Use a smooth noise texture to slightly muddle a flat surface whether through displacements, or wobbling the normals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;most-things-in-life-are-not-perfectly-one-color&quot;&gt;most things in life are not perfectly one color&lt;&#x2F;h2&gt;
&lt;p&gt;If you have a large object, its usually worth slightly muddling its color either with a texture or by applying some bump to its surface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;most-things-in-life-are-not-uniform&quot;&gt;most things in life are not uniform&lt;&#x2F;h2&gt;
&lt;p&gt;Add rough spots and divets to surfaces. Try to avoid having repeating tiling patterns, the human eye picks up on these really quickly and it makes things look artificial. If you have a bunch of instances of the same object add little random variations so they all look subtley different. Maybe warp each of them by a different amount seeded by their position or object ID, maybe give them each a random color variation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;many-things-are-not-perfectly-opaque-or-transparent&quot;&gt;many things are not perfectly opaque or transparent&lt;&#x2F;h2&gt;
&lt;p&gt;In the blender default BSDF, its often worth taking advantage of the subsurface scattering options to add a little bit of realistic color variation to organic materials like bone or marble. Be sure to consider what the undertone of your material is and what colours of light travel the furthest inside it. By default blender’s subsurface scattering is set up to simulate light travelling through the blood and muscle of your flesh.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;dirty-it-up&quot;&gt;dirty it up&lt;&#x2F;h1&gt;
&lt;p&gt;If you watch moveie-prop makers at work you’ll see that a huge part of their work is adding a realistic patina to otherwise perfect objects. In his build videos  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;YXzxEqdvuIE&quot;&gt;Adam savage&lt;&#x2F;a&gt;  talks a lot about how useful “damage” can be in selling a prop as well as its storytelling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-wear-and-tear&quot;&gt;add wear and tear&lt;&#x2F;h2&gt;
&lt;p&gt;Break edges, add dents fleck off bits of paint to expose the metal underneath all of these little signs of damage work together to give an object heft and a sense of materiality. A wooden plank has splinters and plugged knots. An old fire hydrant has rusted bolts worn corners wear the paint has rubbed off and patches where it’s chipped away. An old glass in a diner has a line of scratches where another glass slots into it and fingerprints from the hand that brought it to the table. If it’s a cold drink, maybe there’s beads of condensation, and a pool of water at the base.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;greeble-it&quot;&gt;greeble it&lt;&#x2F;h2&gt;
&lt;p&gt;While tech products often try and communicate how powerful they are by the sleekness of their housing, an industrial tool might have dozens of wires or hydraulic lines running across its surface rather than a smooth hull. Or maybe a shelf has extra unused mounting points that we can still see. Even when in real life, something probably wouldn’t have so many little surface parts, adding them helps convince the viewer of their authenticity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dress-the-set&quot;&gt;dress the set&lt;&#x2F;h2&gt;
&lt;p&gt;have you ever walked into an empty house? One where the interior is fully finished but it just doesn’t feel lived in? it’s because there’s not enough stuff. There’s too much empty space, too many uninterrupted surfaces. If you have a dining table cover it in magazines and plates and cups. Put posters on empty walls furniture into empty floor space and so on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;put-some-dust-in-there&quot;&gt;put some dust in there&lt;&#x2F;h2&gt;
&lt;p&gt;You can use ambient occlusion to push details and simulate dirt and dust getting stuck in cracks. For large objects you might want to add some textures or decals of water and rust damage like you might see gathering around a ridge in a ship hull or a crack in a concrete wall. Adding dust in the air or small insects can also help ground a viewer in the particularities of a scene’s environment. For example, an abandoned warehouse has dust settled over the floor and any remaining boxes, while the lone adventurer leaves behind footprints and kicks some dust into the air; or maybe you want a misty fishing dock with bits of ocean spray whipping over the end of the pier.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;use-photos&quot;&gt;use photos&lt;&#x2F;h1&gt;
&lt;p&gt;The fastest and cheapest way to add realistic weight and color to a scene is to steal it directly from real life!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;photobash&quot;&gt;photobash!&lt;&#x2F;h2&gt;
&lt;p&gt;Look how often people like  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;user&#x2F;mrdodobird&quot;&gt;Ian Hubert&lt;&#x2F;a&gt;  use photobashing and photoscans to quickly and easily create realistic set dressing for their work. For hero objects you might need to put in a little more work, but, for something that isn’t the focus of a scene, quickly cutting out what you need from a photo, or using a photo to bash out a model, will give you something with enough detail, and of the correct proportions, that most people’s eye will just scan over it without incident.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;use-hdris&quot;&gt;use HDRIs&lt;&#x2F;h2&gt;
&lt;p&gt;Setting up natural looking lighting can be time consuming, and harrowing, AND you still need to build out a realistic background set. Skip all of that with HDRIs, these give you naturalistic global illumination and background detail, for free!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pay-attention-to-size&quot;&gt;pay attention to size&lt;&#x2F;h1&gt;
&lt;p&gt;It can be tempting to just sort of eyeball everything as you go without really paying attention to any of the numbers along the way, but, don’t do that! Use measurements from real life to keep things proportional.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naturalistic-proportion&quot;&gt;naturalistic proportion&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re building a human environment make sure to size things proportional to humans. If a doorway looks a little too narrow or a table too tall a viewer may not consciously notice the problem but they  &lt;em&gt;will&lt;&#x2F;em&gt;  notice that what they’re seeing feels off somehow. In fact many parts of our manufactured environment have standardized sizes and proportions so even a slight deviation might seem weird (you ever go up a stairway with a slightly awkward step height).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naturalistic-scale&quot;&gt;naturalistic scale&lt;&#x2F;h2&gt;
&lt;p&gt;light looks and behaves differently at different scales. A fish tank of tea looks almost black, whereas, a millimeter of tea is almost clear. If your translucent, or transparent, objects aren’t true to real-life scale they might look too dark or too light. If I have a glass cup thats about a meter cubed in dimension, it will look weirdly dark since its walls are much thicker than they would be in real life, and thus scatter and absorb more light than we have been trained to expect of a cup, and thus the cup looks weirdly dark.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;make-it-look-like-a-photo&quot;&gt;make it look like a photo&lt;&#x2F;h1&gt;
&lt;p&gt;Most of the naturalistic images we see are produced through the use of a camera, thus the more we make our renders look like they came from a camera the more realistic they will look.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-depth-of-field&quot;&gt;add depth of field&lt;&#x2F;h2&gt;
&lt;p&gt;Cameras don’t have infinite focal length. In blender you can set a camera’s depth of field to keep a specific object in focus. I like to make it follow an empty that I can then move around however I need.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simulate-camera-flaws&quot;&gt;simulate camera flaws&lt;&#x2F;h2&gt;
&lt;p&gt;While raytracing is more or less based off of how real-life optics works it doesn’t simulate all the visual quirks you’ll see using a camera. For bright lights you’ll need to add back in lens-flares and bloom otherwise they’ll look odd and underwhelming. If you’re capturing something in motion you’ll need to tell your engine to simulate motion blur, or add it in yourself. You may also find yourself needing to simulate light leaks, chromatic aberrations, or vignettes. These sorts of camera imperfections aren’t always needed, but every now and then, they can help ground your point of view, and, sell the image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pay-attention-to-your-focal-length-and-f-stop&quot;&gt;pay attention to your focal length and f-stop&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re taking a closeup shot, you’ll want to simulate macro photography with a very narrow depth of field (think f-stop 2.8 or so) and vice versa for wide shots. Maybe you want a telephoto lense to photograph a building, maybe you want a wide angle lens for a landscape.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;light-it-like-a-photo&quot;&gt;light it like a photo&lt;&#x2F;h2&gt;
&lt;p&gt;Learn how photographers think about lighting. Do you want a hard light or a fill light? what color temperature makes sense to use here? do you need a rim light? how about a fill? The lighting in photographs isn’t exactly “natural” but we’re so used to seeing it that having a render follow its conventions won’t just make it look better, but more real. It’s also worth noting that unlike cg artists, photographers are still limited by physical reality and so we should try our based to replicate those same limitations.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;check-your-color-management&quot;&gt;check your color management&lt;&#x2F;h1&gt;
&lt;p&gt;You might be rendering with too low of a dynamic range or something that skews saturation funny or any other host of things. Digital color is a big complicated field with lots of writing, but all I’m really gonna say is that, if you use Blender, you should probably be using the filmic color transform.
Andrew Price’s  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m9AT7H4GGrA&quot;&gt;video&lt;&#x2F;a&gt;  explains it in more detail.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>some blender renders of weird cups</title>
        <published>2023-08-17T00:00:00+00:00</published>
        <updated>2023-08-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/glass-sketches/"/>
        <id>https://skylosblog.com/posts/glass-sketches/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/glass-sketches/">&lt;p&gt;as mentioned in a previous post I recently visited a design museum in shenzhen and while already in an inspired mood I saw a plate in the gift shop and it kicked off a flight of ideas about exploring the materiality of cups which led me to doing a few quick blender sketches of cups designed to use their thermal mass to keep drinks cold.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;IMG_5889.jpg&quot; alt=&quot;an image of the inspiring plate&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-cylindrical-sketches&quot;&gt;the cylindrical sketches&lt;&#x2F;h1&gt;
&lt;p&gt;given that the plate was round, and cups are usually round it seems only natural to start from a primitive cylinder.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-1&quot;&gt;CL-1&lt;&#x2F;h2&gt;
&lt;p&gt;here we take the obvious first step and have thick walls all around providing a nice heavy layer of insulation all around, albeit at the expensive of being cumbersome and nearly impossible to drink out of.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0001.png&quot; alt=&quot;wide concentric&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-2&quot;&gt;CL-2&lt;&#x2F;h2&gt;
&lt;p&gt;The question thus becomes whats a good way of making the cup usable while still playing with the impression of thickness and mass, why not simply move the hole toward the edge to creat a lip.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0004.png&quot; alt=&quot;wide, hole near edge&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0004.png&quot; alt=&quot;close, hole near edge&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-3&quot;&gt;CL-3&lt;&#x2F;h2&gt;
&lt;p&gt;or put the hole at an angle
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0003.png&quot; alt=&quot;wide, hole is at an angle&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0003.png&quot; alt=&quot;close, hole is at an angle&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-4&quot;&gt;CL-4&lt;&#x2F;h2&gt;
&lt;p&gt;or what about tapering but still keeping it offcenter for fun?
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0002.png&quot; alt=&quot;wide, tapered hole&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0002.png&quot; alt=&quot;close, tapered hole&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cl-5&quot;&gt;CL-5&lt;&#x2F;h2&gt;
&lt;p&gt;this one’s a little more conventional, sketched in solve space and exported to blender to render. The geometry isn’t made of pretty ngons and so there’s a few artifacts from normal smoothing which I’ll learn how to clean up in the future, but the model is still good enough to get across the general idea. The shape was partially inspired by a champagne glass where the deep well in the centre creates a pleasing little column of bubbles.
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0008.png&quot; alt=&quot;wide, well hole&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0008.png&quot; alt=&quot;close, well hole&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-square-sketches&quot;&gt;the square sketches&lt;&#x2F;h1&gt;
&lt;p&gt;Then I asked myself if maybe a rectangular prism would feel better visually and created a couple cuboidal sketches.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sq-1&quot;&gt;SQ-1&lt;&#x2F;h2&gt;
&lt;p&gt;a square take on CL-2
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0005.png&quot; alt=&quot;wide, square CL-2&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0005.png&quot; alt=&quot;close, square CL-2&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sq-2&quot;&gt;SQ-2&lt;&#x2F;h2&gt;
&lt;p&gt;a square take on CL-4
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0006.png&quot; alt=&quot;wide, square CL-2&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0006.png&quot; alt=&quot;close, square CL-2&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-other-one-in-1&quot;&gt;the other one (IN-1)&lt;&#x2F;h1&gt;
&lt;p&gt;while thinking about using the glass as a whiskey stone i though why not simply build in an icecube&#x2F;whiskey stone?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;wide0007.png&quot; alt=&quot;wide, “ice cube”&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;posts&#x2F;glass-sketches&#x2F;close0007.png&quot; alt=&quot;close, “ice cube”&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>batching multiple object renders in blender</title>
        <published>2023-08-15T00:00:00+00:00</published>
        <updated>2023-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/batching-blender-renders/"/>
        <id>https://skylosblog.com/posts/batching-blender-renders/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/batching-blender-renders/">&lt;p&gt;I recently visited the seaworld design museum in shenzhen. I really enjoyed the exhibit and found it to be energizing and inspiring. While perusing one of the businesses inside the museum’s building I came across a plate that had a thick body and an off-center cavity. Inspired by the plate’s form I had the idea to design some thick bodied cocktail glasses that would use the thermal mass of glass as a whiskey stone to keep their contents cool. When I got home I quickly sketched out some ideas in blender since I’m familiar with it’s modelling tools and wanted to easily visualize the transparency of the material. While I plan to make more precise sketches in free-CAD later, I’ll first need to learn more about its workflow.&lt;&#x2F;p&gt;
&lt;p&gt;For now I’d like to upload a few renders of my sketches and rather than individually set up each render I’d like to take some time to find a way to automate some of the work of rendering similar shots of each sketch.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;possible-solutions&quot;&gt;Possible Solutions:&lt;&#x2F;h1&gt;
&lt;p&gt;It occurs to me that since I want to use one set and simply cycle through a set of objects I could probably render avery short animation and use the frame number to index through a list of objects rendering each object on successive frames. However, I remember reading about an addon or workflow in a blog one time that was meant to speed up the owrk of rendering out multiple shots of a product for commercial b-roll and think that might also be something interesting to learn about. A cursory websearch for blender batch rendering reveals that blender also has a command line tool, though it doesn’t appear granular enough for what I want at first glance. I also found a few different add-ons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Render-Burst&lt;&#x2F;strong&gt;  from Gleb Alexandrov and co, written for blender 2.8, which renders from each camera in a blendfile in sequence.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Batch render&lt;&#x2F;strong&gt;  which can render isolated views and turn tables of multiple meshes in a directory using blender as a render engine and to apply materials&#x2F;textures, but doesn’t embed said objects in a scene.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Batch Render Creator&lt;&#x2F;strong&gt;  which appears to be a gui for blender’s own command line render tools.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Render+&lt;&#x2F;strong&gt;  appears to be a more polished, paid version of Render-Burst from a different developer&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;it-seems-like-for-what-i-want-the-best-tools-would-be-some-combination-of-render-burst-and-animation-or-using-render&quot;&gt;It seems like for what I want the best tools would be some combination of Render Burst and animation or using Render+.&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;update:&lt;&#x2F;strong&gt;  I’ve installed renderburst and it indeed can render from multiple cameras in the scene, it was written for blender 2.8 and seems to have lost some of its functionality with blender 3.5. So i will either proceed manually or buy render+&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ssh quickstart for newbs like me</title>
        <published>2023-08-10T00:00:00+00:00</published>
        <updated>2023-08-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/ssh-quick-notes/"/>
        <id>https://skylosblog.com/posts/ssh-quick-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/ssh-quick-notes/">&lt;h1 id=&quot;why-does-this-post-exist&quot;&gt;why does this post exist?&lt;&#x2F;h1&gt;
&lt;p&gt;While trying to learn SSH all the use cases and what not had been covered from the client side, assuming the infrastructure was already set up, but the basic qustion of how do I run my own SSH server and how do I find my hostname to connect were hard to come by. So here’s a little post for past me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conceptual-overview&quot;&gt;conceptual overview&lt;&#x2F;h1&gt;
&lt;p&gt;The SSH protocol is divided into the  &lt;strong&gt;server&lt;&#x2F;strong&gt;  and the  &lt;strong&gt;client&lt;&#x2F;strong&gt; . In order to connect from your local client machine to a remote machine the remote machine must be running an ssh server. you can then use the remote machine’s hostname or ip address to send along the credentials of an account to the remote machine and operate a shell on the machine as the account for which you gave credentials.&lt;&#x2F;p&gt;
&lt;p&gt;SSH is not in itself a shell, merely an encrypted tunneling tool that allows you to use existing shells on a remote machine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;using-the-client&quot;&gt;using the client&lt;&#x2F;h1&gt;
&lt;p&gt;using the client is as simple as running the command  &lt;code&gt;$ ssh user@hostname&lt;&#x2F;code&gt;  to get to the remote user’s login shell. If you want to know more there are plenty of articles explaining the client in more detail.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;using-scp&quot;&gt;using scp&lt;&#x2F;h1&gt;
&lt;p&gt;scp follows the syntax of  &lt;code&gt;$ scp [flags] [source] [target]&lt;&#x2F;code&gt;  the source and target have multiple syntaxes but the easiest to remember is  &lt;code&gt;[user@]host:[&#x2F;path]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;using-sftp&quot;&gt;using sftp&lt;&#x2F;h1&gt;
&lt;p&gt;first you establish an sftp session  &lt;code&gt;$ sftp [user]@[host]&lt;&#x2F;code&gt;
this will then put you inside the sftp prompt. we can then navigate the remote file system with all the typical commands such as  &lt;code&gt;cd&lt;&#x2F;code&gt;  or  &lt;code&gt;ls&lt;&#x2F;code&gt;  if we want to interact with the local system instead we prefix the command with an l for example  &lt;code&gt;lcd&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;to download a remote file we can say&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;sftp&amp;gt; get [remotefilename] sftp&amp;gt; get [remotefilename] [local name]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;uploading a file works the same way using the  &lt;code&gt;put&lt;&#x2F;code&gt;  command&lt;&#x2F;p&gt;
&lt;p&gt;once we’re done we use  &lt;code&gt;exit&lt;&#x2F;code&gt;  or  &lt;code&gt;bye&lt;&#x2F;code&gt;  to close out&lt;&#x2F;p&gt;
&lt;h1 id=&quot;setting-up-the-host&quot;&gt;setting up the host&lt;&#x2F;h1&gt;
&lt;p&gt;You just have to make sure that the SSH server is running. On mac this is done by navigating to &lt;code&gt;system preferences -&amp;gt; sharing&lt;&#x2F;code&gt;  and checking the remote login box.&lt;&#x2F;p&gt;
&lt;p&gt;On windows you must install it from the optional features by navigating  &lt;code&gt;settings -&amp;gt; apps -&amp;gt; optional features&lt;&#x2F;code&gt;  then select add a feature and select openssh client and server. I would then reccomend setting ssh server to run on startup by finding the process in task manager, right clicking it and managing its properties and selecting automatic start.&lt;&#x2F;p&gt;
&lt;p&gt;Now, to find the hostname on unix systems, you can simply use the  &lt;code&gt;$ hostname&lt;&#x2F;code&gt;  command which will output the name of the computer on the local network. Since windows now has WSL you can do the same thing for windows machines.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-about-if-im-not-on-the-local-network&quot;&gt;what about if im not on the local network?&lt;&#x2F;h1&gt;
&lt;p&gt;Well I have Tailscale set up on all my devices already so I plan to simply use that to tunnel into the local network and SSH from there. I assume there are more elegant options but for me this is the best solutions by occam’s razor.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>tailscale quick notes</title>
        <published>2023-07-21T00:00:00+00:00</published>
        <updated>2026-02-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/what-is-tailscale/"/>
        <id>https://skylosblog.com/posts/what-is-tailscale/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/what-is-tailscale/">&lt;p&gt;Tailscale is a vpn tool often used for development to connect into dev environments and enterprises. Unlike more traditional vpn systems it doesn’t have a central hub, its more like a mesh network. A group of machines that can talk to eachother is called a  &lt;em&gt;tailnet&lt;&#x2F;em&gt; . Each tailnet also contains a  &lt;em&gt;coordination server&lt;&#x2F;em&gt;  which assigns each device a  &lt;em&gt;Tailscale ip address&lt;&#x2F;em&gt;  an handles metadata changes and network topology. Because Tailscale is a mesh network, typically machines will talk to eachother directly; when they can’t, they’ll use another node as a  &lt;em&gt;relay&lt;&#x2F;em&gt; . Permissions are managed through an  &lt;em&gt;access control list&lt;&#x2F;em&gt;  on the coordination server.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;set-up&quot;&gt;Set Up&lt;&#x2F;h1&gt;
&lt;p&gt;Download tailscale onto your device and log into your tailscale account. If you don’t have one you can log in using your github account or another identity provider.&lt;&#x2F;p&gt;
&lt;p&gt;You can then use the tailscale app to enable your device to be used as an exit node on your tailnet and, if you want, expose the LAN. Doing so enables vpn use to skirt firewalls. For example: accessing your campus network from home. If you enable LAN access then you can have your friends access your LAN to play minecraft or other games together.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;magic-dns&quot;&gt;Magic DNS&lt;&#x2F;h1&gt;
&lt;p&gt;lets you access a device on your tailnet by going to &lt;code&gt;&amp;lt;device name&amp;gt;.&amp;lt;user name&amp;gt;.ts.net&lt;&#x2F;code&gt;. This also lets you set up public access to your projects without having to set up port forwarding on your home router if you want. Magic DNS also lets you visit &lt;code&gt;https:&#x2F;&#x2F;&amp;lt;device-name&amp;gt;&lt;&#x2F;code&gt; in your browser (if you’re connected to your tailnet) or you can &lt;code&gt;ssh &amp;lt;device name&amp;gt;&lt;&#x2F;code&gt; over your tailnet.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;port-forwarding&quot;&gt;port forwarding&lt;&#x2F;h1&gt;
&lt;p&gt;to forward within your tailnet use &lt;code&gt;tailscale serve&lt;&#x2F;code&gt; to forward to the public internet use &lt;code&gt;tailscale funnel&lt;&#x2F;code&gt;. Note that funnel can only listen on 3 specific ports: 443, 8443, 10000. We can forward to a specific port by doing something like &lt;code&gt;tailscale funnel --http(s):443 localhost:5000&lt;&#x2F;code&gt; you can also forward to a specific path: &lt;code&gt;tailscale funnel --set-path=&#x2F;site&#x2F;path localhost:5000&lt;&#x2F;code&gt;. See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;Tailscale&#x2F;comments&#x2F;14gccua&#x2F;funnel_serve_multiple_ports&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; reddit post&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosting-a-simple-website&quot;&gt;Hosting a simple website&lt;&#x2F;h2&gt;
&lt;p&gt;run &lt;code&gt;tailscale serve absolute&#x2F;path&#x2F;to&#x2F;my-site.html&lt;&#x2F;code&gt; to serve the site on your tailnet and &lt;code&gt;tailscale funnel absolute&#x2F;path&#x2F;to&#x2F;my-site.html&lt;&#x2F;code&gt; if you want to serve it to the internet more broadly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;forwarding-a-service&quot;&gt;forwarding a service&lt;&#x2F;h2&gt;
&lt;p&gt;If you have a server listening on &lt;code&gt;localhost:3000&lt;&#x2F;code&gt; you can use tailscale to forward that port by running &lt;code&gt;tailscale funnel 3000&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;file-server&quot;&gt;file server&lt;&#x2F;h2&gt;
&lt;p&gt;you can host a directory with &lt;code&gt;tailscale serve &amp;lt;path&amp;gt;&lt;&#x2F;code&gt;, note that the path must be absolute.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-in-the-background&quot;&gt;running in the background&lt;&#x2F;h2&gt;
&lt;p&gt;you can host in the background using &lt;code&gt;tailscale funnel --bg &#x2F;absolute&#x2F;path&#x2F;to&#x2F;dir&lt;&#x2F;code&gt; and then see it in a list with &lt;code&gt;tailscale funnel status&lt;&#x2F;code&gt; and kill it by specifying that service with off &lt;code&gt;tailcale funnel --https 443 off&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>some gel plate printing experiments</title>
        <published>2023-07-18T00:00:00+00:00</published>
        <updated>2023-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/gel-plate-printing/"/>
        <id>https://skylosblog.com/posts/gel-plate-printing/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/gel-plate-printing/">&lt;p&gt;I purchased a gel plate a few months ago and have been experimenting with it on and off for a few months. I was inspired by  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@yeatesmakes&quot;&gt;Yeates Makes&lt;&#x2F;a&gt; , and have been trying to replicate his image transfer method. However, unlike him, I don’t have acrylic print medium, and due to my art material collection already being cramped I don’t want to buy any. Instead I have slowly been trying to get image transfer to work with my large supply of black tempera.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-summary-of-how-gel-transfer-with-proper-medium-normally-goes&quot;&gt;A summary of how gel transfer with proper medium normally goes&lt;&#x2F;h1&gt;
&lt;p&gt;We either take a printed positive, or create one using oil based mediums, such as crayons. We then apply a film of print medium to the gel plate. After a moment of drying time, the positive is lightly pressed into the gel plate. The paper absorbs print medium while the positive is mildly hydrophobic and does not. Thus when our positive is removed it leaves behind a duplicate image, that can then be absorbed onto a plain sheet of paper. In order for this technique to work the medium  &lt;em&gt;cannot&lt;&#x2F;em&gt;  dry on the plate. If it did it wouldn’t stick to the blank sheet. Thus we need a medium with a long working time, or we need to apply a fresh layer on top after allowing the first layer to dry on the plate. then we can pull both layers while still wet.&lt;&#x2F;p&gt;
&lt;p&gt;since, in principle, the positive doesn’t absorb ink in the waxed areas it should be re-usable a number of times (on the order of 4).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;a-summary-of-tempera-attempts&quot;&gt;A summary of tempera attempts&lt;&#x2F;h1&gt;
&lt;p&gt;The first problem I encountered was that, un-modified, the tempera I used will bead on the plate rather than coating it. I was able to fix this by adding an emulsifier to the tempera. I happen to have a large amount of gum acacia from ink making experiments a few years ago and so opted for that. The thickened, emulsified tempera coated the plate without issue.&lt;&#x2F;p&gt;
&lt;p&gt;The next issue was that the oil pastels I first used didnt seem to be hydrophobic enough, or at least there wasnt enough contrast between my supposed whites and blacks since the paper doesn’t perfectly absorb everything. I tried wetting the positive before applying it but that proved innefective. While some gel printing tutorials reccomend wetting the sheet I found that with the lightweight sheets I was using, the swelling caused the paper to bubble across the plate and thus have such an even contect no image could be reliably produced. Instead I found that the major problems I had were that I had applied too much pressure to the positive, forcing waxed sections to take up ink, and that the tempera was drying too fast and thus not fully picked up onto the blank sheet.&lt;&#x2F;p&gt;
&lt;p&gt;I tried wetting the receiving sheet, but like before, the buckling and swelling of the paper got in the way. I tried going faster and that had some success but i found the positive was just too absorbent. Instead I took another page from  &lt;em&gt;Yeates Makes&lt;&#x2F;em&gt;  and applied a second layer of clear medium made from gum acacia and water, which allowed me to pull everything from the plate. This can work great in most cases, but because it so effectively pulls from the plate, if the positive doesn’t absorb enough ink, the whole page will be dark, though the image is still intelligible. The gum acacia also creates a glossy surface finish which is not neccessarily good or bad but should be noted.&lt;&#x2F;p&gt;
&lt;p&gt;It’s also crucial to give the print enough time to dry onto the blank sheet from the plate. If pulled prematurely most of the image will be left on the plate.&lt;&#x2F;p&gt;
&lt;p&gt;using white pigment rather than clear as the second layer may help improve contrast.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>tkinter notes</title>
        <published>2023-07-16T00:00:00+00:00</published>
        <updated>2023-07-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/tkinter-notes/"/>
        <id>https://skylosblog.com/posts/tkinter-notes/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/tkinter-notes/">&lt;h1 id=&quot;tcl&quot;&gt;tcl&lt;&#x2F;h1&gt;
&lt;p&gt;Tcl stands for tool command language. It’s an interpretted general purpose language. TK is a graphic user interface library built for use with tcl. Python’s TKinter is essentially a bunch of tools to build command strings using the tk module to be handed off to a tcl interpreter that is spun up on program start.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tkinter&quot;&gt;TKinter&lt;&#x2F;h1&gt;
&lt;p&gt;Every tkinter program starts off by spinning up the tcl interpreter with  &lt;code&gt;Tk()&lt;&#x2F;code&gt;  and then we can start telling it to render widgets using the geometry manager (grid, pack, etc). However, it won’t do anything until we activate the main loop with  &lt;code&gt;Tk().mainloop()&lt;&#x2F;code&gt; . We can then quit by calling
the  &lt;code&gt;destroy&lt;&#x2F;code&gt;  method on the root ( &lt;code&gt;Tk()&lt;&#x2F;code&gt; ).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;canvas&quot;&gt;canvas&lt;&#x2F;h1&gt;
&lt;p&gt;the canvas has its own internal environment where each thing drawn to the canvas has its own id and the canvas can identify which element’s pixels the cursor is hovering over.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;text-rendering&quot;&gt;text rendering&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;tk-font&quot;&gt;tk.font&lt;&#x2F;h2&gt;
&lt;p&gt;allows you to load fonts and apply styles lik italic and bold. It has a function to calculate how much space a piece of text will take up in a given display. For whatever reason tk doesnt have builtin support for one text widget with multipl families so you will need to calculate positioning every time you change font.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;window-tools&quot;&gt;window tools&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;ttk-sizegrip&quot;&gt;ttk sizegrip&lt;&#x2F;h2&gt;
&lt;p&gt;this is a widget that enables the user to click and drag it to adjust the size of the parented window.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>About</title>
        <published>2023-07-14T00:00:00+00:00</published>
        <updated>2026-02-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/about/"/>
        <id>https://skylosblog.com/about/</id>
        
        <content type="html" xml:base="https://skylosblog.com/about/">&lt;h1 id=&quot;the-author&quot;&gt;The Author&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;skylosblog.com&#x2F;about&#x2F;VioletChan_SPRING2026.pdf&quot;&gt;Here&lt;&#x2F;a&gt;  is my resume and feel free to shoot me an email  &lt;a href=&quot;mailto:violet@.skylosblog.com&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My name is Violet, and here are some fun facts about me:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I know multiple programming languages!&lt;&#x2F;li&gt;
&lt;li&gt;I know a bit of mandarin and cantonese&lt;&#x2F;li&gt;
&lt;li&gt;I taught myself how to read cyrillic, hangeul, katakana, hiragana, and perso-arabic&lt;&#x2F;li&gt;
&lt;li&gt;I can read international phonetic alphabet&lt;&#x2F;li&gt;
&lt;li&gt;I can also read laundry symbols&lt;&#x2F;li&gt;
&lt;li&gt;I got up to just below conversational french in like a month for a highschool thing&lt;&#x2F;li&gt;
&lt;li&gt;I can sail a dinghy&lt;&#x2F;li&gt;
&lt;li&gt;I’m familiar with muay thai, kung fu, tae kwan do, capoeira, fencing, and am now doing archery, BJJ, and Systema&lt;&#x2F;li&gt;
&lt;li&gt;I did folk dance regularly for 2 years pre-2021&lt;&#x2F;li&gt;
&lt;li&gt;I designed and built a bookshelf for my sister&lt;&#x2F;li&gt;
&lt;li&gt;I can wrap a gift without using any tape&lt;&#x2F;li&gt;
&lt;li&gt;In college I ran a student campaign to be elected to my own name and lost to my close friend&lt;&#x2F;li&gt;
&lt;li&gt;I can do the cool chalk dotted line trick&lt;&#x2F;li&gt;
&lt;li&gt;I have my calligraphy on a couple different local organization’s social media&lt;&#x2F;li&gt;
&lt;li&gt;I also do various print techniques (mostly gelli transfer and collography)&lt;&#x2F;li&gt;
&lt;li&gt;I do chinese water color&lt;&#x2F;li&gt;
&lt;li&gt;I can do the fun chef thing where you julienne stuff really fine&lt;&#x2F;li&gt;
&lt;li&gt;I have bound my own notebooks, sharpened my own knives, and sewn my own clothing&lt;&#x2F;li&gt;
&lt;li&gt;I made a woodblock printed business card&lt;&#x2F;li&gt;
&lt;li&gt;I have made a few of my own programming languages now&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;how-i-intend-to-use-this-blog&quot;&gt;How I Intend to Use This Blog&lt;&#x2F;h1&gt;
&lt;p&gt;This blog will serve as something between documentation and a scratch space. I intend to share projects as I work on them and will often compose blog posts as I work in order to help organize my thoughts and lay out plans of action. The more information dense posts on here are living documents that I will occasionally revise as I learn more about their subject. Rarely will there be a post written after the fact meant to clearly show off a project.&lt;&#x2F;p&gt;
&lt;p&gt;This is less of a portfolio and more of a sketchbook: it’s mostly for my own use but you get to see it too. That said, in the future I may add a section meant to be more portfolio-like.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>a dnd map viewer and maker</title>
        <published>2023-07-12T00:00:00+00:00</published>
        <updated>2023-07-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/python-map-viewer/"/>
        <id>https://skylosblog.com/posts/python-map-viewer/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/python-map-viewer/">&lt;h1 id=&quot;concept&quot;&gt;concept&lt;&#x2F;h1&gt;
&lt;p&gt;we want the ability to take an image, add location specific annotations, zoom in, zoom out, pan around. It may be easier to use a magnifying glass tool rather than have everything zoom around, that way there’s be less moving parts. Ideally we want to only use the python standard library.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;minimum-viable-product&quot;&gt;minimum viable product&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;ability to annotate an image with labels and blurbs&lt;&#x2F;li&gt;
&lt;li&gt;ability to click on labels to reveal annotations&lt;&#x2F;li&gt;
&lt;li&gt;an easy way to build new maps&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;design-ideas&quot;&gt;design ideas&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;multiwindow&quot;&gt;multiwindow&lt;&#x2F;h2&gt;
&lt;p&gt;we have a main map canvas window. a separate window for compass rose and scale, a separate magnifying glass window, and a separate data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-window&quot;&gt;one window&lt;&#x2F;h2&gt;
&lt;p&gt;alternatively we have one window with a canvas widget and a control bar. we zoom in using the canvase and transform all label widgets etc accordingly.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;issues&quot;&gt;issues&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Python does not have standard image module so we will have to write any image processing ourselves.&lt;&#x2F;li&gt;
&lt;li&gt;All images used by TKinter must be in the mainloop scope. otherwise they will be deleted from memory and will not load.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>designing a small c# app</title>
        <published>2023-07-09T00:00:00+00:00</published>
        <updated>2023-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/small-c-app/"/>
        <id>https://skylosblog.com/posts/small-c-app/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/small-c-app/">&lt;h1 id=&quot;concept&quot;&gt;concept&lt;&#x2F;h1&gt;
&lt;p&gt;Let’s make a small app to help with routines. We’re going to borrow the terminology of sets and reps and enable users to build their own routines out of these units.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terminology&quot;&gt;terminology&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;We’ll say a  &lt;strong&gt;rep&lt;&#x2F;strong&gt;  consists of a task name and a target time. In the future we can refactor this to enable different limits.&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;set&lt;&#x2F;strong&gt;  consists of some number of the same  &lt;strong&gt;reps&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;a  &lt;strong&gt;routine&lt;&#x2F;strong&gt;  consists of some number of  &lt;strong&gt;sets&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;functionality&quot;&gt;functionality&lt;&#x2F;h2&gt;
&lt;p&gt;The minimum viable product needs two things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the ability to play a routine (and the ability to select which routine to play)&lt;&#x2F;li&gt;
&lt;li&gt;the ability to design a routine
in the future it would be nice to also have the ability to view statistics about ones routine usage. It may also be nice to reference other routines a user has built within another routine.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;interface&quot;&gt;interface&lt;&#x2F;h2&gt;
&lt;p&gt;What information should the system provide the user while in use?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;while playing a routine a user should know how far they have progressed in the routine&lt;&#x2F;li&gt;
&lt;li&gt;while playing a routine a user should know what rep they are on&lt;&#x2F;li&gt;
&lt;li&gt;while playing a routine it would be nice for a user to know what is next&lt;&#x2F;li&gt;
&lt;li&gt;while designing a routine it may be useful to see an estimate of how long a routine will take&lt;&#x2F;li&gt;
&lt;li&gt;it should be easy to get an overview of what a routine entails before playing it&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>This is my first post: how to zola</title>
        <published>2023-07-08T00:00:00+00:00</published>
        <updated>2023-07-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Violet
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://skylosblog.com/posts/first/"/>
        <id>https://skylosblog.com/posts/first/</id>
        
        <content type="html" xml:base="https://skylosblog.com/posts/first/">&lt;p&gt;I am currently learning how to build this site with Zola, their tutorials are decent, but I think they aren’t clear enough about preisely the system image.&lt;&#x2F;p&gt;
&lt;p&gt;zola breaks sites into content, layout, and styling.
content is the text, layout is the html, styling is the css&lt;&#x2F;p&gt;
&lt;p&gt;content is broken into sections and pages.
each section is a container for pages.
each section has an “_index.md” header that can establish variables.
each page is another markdown file that again has a header of variables and a body of text.
the variable header is enclosesed in “+++”-es.&lt;&#x2F;p&gt;
&lt;p&gt;layout is broken into templates.
templates can have place-holders which are then filled by other templates that “extend” them.
they can also access variables stored in the relavant mark down files as well as certain automatically generated values&lt;&#x2F;p&gt;
&lt;p&gt;styling is either normal css or sass.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;building&quot;&gt;building&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$zola serve&lt;&#x2F;code&gt;  will build and host locally&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$zola build&lt;&#x2F;code&gt;  will build and places the result in the directory called public by default&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;since im using neocities I can then go to the commandline and say  &lt;code&gt;$ neocities push public&lt;&#x2F;code&gt;  and it will recursively upload the directory&lt;&#x2F;p&gt;
&lt;h1 id=&quot;taxonomies&quot;&gt;taxonomies&lt;&#x2F;h1&gt;
&lt;p&gt;you can also have user defined categories called Taxonomies. these taxonomies have terms and values. terms are the pieces of metadata inside the taxonomy, for example colors, the values are objects associated with each piece of metadata.&lt;&#x2F;p&gt;
&lt;p&gt;We place the configuration of a taxonomy in the config.toml file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;taxonomies&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;colors&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; feed&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;shape&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; feed&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you can then set the taxonomies per page in the header of each file&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;taxonomies&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;colors&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;red&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;blue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;shape&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;circle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;the taxonomy pages are then visible at&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;$BASE_URL&#x2F;$NAME&#x2F; (taxonomy) $BASE_URL&#x2F;$NAME&#x2F;$SLUG (taxonomy entry)&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tera&quot;&gt;tera&lt;&#x2F;h1&gt;
&lt;p&gt;Zola uses the Tera html templating syntax.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;markdown&quot;&gt;markdown&lt;&#x2F;h1&gt;
&lt;p&gt;zola uses common mark with shortcodes that allow you to nsert little macros. However, you can also just type raw html in the midst of a markdown document and it will be carried through.
the basics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#n&lt;&#x2F;code&gt;  is  &lt;code&gt;&amp;lt;hn&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;-&lt;&#x2F;code&gt;  is bullet point&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;---&lt;&#x2F;code&gt;  is a horizontal rule&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;*text*&lt;&#x2F;code&gt;  to emphasize&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;**text**&lt;&#x2F;code&gt;  to bold&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;\&lt;&#x2F;code&gt; `` for code snippets, and triple for blocks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;![text](url)&lt;&#x2F;code&gt;  to display an image&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[text](url)&lt;&#x2F;code&gt;  to link&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;sass&quot;&gt;sass&lt;&#x2F;h1&gt;
&lt;p&gt;As mentioned before, Zola uses Sass as a css preprocessor. Sass has two syntaxes: an extended css syntax, referred to as sassy css and indicated with a .scss filetype and indented syntax indicated with a .sass filetype. I’ll be focussing on the scss syntax.&lt;&#x2F;p&gt;
&lt;p&gt;variables can be declared with  &lt;code&gt;$var_name:value;&lt;&#x2F;code&gt;  they are scoped so that variables declared inside a block are local to that block. you can add interpolation expressions anywhere in a scss document with a  &lt;code&gt;#{expression}&lt;&#x2F;code&gt;  the evaluated result of which will be inserted in place as an unquated string NOT a number. numbers can be inserted by using sass code as is. ie just using a variable name  &lt;code&gt;$var&lt;&#x2F;code&gt; .&lt;&#x2F;p&gt;
&lt;p&gt;you can import other sass documents with  &lt;code&gt;@use&lt;&#x2F;code&gt; .  &lt;code&gt;@import&lt;&#x2F;code&gt;  does the same thing but also imports the styles not just mixins and vars and functions.&lt;&#x2F;p&gt;
&lt;p&gt;mixins are importable styles that take the form of a style annotated with a  &lt;code&gt;@mixin&lt;&#x2F;code&gt;  before the style name and an optional list of arguments after  &lt;code&gt;@mixin style(args){rules}&lt;&#x2F;code&gt; . we then use a mixin with the include keyword like so  &lt;code&gt;@include style(args);&lt;&#x2F;code&gt; . arguments can be given default values by doing  &lt;code&gt;$arg:val&lt;&#x2F;code&gt; .  &lt;code&gt;@include&lt;&#x2F;code&gt;  can also pass arguments by name not just positionally.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;themes&quot;&gt;themes&lt;&#x2F;h1&gt;
&lt;p&gt;sometimes you dont wanna build the look from scratch this is where themes come in.&lt;&#x2F;p&gt;
&lt;p&gt;to install a theme you can simply clone it into the themes directory. You then tell Zola to use the theme in the config file. The theme name is the directory it was cloned into e.g  &lt;code&gt;themes&#x2F;blog&lt;&#x2F;code&gt;  has the name  &lt;code&gt;blog&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
