Thog

My Thought Log

ASCII already has 'tabulation' characters beyond 'tab'.

^I | 09 | 09 | HT | ␉ | Character Tabulation, Horizontal Tabulation | \t | Position to the next character tab stop. ^K | 11 | 0B | VT | ␋ | Line Tabulation, Vertical Tabulation | \v | Position the form at the next line tab stop.
H | 136 | 88 | HTS | Character Tabulation Set Horizontal Tabulation Set | Causes a character tabulation stop to be set at the active position. I | 137 | 89 | HTJ | Character Tabulation With Justification Horizontal Tabulation With Justification | Similar to Character Tabulation, except that instead of spaces or lines being placed after the preceding characters until the next tab stop is reached, the spaces or lines are placed preceding the active field so that the preceding graphic character is placed just before the next tab stop. J | 138 | 8A | VTS | Line Tabulation Set Vertical Tabulation Set | Causes a line tabulation stop to be set at the active position.

HT would be used to go to the next column. VT would be to go the the next row (starting at the first column).

Not totally sure how the rest would be used.

HTS & VTS could be used to manually define cell lengths, but how would that make sense for auto-wraping? Maybe it would just disable it.

Is the default auto wrapping or the 'usual' 8 column tabstops w/ line wrapping?

Does auto wrapping need to be 'enabled' somehow or is the existence of a VT enough to go on?

How do you actually HTS and VTS? I think you emit the character when your cursor is where yo want the stop to be. How exactly does that function? Especially for VT, what's the reference point? Can it be unset?


This would be useful for things that are actually tables, but could also be useful for things like log log output lines that clearly delineate new log lines from wrap lines.

For the log line use case, it would probably be useful to define how cells overflow. e.g.:

Default Cell Overflow:

thog  | 2023/11/27 18:45:56 "POST /api/posts/alf2o9ulbz"
        200 9.464619ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
        Gecko/20100101 Firefox/120.0"
thog  | 2023/11/27 18:45:56 "GET /d/alf2o9ulbz" 200
        3.942241ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
        Gecko/20100101 Firefox/120.0"
thog  | 2023/11/27 18:46:06 "GET /d/alf2o9ulbz/edit" 200
        1.413491ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
        Gecko/20100101 Firefox/120.0"

'Indented Wrapping':

thog  | 2023/11/27 18:45:56 "POST /api/posts/alf2o9ulbz"
  200 9.464619ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
  Gecko/20100101 Firefox/120.0"
thog  | 2023/11/27 18:45:56 "GET /d/alf2o9ulbz" 200
  3.942241ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
 Gecko/20100101 Firefox/120.0"
thog  | 2023/11/27 18:46:06 "GET /d/alf2o9ulbz/edit" 200
  1.413491ms "Mozilla/5.0 (X11; Linux x86_64; rv:120.0)
  Gecko/20100101 Firefox/120.0"

Where the latter could be achieved with an HT of 8 and a VT of 1.


Ref

Well, getting this setup was a pain. Might aswell document what it took to get it going with itself.

Writefreely doesn't have any instructions for running it “in production” and it's a bit confusing to get setup since they only seem to support running from it's source code directory, but it's possible to get it setup properly-ish.

I'm going to be running this under docker-compose with a traefik reverse proxy.

We need a directory to put things in:

mkdir -p apps/writefreely/
cd apps/writefreely/

Their releases are really old, so lets clone the repo and just use the latest:

mkdir src
git clone https://github.com/writefreely/writefreely.git src/writefreely

Now we're going to need a dockerfile. The top half of this is basically the same as their builder script in the root of the repo.

The Dockerfile:

# Builder
FROM golang:1.19-alpine as build

RUN apk add --update nodejs npm make g++ git
RUN npm install -g less less-plugin-clean-css

RUN mkdir -p /go/src/github.com/writefreely/writefreely
WORKDIR /go/src/github.com/writefreely/writefreely

COPY ./src/writefreely/ .

RUN cat ossl_legacy.cnf > /etc/ssl/openssl.cnf

ENV GO111MODULE=on
ENV NODE_OPTIONS=--openssl-legacy-provider

RUN make build \
  && make ui

# Server
FROM alpine:3

RUN apk add --no-cache openssl ca-certificates
COPY --from=build /go/src/github.com/writefreely/writefreely/static /app/static
COPY --from=build /go/src/github.com/writefreely/writefreely/templates/ /app/templates
COPY --from=build /go/src/github.com/writefreely/writefreely/static/ /app/static
COPY --from=build /go/src/github.com/writefreely/writefreely/pages/ /app/pages
COPY --from=build /go/src/github.com/writefreely/writefreely/keys/ /app/keys
COPY --from=build /go/src/github.com/writefreely/writefreely/cmd/writefreely /usr/bin/

WORKDIR /app/data
VOLUME /app/data
EXPOSE 8080

ENTRYPOINT ["writefreely"]

The docker-compose.yml, obviously, change with your domain and make sure your Traefik is configured with the same entry point names:

version: "3.8"

services:
  thog:
    container_name: thog
    build:
      dockerfile: ./Dockerfile
    restart: unless-stopped
    networks:
      - web
    volumes:
      - "./data:/app/data/:Z"
    labels:
      - traefik.enable=true
      - traefik.docker.network=web
        # HTTP redirect
      - traefik.http.routers.insec-thog.entryPoints=web
      - traefik.http.routers.insec-thog.rule=Host(`thog.azdle.net`)
      - traefik.http.routers.insec-thog.service=thog
        # HTTPS reverse proxy
      - traefik.http.routers.thog.entryPoints=websecure
      - traefik.http.routers.thog.rule=Host(`thog.azdle.net`)
      - traefik.http.routers.thog.service=thog
      - traefik.http.routers.thog.tls=true
      - traefik.http.routers.thog.tls.certResolver=default
      - traefik.http.services.thog.loadbalancer.server.port=8080
      - traefik.http.services.thog.loadbalancer.passHostHeader=true

networks:
  web:
    external: true

That should be enough to get it to be able to configure itself. Run the config wizard and answer its questions:

docker-compose run thog config start

Now we need to fix a few things in the generated config to make it actually work.

Edit your config.ini (^ created this in the data directory) to have these settings:

[server]
hidden_host          = 
port                 = 8080
bind                 = 0.0.0.0
tls_cert_path        = 
tls_key_path         = 
autocert             = false
templates_parent_dir = /app
static_parent_dir    = /app
pages_parent_dir     = /app
keys_parent_dir      = /app/data

[...]

Now generate the keys:

docker-compose run thog keys generate

And finally you can start the server:

docker-compose up -d

Improvements

  • Check if there are ENV vars I can just bake into the image to prevent all the config file fubling.
  • How the heck do I get a Dockerfile COPY to copy folders and not just their contents? (Merge all the COPY statements that go into /app.)
  • Maybe document my Traefik setup here too?