arnaught [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=92431 Orbit XS <p> <table><tr><td> <a href="/bbs/?pid=172179#p"> <img src="/bbs/thumbs/pico8_orbitxs-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=172179#p"> Orbit XS</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=172179#p"> [Click to Play]</a> </td></tr></table> </p> <p>An <a href="https://store.steampowered.com/app/615610/Orbt_XL/">Orbt XL</a> demake in Pico-8 for LowRezJam2025!</p> <p><a href="https://rayquaza01.itch.io/orbit-xs">Itch</a>, <a href="https://itch.io/jam/lowrezjam-2025/rate/3814069">Jam Submission</a></p> <h1>How To Play</h1> <p>The planet is orbiting a black hole! Press any button (Up, Down, Left, Right, Z/O, or X/X) to move the planet away.</p> <p>Points are awarded based on how close to the black hole you are. (3 points/second for the inner ring, 2 points/second for the middle ring, and 1 point/second for the outer ring.)</p> <p>Asteroids are also being pulled in, too, so try not to get hit. Near misses award bonus points! Green asteroids change the direction of the orbit once they hit the black hole.</p> <p>Asteroids will spawn faster for each minute you're alive.</p> <p>Additional planets can be unlocked with points. This is just cosmetic. Try and earn 400 points to unlock all the planets! (And try and beat my high score, which is 577!)</p> https://www.lexaloffle.com/bbs/?tid=150975 https://www.lexaloffle.com/bbs/?tid=150975 Fri, 15 Aug 2025 13:41:37 UTC Bubbles <p> <table><tr><td> <a href="/bbs/?pid=170148#p"> <img src="/bbs/thumbs/pico64_zxbubbles-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=170148#p"> zxbubbles</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=170148#p"> [Click to Play]</a> </td></tr></table> </p> <p>My attempt at recreating the bubbles demo from this youtube video (the bubbles part starts at around 15 minutes)</p> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/ZQZt4MO2eD4&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="https://www.youtube.com/v/ZQZt4MO2eD4&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>Circles are drawn at a random position on the bottom row, and the screen is scrolled (by using <code>blit</code> to copy the display onto itself offset by -1 rows).</p> <p>It's not quite the 31 bytes the one in the video is, but I tried to keep it small. 152 bytes minified, 141 minified+compressed.</p> https://www.lexaloffle.com/bbs/?tid=150204 https://www.lexaloffle.com/bbs/?tid=150204 Fri, 11 Jul 2025 13:54:24 UTC HTTP Server <p> <table><tr><td> <a href="/bbs/?pid=170011#p"> <img src="/bbs/thumbs/pico64_httpserver-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=170011#p"> HTTP Server</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=170011#p"> [Click to Play]</a> </td></tr></table> </p> <p>An HTTP Server in Picotron!</p> <p>Running the cart will start a demo, hosting a server on localhost:8000. The cart will display the access logs. The site serves a form. Once submitted, the form results will be displayed in the log.</p> <p>Full instructions on GitHub: <a href="https://github.com/Rayquaza01/picotron-http">https://github.com/Rayquaza01/picotron-http</a></p> https://www.lexaloffle.com/bbs/?tid=150165 https://www.lexaloffle.com/bbs/?tid=150165 Wed, 09 Jul 2025 16:29:45 UTC livesplit <p> <table><tr><td> <a href="/bbs/?pid=169880#p"> <img src="/bbs/thumbs/pico64_livesplit-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=169880#p"> livesplit</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=169880#p"> [Click to Play]</a> </td></tr></table> </p> <p>A Proof of Concept livesplit client for Picotron!</p> <p>Requires Livesplit (livesplit.org) with the TCP server running.</p> <p>Usage: Z to start/split, X to reset</p> <p>Color matches the Livesplit colors (green for running, blue for stopped, grey for not running)</p> <p>When the TCP server is not connected, the timer will be red. Once it connects, it will change to normal.</p> https://www.lexaloffle.com/bbs/?tid=150116 https://www.lexaloffle.com/bbs/?tid=150116 Mon, 07 Jul 2025 15:55:41 UTC Image Viewer <p> <table><tr><td> <a href="/bbs/?pid=163097#p"> <img src="/bbs/thumbs/pico64_imgviewer-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=163097#p"> Image Viewer</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=163097#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a cart to view png or qoi images in Picotron. It uses <a href="https://www.lexaloffle.com/bbs/?uid=27691"> @pancelor</a>'s <a href="https://www.lexaloffle.com/bbs/?tid=141149">import png</a> library. It's basically a different frontend for import png.</p> <p>You can zoom in/out an image with scroll wheel, and pan across the image by dragging.</p> <p>You can copy the image as a sprite to clipboard by pressing Ctrl+C.</p> <p>You can open png and qoi images (as well as pal and hex pallets) by dropping them on the window (or, <code>default_app png /path/to/imgviewer.p64</code> to set image viewer as the default app for pngs).</p> <p>The statusbar shows the size, viewport position (coordinate of top left pixel), zoom, and loading progress.</p> <p>The image used in the label preview is <a href="https://commons.wikimedia.org/wiki/File:Cat_demonstrating_static_cling_with_styrofoam_peanuts.jpg">Cat demonstrating static cling with styrofoam peanuts</a> from Wikipedia.</p> <p>Original image: Sean McGrath from Saint John, NB, Canada, Derived image: Black Rainbow 999, CC BY 2.0 &lt;<a href="https://creativecommons.org/licenses/by/2.0&gt">https://creativecommons.org/licenses/by/2.0&gt</a>;, via Wikimedia Commons</p> https://www.lexaloffle.com/bbs/?tid=147616 https://www.lexaloffle.com/bbs/?tid=147616 Sun, 02 Mar 2025 00:30:09 UTC Calendar Widget <p> <table><tr><td> <a href="/bbs/?pid=163064#p"> <img src="/bbs/thumbs/pico64_calendarwidget-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=163064#p"> Calendar Widget v1.1.0</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=163064#p"> [Click to Play]</a> </td></tr></table> </p> <p>A simple calendar widget. Install to tooltray with drag-and-drop.</p> <p>Displays the current month's calendar, and highlights the current day.</p> <p>Click the block (top left) to toggle the window's transparency. (When started on the tooltray, it will automatically be transparent)</p> <p>The date is calculated in local time by default. Switch to UTC by clicking the house (local) indicator.</p> <p>Using my DateToUnix function: <a href="https://www.lexaloffle.com/bbs/?tid=146596">https://www.lexaloffle.com/bbs/?tid=146596</a> (Hey, I finally found a use for it!)</p> <p><strong>Changelog</strong></p> <p>v1.0.1 (2025-03-01):</p> <ul> <li>Fix text centering</li> </ul> <p>v1.0.2 (2025-03-09):</p> <ul> <li>Fixed day of week being wrong after daylight savings starts</li> </ul> <p>v1.1.0 (2025-05-13):</p> <ul> <li>Settings override file (/appdata/bbs/calendarwidget/settings.lua) to change colors, format, and week start</li> </ul> https://www.lexaloffle.com/bbs/?tid=147609 https://www.lexaloffle.com/bbs/?tid=147609 Sat, 01 Mar 2025 14:50:04 UTC Analog Clock Widget <p> <table><tr><td> <a href="/bbs/?pid=163063#p"> <img src="/bbs/thumbs/pico64_clockwidget-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=163063#p"> Analog Clock Widget 1.0.0</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=163063#p"> [Click to Play]</a> </td></tr></table> </p> <p>A simple analog clock widget. Install to tooltray with drag-and-drop.</p> <p>Time is 12 hour by default. Switch to 24 hour by clicking the digital display, or the am/pm indicator.</p> <p>Time is local time by default. Switch to UTC by clicking the house (local) indicator.</p> <p>Right click to close widget on desktop.</p> https://www.lexaloffle.com/bbs/?tid=147608 https://www.lexaloffle.com/bbs/?tid=147608 Sat, 01 Mar 2025 14:44:10 UTC Bouncy Ball <p> <table><tr><td> <a href="/bbs/?pid=162708#p"> <img src="/bbs/thumbs/pico64_ball-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=162708#p"> Bouncy Ball v1.0.2</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=162708#p"> [Click to Play]</a> </td></tr></table> </p> <p>A bouncy ball for your Picotron desktop!</p> <p>Open the cart and a ball will drop on your desktop! Pick it up, and throw it around. It will bounce and roll on your open windows!</p> <p>When you're done with the ball, right click it to close it.</p> <p>Using rspr by <a href="https://www.lexaloffle.com/bbs/?uid=45492"> @fletch_pico</a> to get the ball rolling (literally!) - <a href="https://www.lexaloffle.com/bbs/?tid=141706">https://www.lexaloffle.com/bbs/?tid=141706</a></p> <p>If you spawn multiple balls, they won't interact with each other. I have the window background set to be transparent (using <code>poke(0x547d, 0xff)</code>), but this seems to cause the window to be excluded from <code>/ram/shared/windows.pod</code>.</p> <p>Video Showcase: <a href="https://www.youtube.com/watch?v=x22LJ8qvKN4">https://www.youtube.com/watch?v=x22LJ8qvKN4</a></p> https://www.lexaloffle.com/bbs/?tid=147494 https://www.lexaloffle.com/bbs/?tid=147494 Sat, 22 Feb 2025 22:07:11 UTC Inline (one-off) Image Editor <p> <table><tr><td> <a href="/bbs/?pid=162578#p"> <img src="/bbs/thumbs/pico64_inlineimg-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=162578#p"> inlineimg</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=162578#p"> [Click to Play]</a> </td></tr></table> </p> <p>You can print inline images (one off characters) using an escape code (<code>\^:&lt;character&gt;</code>). For example, <code>\^:447cb67c3e7f0106</code> will print a cat.</p> <p>The format is 8 bytes in hexadecimal representing a row, and each bit representing a column, for a 8x8 monochrome image. However, writing it out by hand is obviously a pain. I found some editors for Pico8 (<a href="https://www.lexaloffle.com/bbs/?tid=50298">https://www.lexaloffle.com/bbs/?tid=50298</a>), but I couldn't find one for Picotron. So I made one.</p> <p>There is a 8x8 grid of tiles, representing the image. Clicking a tile inverts it. The escape code and character preview are shown at the bottom of the window.</p> <p>Ctrl+V to paste an image from clipboard and load it into the editor<br /> Ctrl+C to copy the image in hexadecimal format<br /> Ctrl+B to copy the image in binary format.</p> <p>The binary escape code is <em>supposed</em> to be more compact. However, it contains unprintable characters, so it needs to be escaped if you want to put it in your code. Once escaped, it's often <em>less</em> compact than the hexadecimal escape code.</p> <p><a href="https://pico-8.fandom.com/wiki/P8SCII_Control_Codes#Drawing_one-off_characters">https://pico-8.fandom.com/wiki/P8SCII_Control_Codes#Drawing_one-off_characters</a></p> https://www.lexaloffle.com/bbs/?tid=147445 https://www.lexaloffle.com/bbs/?tid=147445 Thu, 20 Feb 2025 13:20:20 UTC Balloon Run (Pico 1k Jam 2024) <p> <table><tr><td> <a href="/bbs/?pid=162505#p"> <img src="/bbs/thumbs/pico64_balloonrun-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=162505#p"> balloonrun</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=162505#p"> [Click to Play]</a> </td></tr></table> </p> <p>I made this as my submission for <a href="https://itch.io/jam/pico-1k-2024">Pico 1k Jam 2024</a>, but I never actually posted it on the BBS.</p> <p>Move with Left+Right, Jump with Z (O). Try and dodge the parachuting enemies. See how long you can last!</p> <p>Additional Links:</p> <ul> <li>Balloon Run on Itch (contains the compressed 1021 byte version) - <a href="https://rayquaza01.itch.io/balloon-run">https://rayquaza01.itch.io/balloon-run</a></li> <li>Source code gist - <a href="https://gist.github.com/Rayquaza01/802ccea3ac1ce22a9a812d17f84e6bd6">https://gist.github.com/Rayquaza01/802ccea3ac1ce22a9a812d17f84e6bd6</a></li> </ul> https://www.lexaloffle.com/bbs/?tid=147406 https://www.lexaloffle.com/bbs/?tid=147406 Wed, 19 Feb 2025 13:42:53 UTC Working with Dates <p>The <a href="https://www.lexaloffle.com/dl/docs/picotron_manual.html#date"><code>date()</code> function</a> returns a formatted date.</p> <p>It takes three arguments</p> <ol> <li>format, the format to use for display (See: <a href="https://www.lua.org/pil/22.1.html">Programming in Lua 22.1 - Date and Time</a>). Starting the format with <code>!</code> makes it UTC, otherwise it will be local time.</li> <li>t, the timestamp either as a string (in the default UTC <code>YYYY-mm-dd HH:MM:SS</code>) or Unix timestamp (seconds since 1970-01-01 00:00:00)</li> <li>delta, an amount of seconds to add to the timestamp.</li> </ol> <p><code>date()</code> gets the current time in UTC, and is used to generate timestamps in Picotron (for modified and created times).</p> <p><code>date(&quot;%Y-%m-%d %H:%M:%S&quot;, timestamp)</code> converts <code>timestamp</code> to local time. (So you can store timestamps in UTC and later display them in local time)</p> <p><code>date(nil, nil, -86400 * 10)</code> subtracts 10 days from the current time.</p> <p>Since timestamps are in <code>YYYY-mm-dd HH:MM:SS</code> format, they can be compared directly as strings.</p> <p>Example: <code>&quot;2025-01-17 05:00:00&quot; &lt; &quot;2025-01-17 05:10:00&quot;</code> returns true, as the first timestamp is smaller than the second timestamp (by 10 minutes).</p> <p>I did not realize timestamps could be compared as strings until <em>after</em> writing a function to parse timestamps into Unix timestamps lol.</p> <p>Here is the function to do that. It takes a timestamp string (from <code>date</code>), and returns the Unix timestamp. You can convert a Unix timestamp back into a string using <code>date</code>. Not sure if there are many practical uses for this, since you can do most things with <code>date</code> directly, but I'm sure it'll be useful for something.</p> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--- Converts a Picotron timestamp (from date()) to a unix timestamp --- @param d string function DateToUnix(d) local start, _, year, month, day, hour, minute, second = d:find(&quot;(%d+)%-(%d+)%-(%d+) (%d+):(%d+):(%d+)&quot;) if start then local tm_year = tonum(year) - 1900 local month = tonum(month) local day = tonum(day) local tm_hour = tonum(hour) local tm_min = tonum(minute) local tm_sec = tonum(second) -- tm_yday is the number of days since jan 1 -- the current day is not included, as it's not finished local tm_yday = -1 local isLeapYear = ((year % 4 == 0) and (year % 100 ~= 0)) or (year % 400 == 0) for m = 1, month - 1, 1 do if m == 2 then tm_yday += isLeapYear and 29 or 28 elseif m == 4 or m == 6 or m == 9 or m == 11 then tm_yday += 30 else tm_yday += 31 end end tm_yday += day -- https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16 return tm_sec + tm_min * 60 + tm_hour * 3600 + tm_yday * 86400 + (tm_year - 70) * 31536000 + ((tm_year - 69) // 4) * 86400 - ((tm_year - 1) // 100) * 86400 + ((tm_year + 299) // 400) * 86400 end return nil end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> <p>I also made a quick function that uses the Unix timestamps to calculate the UTC offset (I don't think there's a direct way to do this using <code>date</code>, but I could be wrong.)</p> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--- Calculates the timezone difference between local time and UTC --- Add to UTC to get local time, subtract from local time to get UTC function GetTZDiff() local utc = DateToUnix(date()) local ltz = DateToUnix(date(&quot;%Y-%m-%d %H:%M:%S&quot;)) return ltz - utc end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=146596 https://www.lexaloffle.com/bbs/?tid=146596 Fri, 17 Jan 2025 05:23:07 UTC Conway's Game of Life (with PVP) <p> <table><tr><td> <a href="/bbs/?pid=160684#p"> <img src="/bbs/thumbs/pico64_conway_pvp-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=160684#p"> conway_pvp</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=160684#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a version of Conway's Game of Life with PVP support! It's inspired by/based on this DougDoug stream: <a href="https://www.youtube.com/watch?v=GXUSUFoEJ_Y">A Crew VS. Z Crew in Conway's Game of Life</a>.</p> <p><a href="https://en.wikipedia.org/wiki/Conway's_Game_of_Life#Rules">The rules</a> are very similar to regular Conway's Game of Life.</p> <ol> <li>Any living cell with &lt; 2 living neighbors dies (underpopulation)</li> <li>Any living cell with 2 or 3 living neighbors lives</li> <li>Any living cell with &gt; 3 living neighbors dies (overpopulation)</li> <li>Any dead cell with exactly 3 live neighbors lives (reproduction)</li> </ol> <p>However, there are <em>two colors</em>, red and blue. For rules (2) and (4), when the cell lives, it will match the color of its adjacent cells. If there are more red adjacent cells, it will become red. If there are more blue adjacent cells, it will become blue. If there are an equal number of red and blue adjacent cells, it will randomly choose one.</p> <p>The grid is 25x25, and it wraps around.</p> <p>Place red cells with LMB<br /> Place blue cells with RMB<br /> Erase cells with MMB<br /> Change the simulation speed with Scroll<br /> Step the simulation with O (Z)<br /> Run the simulation with X (X)<br /> Reset simulation with R</p> <p><a href="https://github.com/Rayquaza01/conway-pvp">https://github.com/Rayquaza01/conway-pvp</a></p> https://www.lexaloffle.com/bbs/?tid=146583 https://www.lexaloffle.com/bbs/?tid=146583 Wed, 15 Jan 2025 19:27:20 UTC Using an External Editor - extload and extrunner <p>Typically, when using an external editor, I do <code>cp -f cart.p64 src</code> and then work on <code>src</code> externally. Every time I make a change, I need to <code>load src</code> before running. Then, I can put it back in the cart by doing <code>cp -f src cart.p64</code>.</p> <p>The <a href="https://www.lexaloffle.com/dl/docs/picotron_manual.html#Using_External_Editors">suggested way of using external editors in the docs</a> is to have the code externally, and simply include it from inside the cart. This will automatically use the latest external change, but it makes it harder to switch back to editing inside Picotron, as you need to change parts of your code to put everything back in the cart.</p> <p>I made a quick utility to make loading an external folders easier.</p> <p><code>extload</code> is a modified version of <code>/system/util/load.lua</code> that loads a folder for external editing. It saves the path of the folder in <code>/ram/extcart.pod</code> and loads <code>extrunner</code> instead of the actual folder. (It also loads the workspaces from the folder, though this is a little janky.)</p> <p><code>extrunner</code> is a dummy cart that cds into the external folder (from <code>/ram/extcart.pod</code>), loads the graphics and sfx (by including <code>/system/lib/resources.lua</code>), and runs it (by including <code>main.lua</code>).</p> <hr /> <p>So, to set up an external project:</p> <ol> <li>Create a cart for the project (<code>cart.p64</code>)</li> <li>Extract the cart (<code>cp -f cart.p64 src</code>)</li> <li>Load the extracted cart (<code>extload src</code>)</li> <li>Make any changes with an external editor, test those changes with Ctrl+R</li> <li>When done, rebuild the cart (<code>cp -f src cart.p64</code>)</li> </ol> <p>This lets you work on any cart externally without having to <code>load src</code> every time you make an external change and without needing to make any code changes!</p> <hr /> <p>extload.lua</p> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> --[[ extload load an external folder ]] cd(env().path) local argv = env().argv if (#argv &lt; 1) then print(&quot;\f6usage: load filename -- can be file or directory&quot;) exit(1) end filename = &quot;/appdata/system/util/extrunner&quot; extdir = fullpath(argv[1]) attrib = fstat(filename) if (attrib ~= &quot;folder&quot;) then -- doesn't exist or a file --&gt; try with .p64 extension filename = filename..&quot;.p64&quot; if (fstat(filename) ~= &quot;folder&quot;) then print(&quot;could not load&quot;) exit(1) end end -- remove currently loaded cartridge rm(&quot;/ram/cart&quot;) -- create new one local result = cp(filename, &quot;/ram/cart&quot;) if (result) then print(result) exit(1) end store(&quot;/ram/extcart.pod&quot;, extdir) -- set current project filename store(&quot;/ram/system/pwc.pod&quot;, fullpath(filename)) -- tell window manager to clear out all workspaces send_message(3, {event=&quot;clear_project_workspaces&quot;}) --meta = fetch_metadata(&quot;/ram/cart&quot;) meta = fetch_metadata(extdir) if (meta and type(meta.runtime) == &quot;number&quot; and meta.runtime &gt; stat(5)) then print(&quot;** warning: this cart was created using a future version of picotron.&quot;) print(&quot;** some functionality might be broken or behave differently.&quot;) print(&quot;** please upgrade to the latest version of picotron.&quot;) end if (meta) dat = meta.workspaces --[[ deleteme dat = fetch(&quot;/ram/cart&quot;..&quot;/.workspaces.pod&quot;) if (not dat) printh(&quot;*** could not find\n&quot;) ]] -- legacy location; to do: deleteme if (not dat) then dat = fetch(&quot;/ram/cart/_meta/workspaces.pod&quot;) if (dat) printh(&quot;** fixme: using legacy _meta/workspaces.pod&quot;) end -- legacy location; to do: deleteme if (not dat) then dat = fetch(&quot;/ram/cart/workspaces.pod&quot;) if (dat) printh(&quot;** fixme: found /workspaces.pod&quot;) end -- at the very least, open main.lua if it exists if ((type(dat) ~= &quot;table&quot; or #dat == 0) and fstat(&quot;/ram/cart/main.lua&quot;)) then --dat = {{location=&quot;main.lua&quot;}} -- relative to /ram/cart/ dat = {{location=extdir..&quot;/main.lua&quot;}} end if (type(dat) == &quot;table&quot;) then -- open in background (don't show in workspace) local edit_argv = {&quot;-b&quot;} for i=1,#dat do local ti = dat[i] local location = ti.location or ti.cproj_file -- cproj_file is dev legacy if (location) then --add(edit_argv, &quot;/ram/cart/&quot;..location) add(edit_argv, extdir..&quot;/&quot;..location) end end -- open all at once create_process(&quot;/system/util/open.lua&quot;, { argv = edit_argv, pwd = extdir } ) end print(&quot;\f6loaded &quot;..filename..&quot; into /ram/cart&quot;) print(&quot;\f6loaded external cart &quot; .. extdir)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> <p>extrunner main.lua</p> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>if fstat(&quot;/ram/extcart.pod&quot;) == &quot;file&quot; then cd(fetch(&quot;/ram/extcart.pod&quot;)) include(&quot;/system/lib/resources.lua&quot;) include(&quot;main.lua&quot;) else print(&quot;Couldn't load external cart!&quot;) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> <p><a href="https://gist.github.com/Rayquaza01/574a21a168aa38dc4c0b8b3ec2caf69b">https://gist.github.com/Rayquaza01/574a21a168aa38dc4c0b8b3ec2caf69b</a></p> https://www.lexaloffle.com/bbs/?tid=146533 https://www.lexaloffle.com/bbs/?tid=146533 Sat, 11 Jan 2025 23:09:48 UTC ini Parser <p>I made a simple ini parsing/dumping function. <code>load_ini()</code> converts an ini string to a table, and <code>dump_ini()</code> converts a lua table to an ini string.</p> <p>This could be useful for projects that have a configuration file. Using an ini might be better for user configs since ini supports comments.</p> <p>The ini format is simple. Section headings are marked with <code>[section]</code> and items are stored as <code>key=value</code>. Subsections are separated with a dot. Inline comments are not supported, but comments at the start of the line are.</p> <p>Strings don't have to be quoted, but you should quote them.</p> <p>Example:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>[heading] a=1 b=2 [heading.sub] c=&quot;hello&quot; d=&quot;world&quot; [heading.array] 1=4 2=5 3=6</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>This will convert to:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>{ heading = { a = 1, b = 2, sub = { c = &quot;hello&quot;, d = &quot;world&quot; }, array = { 4, 5, 6 } } }</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>With the way I wrote it, it can handle anything that can be parsed with <code>unpod()</code>. This may be useful for writing some things (such as arrays) more compactly. The following is equivalent to the above example:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>[heading] a=1 b=2 sub={c=&quot;hello&quot;,d=&quot;world&quot;} array={4,5,6}</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <hr /> <p><strong>Changelog</strong></p> <p>2025-04-02:</p> <ul> <li>Allow subheadings to be numbers, providing a different way of writing arrays, and fixing an inconsistency with dump/load</li> </ul> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>[array.1] some=value [array.2] other=value</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <hr /> <p>Code under the cut</p> <p><a href="https://gist.github.com/Rayquaza01/e2cedb3ab53d166fdcd2c1a9cc950b1e">https://gist.github.com/Rayquaza01/e2cedb3ab53d166fdcd2c1a9cc950b1e</a></p> <p><div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--- Loads an ini string into a lua table --- @param ini_text string --- <a href="https://www.lexaloffle.com/bbs/?uid=27234"> <a href="https://www.lexaloffle.com/bbs/?uid=27234"> @Return</a></a> table function load_ini(ini_text) local tbl = {} local lines = split(ini_text, &quot;\n&quot;, false) local current_head = tbl local header = &quot;&quot; for l in all(lines) do -- if line is not comment if not (l == &quot;&quot; or l:find(&quot;^%s*;&quot;) or l:find(&quot;^%s*%-%-&quot;) or l:find(&quot;^%s*#&quot;) or l:find(&quot;^%s*//&quot;)) then if l:find(&quot;^%[.+%]$&quot;) then current_head = tbl header = l:sub(2, #l - 1) for h in all(split(header, &quot;.&quot;, false)) do if tonum(h) ~= nil then h = tonum(h) end if (current_head[h]) == nil then current_head[h] = {} end current_head = current_head[h] end elseif l:find(&quot;^%w+=.+&quot;) then local equals_pos = l:find(&quot;=&quot;, 1, true) local key = l:sub(1, equals_pos - 1) local value = l:sub(equals_pos + 1, #l) if tonum(key) ~= nil then key = tonum(key) end if tonum(value) ~= nil then value = tonum(value) elseif value == &quot;true&quot; or value == &quot;false&quot; then value = unpod(value) else value = unpod(value) or value end current_head[key] = value end end end return tbl end --- Dumps a lua table into an ini string --- @param tbl table --- @param header_prefix? string --- <a href="https://www.lexaloffle.com/bbs/?uid=27234"> <a href="https://www.lexaloffle.com/bbs/?uid=27234"> @Return</a></a> string function dump_ini(tbl, header_prefix) if header_prefix == nil or type(header_prefix) ~= &quot;string&quot; then header_prefix = &quot;&quot; end local text = {} -- first pass add any values for key, value in pairs(tbl) do if type(value) ~= &quot;table&quot; then add(text, (&quot;%s=%s&quot;):format(tostr(key), pod(value))) end end -- second pass add nested tables for key, value in pairs(tbl) do if type(value) == &quot;table&quot; then add(text, (&quot;[%s%s]&quot;):format(header_prefix, key)) add(text, dump_ini(value, (&quot;%s%s.&quot;):format(header_prefix, key))) end end return table.concat(text, &quot;\n&quot;) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=146523 https://www.lexaloffle.com/bbs/?tid=146523 Fri, 10 Jan 2025 21:31:32 UTC Trash Manager <p> <table><tr><td> <a href="/bbs/?pid=160465#p"> <img src="/bbs/thumbs/pico64_trashman-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=160465#p"> trashman v1.0.3</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=160465#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a trash manager for Picotron that loosely follows the XDG Trash Specification. You can use it to delete and and later restore files from trash.</p> <p>Full usage instructions are in the <a href="https://github.com/Rayquaza01/trashman">README</a> (also available from &quot;Help&quot; inside the cart), but basically you can drag/drop files to move them to trash. Left click a file in trash to restore it, right click a file in trash to permanently delete it.</p> <p>You can also use Trash Manager as a CLI utility.<br /> <code>trash [files]</code> to move files to trash<br /> <code>trash --list [search]</code> or <code>trash --search [search]</code> to list/search trash<br /> <code>trash --restore [files]</code><br /> <code>trash --restore-all</code> to restore all files<br /> <code>trash --delete [files]</code> to permanently delete files<br /> <code>trash --empty</code> or <code>trash --delete-all</code> to permanently delete all trash</p> <p>Finally, you can use it in the tooltray. You can drop files to the indicator to move them to trash, and you left click the indicator to open the GUI or right click it to empty the trash.</p> <p><strong>Changelog</strong></p> <p>v1.0.1 (2025-02-18):</p> <ul> <li>Use <code>argv[0]</code> instead of <code>prog_name</code> (0.1.1e compatibility)</li> <li>Use <code>open</code> instead of accessing notebook.p64 directly</li> <li>Support installing tooltray widget by dragging to tooltray</li> <li>Ctrl+Drag to move tooltray indicator (Tip: Hold right click on the indicator to focus it first)</li> <li>Move delete action in for tooltray to Middle Click (0.1.1e compatibility)</li> <li>Remove gap between final item and status bar</li> <li>Must be unsandboxed to work!</li> </ul> <p>v1.0.2 (2025-02-18):</p> <ul> <li>Fix bug where can't open cart from indicator or double click</li> <li>All instances of help use open</li> </ul> <p>v1.0.3 (2025-03-01):</p> <ul> <li><a href="https://github.com/Rayquaza01/trashman/releases/tag/v1.0.3">https://github.com/Rayquaza01/trashman/releases/tag/v1.0.3</a></li> <li>Make moving tooltray widget easier (no ctrl+drag required)</li> </ul> https://www.lexaloffle.com/bbs/?tid=146519 https://www.lexaloffle.com/bbs/?tid=146519 Fri, 10 Jan 2025 14:59:46 UTC Snowglobe <p> <table><tr><td> <a href="/bbs/?pid=159476#p"> <img src="/bbs/thumbs/pico64_snowglobe2024-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=159476#p"> Snowglobe</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=159476#p"> [Click to Play]</a> </td></tr></table> </p> <p>A little snowglobe application. Shake the window to make the snow fall. More shaking causes more snow to fall! (If you don't want to shake the window, you can also use the scroll wheel.)</p> <p>Uses the same shaking detection as in <code>#8ball</code>. I drew the scene Pixelorama, and imported it using <code>#importpng</code>.</p> https://www.lexaloffle.com/bbs/?tid=146191 https://www.lexaloffle.com/bbs/?tid=146191 Wed, 18 Dec 2024 18:41:11 UTC PUSH - Terminal Replacement <p>PUSH (<strong>P</strong>icotron <strong>U</strong>pgraded <strong>SH</strong>ell) is a modified version of <code>terminal.lua</code> I made that allows you to add modifications from lua modules. You can place modules in <code>/appdata/system/terminal/</code> and PUSH will load them.</p> <p>Without any modules, PUSH changes very little (<code>cd</code> with no arguments acts as <code>cd /</code>), but modules let you add more functionality.</p> <p>In the repo, I have a list of examples of the sort of things you can do with PUSH, including changing the prompt, adding and overriding commands, and adding shortcuts.</p> <p><a href="https://github.com/Rayquaza01/picotron-upgraded-shell/blob/main/examples/cd.lua">cd.lua</a> is my favorite module so far, I think. It adds replaces the default <code>cd</code> command and adds fish-style directory history.</p> <p><a href="https://github.com/Rayquaza01/picotron-upgraded-shell">https://github.com/Rayquaza01/picotron-upgraded-shell</a></p> <p>This is very WIP, so if you have any trouble or suggestions for how to improve PUSH, let me know!</p> <p><strong>Changelog</strong></p> <p>2025.10.16</p> <ul> <li>Rebase to 0.2.1b terminal</li> <li>Change prompt example to include sandbox indicator</li> <li>Add rm to trash alias example</li> </ul> <p>2025.07.10:</p> <ul> <li>Rebase to 0.2.0g terminal</li> <li>Custom prompts should be mindful of <code>input()</code></li> <li><code>suspend_corun_program()</code> cleans up some variables. Resetting <code>cmd</code> breaks <code>altl</code>, so I removed that. Not sure if there are any downsides to this?</li> <li><code>add_line()</code> was made local. I've changed it back to global for easy access through PUSH modules</li> </ul> <p>2025.2.18:</p> <ul> <li>Add in changes from 0.1.1e terminal.lua</li> <li>Disable barecd when pwd is in bbs:// (fstat in bbs:// seems to <em>always</em> return folder, even when it doesn't exist)</li> </ul> https://www.lexaloffle.com/bbs/?tid=145933 https://www.lexaloffle.com/bbs/?tid=145933 Thu, 05 Dec 2024 03:35:01 UTC Picotron Remote Terminal <p> <table><tr><td> <a href="/bbs/?pid=156917#p"> <img src="/bbs/thumbs/pico64_prt-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=156917#p"> Picotron Remote Terminal v2.0</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=156917#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a tool that lets you remotely control Picotron from the host and vice-versa.</p> <p>You can run commands in Picotron by running <code>prt &lt;COMMAND&gt;</code> from the host</p> <p>This is useful when working with an external editor. You can load and run the updated source code from the external editor, and build/extract the cartridge.</p> <p>You can also run host commands from inside of Picotron with the <code>host</code> command (included in the cart at <code>/exports/appdata/system/util/host.lua</code>). You can even use pipelines!</p> <p>Full usage and installation instructions are included in the repo: <a href="https://github.com/Rayquaza01/picotron-remote-terminal">https://github.com/Rayquaza01/picotron-remote-terminal</a></p> <p>There is an issue I know about where if the cart is running for a while, it will start dropping commands seemingly at random. Not sure exactly what causes this, but restarting the cart seems to fix it.</p> <p><strong>Changelog</strong></p> <p><strong>2025-07-08 - v2.0</strong></p> <ul> <li>Rewritten to use Picotron 0.2.0G sockets! <ul> <li>Picotron server (cart, PUSH module) now listens on port 7426 (PICO)</li> <li>Host server now listens on port 7420 (PIC0)</li> </ul></li> <li>Host server application is no longer required! All you need now is a way to write to a TCP socket (e.g. <code>nc</code>) <ul> <li>This is much more reliable. Commands no longer seem to drop!</li> </ul></li> <li>Host server is still needed if you want to run host commands from in Picotron</li> <li>It may even be practical to use now (maybe...)</li> </ul> https://www.lexaloffle.com/bbs/?tid=145162 https://www.lexaloffle.com/bbs/?tid=145162 Tue, 05 Nov 2024 21:21:17 UTC pretty_printh and ANSI codes for colored logs <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/92431/Screenshot from 2024-10-10 18-38-40.png" alt="" /> <p>This isn't a Picotron specific thing, but you can use ANSI escape codes inside printh to make your logs colorful, which can be helpful with debugging.</p> <p>To set the color, typically you do <code>\033[38;5;&lt;COLOR&gt;m</code> or <code>\033[38;2;&lt;RED&gt;;&lt;GREEN&gt;;&lt;BLUE&gt;m</code>. This sets the foreground color to a color from <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit">this chart</a> or an RGB color code (if your terminal supports truecolor).</p> <p>This just works in Picotron, but you have to do <code>\27</code> instead of <code>\033</code>. (This is the escape code for ESC, which is 27 in decimal and 033 in octal.)</p> <p>However, writing ANSI codes by hand is a pain, so I wrote a function to make inserting these codes easier, using a bbcode-like syntax.</p> <p>Foreground color can be set with <code>[fg=1][/fg]</code> or <code>[fg=#ff0000][/fg]</code><br /> Background color can be set with <code>[bg=1][/bg]</code> or <code>[bg=#ff0000][/bg]</code><br /> Bold can be set with <code>&amp;lsqb;b][/b]</code><br /> Italics can be set with <code>&amp;lsqb;i][/i]</code><br /> Underline can be set with <code>&amp;lsqb;u][/u]</code></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>function pretty_printh(s) s = s :gsub(&quot;%[fg=(#?%w+)]&quot;, function (c) if c:find(&quot;^%d+$&quot;) then return string.format(&quot;\27[38;5;%sm&quot;, c) end if c:find(&quot;^#[%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F]$&quot;) then return string.format( &quot;\27[38;2;%d;%d;%dm&quot;, tonum(&quot;0x&quot; .. c:sub(2, 3)), tonum(&quot;0x&quot; .. c:sub(4, 5)), tonum(&quot;0x&quot; .. c:sub(6, 7)) ) end end) :gsub(&quot;%[/fg]&quot;, &quot;\27[39m&quot;) :gsub(&quot;%[bg=(#?%w+)]&quot;, function (c) if c:find(&quot;^%d+$&quot;) then return string.format(&quot;\27[48;5;%sm&quot;, c) end if c:find(&quot;^#[%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F][%da-fA-F]$&quot;) then return string.format( &quot;\27[48;2;%d;%d;%dm&quot;, tonum(&quot;0x&quot; .. c:sub(2, 3)), tonum(&quot;0x&quot; .. c:sub(4, 5)), tonum(&quot;0x&quot; .. c:sub(6, 7)) ) end end) :gsub(&quot;%[/bg]&quot;, &quot;\27[49m&quot;) :gsub(&quot;%[u]&quot;, &quot;\27[4m&quot;) :gsub(&quot;%[/u]&quot;, &quot;\27[24m&quot;) :gsub(&quot;%[b]&quot;, &quot;\27[1m&quot;) :gsub(&quot;%[/b]&quot;, &quot;\27[22m&quot;) :gsub(&quot;%[i]&quot;, &quot;\27[3m&quot;) :gsub(&quot;%[/i]&quot;, &quot;\27[23m&quot;) printh(s .. &quot;\27[0m&quot;) end function error(msg) pretty_printh(&quot;[fg=1][b][ERROR][/b][/fg]: &quot; .. msg) end function warn(msg) pretty_printh(&quot;[fg=3][b][WARNING][/b][/fg]: &quot; .. msg) end function info(msg) pretty_printh(&quot;[fg=4][b][INFO][/b][/fg]: &quot; .. msg) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Here's the code that I used to get the example in the screenshot:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>function left_pad(s, ch, len) while #s &lt; len do s = ch .. s end return s end function _init() pretty_printh(&quot;[fg=6][b][u]Pretty Printh Demo[/u][/b][/fg]&quot;) for i = 0, 15, 4 do str = string.format( &quot;[fg=%d]color %s[/fg]\t[fg=%d]color %s[/fg]\t[fg=%d]color %s[/fg]\t[fg=%d]color %s[/fg]&quot;, i, left_pad(tostr(i), &quot;0&quot;, 2), i + 1, left_pad(tostr(i + 1), &quot;0&quot;, 2), i + 2, left_pad(tostr(i + 2), &quot;0&quot;, 2), i + 3, left_pad(tostr(i + 3), &quot;0&quot;, 2) ) pretty_printh(str) end error(&quot;this is an error&quot;) warn(&quot;this is a warning&quot;) info(&quot;this is informative&quot;) pretty_printh(&quot;this is a line with [b]bold[/b], [i]italics[/i], and [u]underlines[/u]&quot;) pretty_printh(&quot;[bg=#ffffff][fg=#241f31]this is a line with hex colors[/fg][/bg]&quot;) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=144691 https://www.lexaloffle.com/bbs/?tid=144691 Thu, 10 Oct 2024 23:05:03 UTC Fuzzy Finder <p> <table><tr><td> <a href="/bbs/?pid=155555#p"> <img src="/bbs/thumbs/pico64_fzf-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=155555#p"> fzf 1.1</a><br><br> by <a href="/bbs/?uid=92431"> arnaught</a> <br><br><br> <a href="/bbs/?pid=155555#p"> [Click to Play]</a> </td></tr></table> </p> <p>I built a fuzzy finder. You can quickly search for and open files (anything supported by <code>/system/util/open.lua</code>, so folders, lua files, text files, pods, etc.) Additionally, it can follow <code>.loc</code> files to their destination before opening (which <code>open</code> doesn't currently support), and it can execute <code>.p64</code> files instead of opening them!</p> <p>The full code and documentation is available here: <a href="https://github.com/Rayquaza01/fuzzy-finder-picotron/">https://github.com/Rayquaza01/fuzzy-finder-picotron/</a></p> <p>This uses <a href="https://github.com/swarn/fzy-lua">swarn/fzy-lua</a> (MIT License) and <a href="https://github.com/TheAlgorithms/Lua/blob/main/src/sorting/mergesort.lua">mergesort.lua from TheAlgorithms/Lua</a> (MIT License)</p> <h2>Changelog</h2> <h3>v1.1 - Oct 21, 2024</h3> <ul> <li><a href="https://github.com/Rayquaza01/fuzzy-finder-picotron/releases/tag/v1.1">https://github.com/Rayquaza01/fuzzy-finder-picotron/releases/tag/v1.1</a></li> <li>Fixed bug where blank ignore file causes nothing to appear. <ul> <li>This is still the behavior in the web player, but it should work correctly on desktop Picotron.</li> </ul></li> <li>Commented lines in the ignore file (starting with <code>#</code>) will be ignored.</li> </ul> https://www.lexaloffle.com/bbs/?tid=144685 https://www.lexaloffle.com/bbs/?tid=144685 Thu, 10 Oct 2024 15:04:05 UTC