Location via proxy:   
[Report a bug]   [Manage cookies]                

My Blog

NTFS on Mac

February 24, 2025

Using NTFS on macOS is still a pain. It at least mounts volumes as read-only by default, which is better than nothing, but if you want to write to the disk it’s not as straightforward.

Tuxera and Paragon both have commercial solutions, but I’d rather just use something janky and unsupported, because I’m me. The only reason I even want to write to an NTFS volume on macOS is because my TV only supports playback from FAT32 and NTFS filesystems, and FAT32’s 4 GB limit is not ideal for modern media resolutions, even with newer codecs like AV1.

Let’s just use random Homebrew packages and accept the potential for data loss.

brew install --cask macfuse mounty

brew tap gromgit/homebrew-fuse
brew install gromgit/fuse/ntfs-3g-mac

Simple enough, my TV can play back media written with this setup, and that’s all I really wanted. MacFUSE lets us use the ntfs-3g FUSE driver (which is not intended for macOS, and is very unsupported). The Mounty app wraps the driver in a nice GUI that can auto-remount NTFS volumes r/w, and it’s not a terrible UX overall once it’s working.

fish is Also Great

February 22, 2025

fish is the first shell I’ve used that feels like it’s actually designed around how I want to use a shell. As I’ve gotten more into Python, I’ve loved the convenience and power of a simplified scripting language, and have grown increasingly annoyed at how limiting and unintuitive POSIX shells are, to the point where I was actually considering trying to write my own Python-compatible shell where Python syntax could be used intermixed with generic commands. Basically a Python script but where subprocess.run() would be called most of the time.

I’ve used bash heavily since I was a kid, and switched to zsh after macOS changed defaults for whatever reason (maybe just for consistency between my platforms), but have always felt both were lacking in various ways.

Then I finally tried fish. I no longer feel like I have any desire to reinvent the shell, because fish did it perfectly.

For the basic user config, the default behavior is intuitive and nice, but easily adjusted. Here’s an example of some of my user config in ~/.config/fish/config.fish:

# alias is great for running flatpak CLI apps:
alias wine="/usr/bin/flatpak run --command=wine --file-forwarding net.lutris.Lutris"

# nvm works well enough without the global init:
set -gx NODE_VERSION 'lts/*'
alias node="$HOME/.nvm/nvm-exec node"
alias npm="$HOME/.nvm/nvm-exec npm"
alias npx="$HOME/.nvm/nvm-exec npx"
# You can get full functionality of nvm if needed by following their docs, but this is simpler and doesn't slow down the shell the same way, as long as you only need one node version at a time.

# abbr is like alias but better since it expands to the full command interactively and in history:
abbr -a yt yt-dlp
abbr -a artisan php artisan
abbr -a su sudo su -
abbr -a serve python -m http.server

Adding more complex functions interactively is nice, just use funced -s function_name and you’re dropped into an editor, where the syntax is simple and powerful:

function unzip_all_ja
  for z in *.zip
    unzip -O Windows-31J $z -d (string replace '.zip' '' $z) && rm $z
  end
end

Setting the executable path can be done with extending the PATH envvar, but Fish has a global shell variable file that is far more powerful and intuitive in ~/.config/fish/fish_variables. Adding a path to executables can be done with fish_add_path <dir>, which will automatically update the variable globally.

For adjusting much of the global configuration including the prompt style, color schemes, etc. there is a fish_config function which will launch a web interface for interactively configuring the shell. Every built-in fish_* command can be edited with funced, allowing easy customization of default behavior like prompts, terminal titles, command-not-found handling, and more.

The scripting language for functions and logic is similar to bash, but simplified and much more powerful and intuitive. The shell wraps man by default to add all of the fish documentation, and man fish-doc and man fish-language are excellent references for learning it.

If you want to switch, man fish-tutorial and man fish-for-bash-users are great introductions and cover everything a typical user would need to know. I highly recommend trying it out!

Python is Great

February 21, 2025

Python is my favorite language at this point. It’s so incredibly powerful and easy to work with. The multiprocessing module is simple but so, so useful, I adore how useful argparse is for making intuitive CLI tools, and SQLite being built in has completely converted me away from traditional hosted databases outside of enterprise-scale deployments.

Everything I write for personal tooling is in Python now, and I couldn’t be happier with it. It’s a virtually perfect language, with the exact right functionality included out of the box, with PyPI modules available for anything a bit more obscure.

