RSSAmplifier

BurgeonLab: Full-text · May 28, 2025

ReText: Markdown Editor (How to Install Python Apps on Mac)

0
Sign in to vote or save

Naty S · BurgeonLab

Explore my love for Markdown editors, starting with Mou and evolving to ReText, a Python-based editor. Learn why Markdown is a powerful tool for writing, its pros and cons, and how to set up ReText on macOS using Python virtual environments (venv). Plus, discover tips like creating a minimal app bundle for easier use of Python apps on a Mac.

This post was last updated 1 year ago. The core ideas should still be useful, but tech moves fast; always check the latest docs for current best practices before applying what is mentioned.

My Love For Markdown Editors

As a Markdown user for over a decade, I can vividly recall downloading my first Markdown editor, Mou, by Chen Luo.1 It was an excellent, lightweight application that made note-taking enjoyable during my college years. I loved the customizability; and typing in Markdown meant I didn’t have to use my trackpad/mouse, speeding up my note taking.

Last month, I discovered an open source version called MacDown, but unfortunately it hasn’t been updated since 2020.

I use Markdown when I’m writing all my notes on Obsidian (which I’ve blogged about before) and in VSCodium. I don’t even remember the last time my computer had a word processor installed! A great word processor if you need one is LibreOffice; but I digress.

Markdown Beginners

If you’re just starting with Markdown, check out this great tutorial by Commonmark, which is the main spec of Markdown (There are various dialects or “flavours”, if you will, of Markdown used by different editor/apps like GitHub Markdown). Or read through a detailed guide here.

Why I Use Markdown

  • Easy to get started.
  • High readability.
  • Fast formatting without mouse input.
  • Ability to export to other formats; .md to .html or .md to .pdf.
  • Many other places support Markdown, including instant messaging apps, forums, etc.
  • Minimal appearance in your workspace, i.e., no space-wasting formatting bars in word processors.
  • No more proprietary formats! Markdown files are simple plain text and can be opened for years to come.

Disadvantages of Markdown

  • As mentioned previously, Markdown is not standardized, so you may need to learn specific syntax for the app you’re using

A Minimal Markdown Cheatsheet

Here’s a quick Markdown cheatsheet I made with an A.I. tool I’ve been enjoying; Napkin.AI (not affiliated).

Markdown basic syntax cheatsheet.

This week, I was getting the itch to find a plain Markdown editor again, seeing if I could finally find something that could fit the missing hole Mou left.

Screenshot of ReText Github Readme.

I checked the following alternatives, but none were really suitable for me or runs well on macOS (which is still my daily driver OS). If you’re on Linux, I think Ghostwriter and Marknote are both nice options from KDE.

  1. Ghostwriter—No macOS installer
  2. Marknote—Unstable macOS version
  3. MarkFlowy (alpha)—I didn’t want built-in AI features

In the end, I decided to try ReText, a 100% Python compiled project. The appearance can be fully customized using custom CSS and supports more than just Markdown; reStructuredText, Textile and AsciiDoc are also supported. Although it is also a Linux-first application, I found ReText easier to set up and run on macOS than the other two KDE apps. Building apps from source code and managing dependencies is beyond my current skill level.

Some Notes on Python

Just to make a disclaimer… I have limited Python knowledge from experimenting with Jupyter Notebooks, writing Python automation scripts and using libraries like Matplotlib to analyse data from my Garmin watch. So I’m not sure if the methods I mention below are correct or best practices. I would love any pointers or correction (message me) from those who are more fluent with all this!

Please make your own judgement if it is worth using an app that could lose your work! (So far, the app has been pretty stable, no crashes yet on my Mac Mini M1, Sonoma 15.5.)

Anyway, one thing I learnt was the importance of using virtual environments, AKA venv, as they keep packages, the Python interpreter, and related files within its own isolated environment.

Warning

ReText also suggests installing it inside a venv, but warn about Windows and macOS are in no way officially supported. Use ReText at your own risk.

How I Installed ReText on macOS

The gist of my ReText installation guide is to install ReText into a virtual isolated Python environment, create a shell script that activates the venv automatically whenever ReText is run and closes it when the app is quit. It’s a bit of a makeshift way of running ReText I have to admit.

Discovered a Better Method

Update

After writing up the steps below, I’ve done some further testing and realise that apps launched in the manner I describe—Method A: Using a Shell Script, launching a GUI app from the terminal, sometimes breaks the macOS app focus and fails to switch to ReText; causing it to become unresponsive intermittently, e.g. showing the Terminal menu instead of the Python app launched.

So I investigated on how to make it a native macOS application bundle (.app), and I have failed to get it working, without generating other problems, with both Platypus and Py2app. Platypus worked better than Py2app and was easier to use but it opened another can of worms so I gave up on both.

After quite a bit of reading and troubleshooting, I found out a minimal app bundle could work to make a ReText.app so macOS can launch ReText properly. Very happy to get it to work in the end! It launches ReText without using the terminal, has its own app icon and no more UI glitches. I am pretty excited. I’ve added this second method below.

End of update! I’ll leave the Method A in for reference. Scroll down for an alternative, improved Method B.

Method A: Using a Shell Script

(A bit janky, prone to UI errors, but can let you test out ReText relatively quickly.)

  1. Make a script (name it anything you want) and set correct permissions (make it executable). We will come back to it in step 4.

    1touch launch_retext.sh
    2chmod +x launch_retext.sh
  2. Create a virtual environment, cd into the path of the venv and use source activate the venv.

    1python3 -m venv /path/to/venv/retext-env
    2cd /path/to/venv/retext-env
    3source retext_env/bin/activate

    Tip

    I tend to use the long form install command and not pip3 install ReText or just pip install as I have multiple versions of Python on my Mac and it is the most explicit way to installing packages. It guarantees the correct Python version, works well in virtual environments and avoids PATH issues.

  3. Double check if pip is installed in the venv with pip --version. If so, install ReText with python3 -m pip install ReText. Ensure the virtual environment is activated before installing ReText. And remember to use deactivate after installation to stop the venv!

    Important

    At this point, you can decide to continue with the shell script method or switch to an improved app bundle method I worked out.

  4. Edit the script we made in step 1 with codium launch_retext.sh (My choice of IDE is VS Codium, but nano is good too), and fill in the correct paths. Save when done. Note: Because we are installing via pip, the RETEXT_EXECUTABLE will be in the bin directory of the venv directory.

     1#!/bin/zsh
     2
     3# Set the path to your virtual environment's activation script
     4VENV_ACTIVATE="/path/to/venv/retext-env/bin/activate"
     5# Set the path to the ReText executable
     6RETEXT_EXECUTABLE="path/to/where/retext/is/installed/local/bin/python3"
     7# Path to the __main__.py script within the venv
     8RETEXT_SCRIPT="path/to/where/retext/is/installed/lib/python3.13/site-packages/ReText/__main__.py"
     9
    10echo "Activating virtual environment: $VENV_ACTIVATE"
    11
    12# Activate the virtual environment
    13source "$VENV_ACTIVATE"
    14
    15# Check if the activation worked
    16if [ $? -ne 0 ]; then
    17    echo "Failed to activate virtual environment."
    18    exit 1
    19fi
  5. To make the script more accessible and executable from any directory, there are two options I usually use:

    • Add the folder of where we saved our script launch_retext.sh to our PATH so that any executable script in that directory can be run by its filename alone.

    • Add a shell function for our particular script.

Both methods allow the script to be run anywhere, but the shell function option is more explicit and actually more flexible as it can handle more processing steps, e.g. error checking and argument validations. If you have a lot of scripts, the PATH method is easier.

How to Add Script Directory to PATH

  • To add the script’s directory to your PATH, copy the pathname of the newly created script. Identify which shell you’re using with echo $SHELL. Open the shell configuration file, e.g. .zshrc or .bash_profile in the macOS home directory (~).

  • Add a line near the end of the file: export PATH="$PATH:/location/to/your/scripts".

  • If you have prompt themes installed like powerlevel10k, zsh-theme, add the aliases or PATH mods before theme mods. This ensures are applied and not overwritten by the theme.

  • Save and reload shell with source ~/.zshrc (or the config you edited). Or just close the terminal window and launch a new one.