I love building little helpful tools for various sysadminy things that I do, and some of my more useful tools are publicly available. One is ren, a simple batch file rename utility that makes quickly doing bulk naming operations with Python formatting syntax easy. Another is imgfind, a tool for finding and working with images. It works similar to GNU findutils, searching image metadata, and also includes features for modifying images including a simple way of recompressing/optimizing images in bulk.

My home repository, which is becoming increasingly less relevant to a home directory, includes a bunch of tiny Python-based utilities. It includes a dedup.py utility for easy deduplication of files by linking/deleting, with some simple filters. relink.py makes bulk modifying symlinks easy, with simple path string substitutions and recursive operation. relink-relative.py modifies symlinks in bulk to make them relative instead of absolute, useful for portability. ytdl-db.py works as a standalone utility or a yt-dlp postprocess hook to record metadata about downloaded videos and playlists to a sqlite database, and long-term I plan on integrating it into mytube to make automatic import/discovery of archived video metadata easy.

All of these are relatively simple scripts, but show the power in the simplicity of Python as a language and platform. It’s an excellent alternative for bash scripts when you need a bit more power and flexibility, while still being fairly portable and lightweight. I used to use PHP or Node.js for this kind of thing since those were the languages I knew best, and had moved to using Go for some things that needed parallel processing. Python has all of the advantages of each of those for utility scripts, while being far more likely to be available on any given system.

While the majority of Python I write is for command-line tools, the GTK and QT integrations are excellent, and make powerful GUI apps simple and quick to build, and are a great example of where SQLite is so useful for persisting settings, UI state, etc. in a cross-platform, easily extensible way.

For web apps, I still greatly prefer PHP, since having a template engine built-in is just so convenient, but I don’t see myself ever trying to use PHP or Node.js for anything else now. Except this blog for now I guess, unless I find a really nice Python SSG blogging platform.

Ooblets

February 17, 2025

I really like Ooblets. It’s a fun game with adorable characters and a cute aesthetic. The UI is very simple, so it felt like a fun idea to update the design of my blog again to make it look a bit like Ooblets. The profile image is a watercolor painting of my Ooblets character 🌈✨

Also it’s Tailwind 4 now. The upgrade tool is really helpful!

Ender 3 kinda sucks

November 18, 2024

I like 3D printers. They’re neat. I’m tired of my Ender 3 though.

I know this is very old news, considering how long the Ender 3 has been around. I’ve been fairly reliant on mine for a number of years now, but I’ve grown increasingly disappointed in it, especially with some of it’s inherent design limitations that really compromise the usability and reliability.

Many other cheap printers have similar designs with similar limitations, but having also tried some other printers that don’t have these issues, they still frustrate me.

The extruder

The Ender 3 has separate assemblies for the print nozzle and extruder motor. This reduces weight on the X-axis arm, which can help with stability, especially since the arm is only really supported on one side of the structure. Sadly, it also means the distance between the stepper motor feeding the nozzle and the actual nozzle is significant, and potentially variable. The solution is to have a fixed tube between the motor and nozzle assemblies, but to ensure the feeding and retraction are accurate it needs to precisely fit the filament.

The feeder tube makes tolerances on filament much more important than they would otherwise be if the extruder was a single assembly directly feeding into the nozzle. It also introduces a bunch of new points of failure, mainly with the connection points between tube and assemblies. Filaments with less common materials (especially with increased flexibility or friction) are dramatically affected, leading the extrusion to be inaccurate and unreliable.

The Z-axis

Not too terrible, but the Z-axis motor only directly controls one side of the structure. This means the horizontal X-axis arm that’s raised/lowered by the Z-axis motor can lag behind changes on one side, causing a difference in height adjustment depending on where the extruder is on the X-axis. I haven’t experienced serious issues with this as long as I keep belts and such adjusted just right, but it’s a frustrating limitation compared to some other printers.

Seems like it could easily be improved with another belt. Make the right side of the arm actually actively controlled rather than just being dragged along by the changes to the left side. 🤷🏻

The firmware

It’s slow, it crashes, I just generally dislike it. Many useful features for live adjustment of the print job though, which is very nice when trying to work around the printer’s limitations.

The control knob

The knob used to control the printer (when not controlling it by USB or serial or whatever) is very unreliable, with it often missing presses and rotations. Not a problem necessarily, but adds to the cheap and unreliable feel of using the printer.