How to Add a Shell Function

  • Add this snippet to .zshrc, or to your shell config file, following the same rules as the PATH method regarding where in the config it is added. (The config is read in order, from top to bottom.)

  • I have named my function rtx for fast access, i.e. less typing to open the app. You can name it anything you want. This is the word you type into terminal to open ReText.

    1rtx() {
    2    source "/location/to/your/scripts/launch_retext.sh" "$@"
    3}
  • Next, add this extra snippet to the bottom of launch_retext.sh to allow for ReText to open even if we don’t provide a file for it to open, e.g. rtx first_note.md

    1# Check if a file path was provided as an argument
    2if [ -z "$1" ]; then
    3    # If no argument, open ReText with a new, empty file
    4    "$RETEXT_EXECUTABLE" "$RETEXT_SCRIPT"
    5else
    6    # Run ReText with the specified file
    7    "$RETEXT_EXECUTABLE" "$RETEXT_SCRIPT" "$1"
    8fi
  • The whole script should now look like this:

     1#!/bin/zsh
     2
     3# Set the path to your virtual environment's activation script
     4VENV_ACTIVATE="/path/to/venv/retext-env/bin/activate"
     5# Set the path to the ReText executable
     6RETEXT_EXECUTABLE="path/to/where/retext/is/installed/local/bin/python3"
     7# Path to the __main__.py script within the venv
     8RETEXT_SCRIPT="path/to/where/retext/is/installed/lib/python3.13/site-packages/ReText/__main__.py"
     9
    10echo "Activating virtual environment: $VENV_ACTIVATE"
    11
    12# Activate the virtual environment
    13source "$VENV_ACTIVATE"
    14
    15# Check if the activation worked
    16if [ $? -ne 0 ]; then
    17    echo "Failed to activate virtual environment."
    18    exit 1
    19fi
    20
    21# Check if a file path was provided as an argument
    22if [ -z "$1" ]; then
    23    # If no argument, open ReText with a new, empty file
    24    "$RETEXT_EXECUTABLE" "$RETEXT_SCRIPT"
    25else
    26    # Run ReText with the specified file
    27    "$RETEXT_EXECUTABLE" "$RETEXT_SCRIPT" "$1"
    28fi
  • Remember to run source ~/.zshrc to reload config after making changes.

  • Last step: to open the app, go to Terminal, type the function or script name you have set like rtx or to open a file directly rtx /path/to/a/note.md and you should see this:

Screenshot of launching ReText Markdown Editor on a Mac with the terminal.

That’s it for Method A! To close ReText, just close the main ReText window and when you go back to the Terminal, you’ll see you still have the venv activated by the visual cue (name of venv). Just closing the Terminal window will close the venv, or type deactivate.

Let’s get on to the second, perhaps more robust method!

Method B: Make a Minimal App Bundle

  1. Follow step 2 (creating a Python virtual environment for ReText) and step 3 (installing ReText with pip) from Method A.

  2. We will be creating an app bundle with this directory structure. Use mkdir -p ReText.app/Contents/MacOS ReText.app/Contents/Resources to make the folder structure shown below. (To access the files inside the app, right click on the app > Show Package Contents). Put ReText.app into the /Applications folder. We will deal with the Resources/retext.icns in the last step.

    1ReText.app
    2└── Contents
    3  ├── Info.plist
    4  ├── MacOS
    5  │   └── ReTextLauncher
    6  └── Resources
    7      └── retext.icns
  3. Create a Info.plist with xml syntax. CFBundleExecutable will be the name of the executable script and CFBundleIdentifier can be anything you want (I filled it in with the ReText’s creator details). Make sure the file is using UTF-8 encoding.

     1<?xml version="1.0" encoding="UTF-8"?>
     2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     3<plist version="1.0">
     4<dict>
     5    <key>CFBundleExecutable</key>
     6    <string>ReTextLauncher</string>
     7    <key>CFBundleIconFile</key>
     8    <string>retext</string>
     9    <key>CFBundleIdentifier</key>
    10    <string>com.DmitryShachnev.ReTextLauncher</string>
    11    <key>CFBundleInfoDictionaryVersion</key>
    12    <string>6.0</string>
    13    <key>CFBundleName</key>
    14    <string>ReTextLauncher</string>
    15    <key>CFBundleDisplayName</key>
    16    <string>ReTextLauncher</string>
    17    <key>CFBundlePackageType</key>
    18    <string>APPL</string>
    19    <key>CFBundleShortVersionString</key>
    20    <string>1.0</string>
    21    <key>CFBundleVersion</key>
    22    <string>1.0</string>
    23    <key>LSMinimumSystemVersion</key>
    24    <string>10.10</string>
    25    <key>NSPrincipalClass</key>
    26    <string>NSApplication</string>
    27    <key>NSRequiresAquaSystemAppearance</key>
    28    <false/>
    29</dict>
    30</plist>
  4. Like in Method A, step 4, we will create a script in ReText.app/Contents/MacOS/ReTextLauncher to launch ReText in a venv.

    • Fill in the correct path for your VENV_DIR (the one you created in Method A: Step 2) for the script, the rest should not need to be edited.
    • After saving the script, type chmod +x /path/to/ReTextLauncher.app/Contents/MacOS/ReTextLauncher to make it executable.
     1#!/bin/zsh
     2
     3# Set path to the virtual environment
     4VENV_DIR="/Users/username/path/to/venv"
     5
     6# Path to the virtual environment's activate script
     7ACTIVATE_SCRIPT="$VENV_DIR/bin/activate"
     8
     9# Path to the ReText executable
    10RETEXT_EXECUTABLE="$VENV_DIR/bin/retext"
    11
    12# PYTHONPATH (change version number, i.e. 3.13, as required)
    13export PYTHONPATH="$VENV_DIR/lib/python3.13/site-packages:$PYTHONPATH"
    14
    15# Add the virtual environment's bin directory to the PATH
    16export PATH="$VENV_DIR/bin:$PATH"
    17
    18# Launch ReText using the retext command
    19"$RETEXT_EXECUTABLE" "$@"

    Tip

    Sometimes apps fail to run because it’s downloaded outside the Mac App Store or was created manually. It’s due to the new quarantine mechanism. Although I didn’t have to use it on this occasion, I often use it for FOSS apps I get direct from repos online. Always be wary of what you download from the Internet though! Check SHA256 hashes when you can.

    Run xattr -d com.apple.quarantine /path/to/ReTextLauncher.app to remove the quarantine attribute.

    Another cause for errors is the fact this app bundle is not code signed. Code signing is like the seal found in medicine; it is to verify that the contents (app code) is not tampered with. To sign an app for personal use (not distribution), like in this scenario, we can create a self-signed certificate using Keychain Access on the Mac for this.

    • Go to Applications > Utilities > Keychain Access > In the menu bar > Keychain Access > Certificate Assistant > Create a Certificate.
    • Name it something like “Self-Signed Cert”.
    • Identity Type: “Self Signed Root” and check the box “Let me override defaults”, click create.
    • Continue with all the default options until the cert is generated.
    • Go back to the Terminal and use codesign -s "Self-Signed Cert" -f -v /path/to/ReText.app
  5. We’re nearly done!

    • Grab the .png icon from /path/to/venv/lib/python3.13/site-packages/ReText/icons/retext.png and convert it to .icns using an online converter
    • Place the .icns file into ReText.app/Contents/Resources/retext.icns

    Screenshot of the app info window on the ReText bundled app on macOS.

  6. Double click the app to run and close it without going through the Terminal! 🎉

Wrap Up

This ended up longer than I expected, but I learnt some new tricks here and there…2 Hope you did too; and that this tutorial allows Mac users to enjoy this Python-based, Linux-optimized Markdown editor!

Update: Here’s a follow-up guide on how to customize ReText like syntax highlighting and using Python Markdown extensions. Learn how to setup the configuration file because I found it slightly unclear to begin with.

P.S. I made some pretty major changes to the look of this blog last week; which in turn gave me some extra motivation to write! Hope it’s easier on the eyes and looks more polished. 😉


  1. It no longer exists on the web, but here are two blog posts by others talking about it. By Tom and by Andrew ↩︎

  2. Just one of the things I discovered was there’s this CLI tool that generates pretty looking directory trees! brew install tree and run tree in a directory. ↩︎

Read the original on burgeonlab.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.