What are you working on? - Programming On Unix

Users browsing this thread: 1 Guest(s)
jkl
Long time nixers
I’ve read that Twitter will roll out a new API soon. I will have to rewrite my Twitter client, my low-resource tweet viewer and my data collection project. Eek.
freem
Members
A dialog alternative.
It's a project I have since... long. I got some PoCs, now I'm working on the tooling I need.

My idea is to write a declarative DSL to manipulate exactly 2 types of elements: nodes and leaves. Nodes would be groups of nodes or (inclusive) leaves, and leaves would be the "widgets". My current thinking is that they can actually be described without using the usual inheritance/derivation hell that can be found in toolkits I've played with, one just need to define a number of rules to describe which values the content should accept.
That language would be spoken on stdin and stdout, of course, and if asked to not expect a client, the rendering would be a fdisk-like menu interface. Otherwise, clients could connect to that server, maybe spawned by the server itself, to do the rendering.

This is a tool I need in order to achieve other bigger projects, aka build my own distro. This tool would allow me to use shell scripts to build system tools that could be usable with: ssh, TTY, X11, framebuffer... and, yes, I suppose wayland too.

I really started to think on this when I wrote a tiny shell script allowing to manage runit daemons, and noticed that a lot of the complexity directly comes from dialog itself.
Here is the script, that I place on CC-0 license (no, I don't think I've published it):

Code:
#!/bin/sh

# This script aims to offer a friendly interface to manage runit services
# Requires:
# * dialog
# * find
# * $SVDIR which indicates the supervision folder
# * $SVKNOWN which indicates a colon-separated list of places to search for
#     existing services (duplicated services are *not* supported... yet?)
# * $ACTION indicates how to manipulate services
#
# Currently supported $ACTION values:
# * install: allows to register/unregister known services;
#
# Planned to support $ACTION values:
# * enable: allows to enable/disable known services;
# * toggle: same, via down file;

printf "SVDIR=%s\nSVKNOWN=%s\n" ${SVDIR:="/etc/service"} ${SVKNOWN:="/etc/sv/"} >&2
ACTION="enable"
SV_LIST=""

FINDOPT="-mindepth 1 -maxdepth 2 -name run "
for SOURCE in $(printf ${SVKNOWN} | tr ':' '\t')
do
    SV_LIST="$SV_LIST    $(find -H $SOURCE $FINDOPT -exec sh -c \
        'printf "%s %s off\n" $(dirname {}) $(dirname {})' \; | sort)"
done

SV_ENABLED=$(find -L ${SVDIR} $FINDOPT -exec sh -c \
    'printf " -e '\''/%s off$/ s/off$/on/g'\'' " $(basename $(dirname {}))' \;)

SV_CURRENT=$(printf "%s %s %s\n" $SV_LIST | eval sed $SV_ENABLED)

DIALOG=$(mktemp -d)
dialog --no-tags --checklist "List of service to $ACTION:" 0 0 0 $SV_CURRENT 2> $DIALOG/out
SV_NEW_ENABLED=$(tr ' ' '\n' < $DIALOG/out | awk -F/ '{printf " -e '\''/%s off$/ s/off$/on/g'\'' \n", $NF}END{printf "\n"}')
SV_NEXT=$(printf "%s %s %s\n" $SV_LIST | eval sed $SV_NEW_ENABLED)

printf "%s\n" "$SV_CURRENT" > $DIALOG/curr
printf "%s\n" "$SV_NEXT" > $DIALOG/next
AWKPROG='
{
    if( $2 != $3 )
    {
        if( $2 == "on" )
        {
            last = split( $1, elem, "/" );
            printf "rm %s/%s\n", svdir, elem[last];
        }
        else
        {
            printf "ln -s %s %s/\n", $1, svdir;
        }
    }
}
'
paste -d ' ' $DIALOG/curr $DIALOG/next | cut -f1,3,6 -d ' ' | awk -F' ' -v svdir="$SVDIR" "$AWKPROG"
rm -r $DIALOG

It's not my first dialog script, either. This project I work on because I am really tired of that crapiness.
ckester
Members
I'm not doing any coding right now, but I am doing some reading on constraints and "little languages" for layout.

http://hcil2.cs.umd.edu/trs/98-13/dissertation.html

http://www.layx.org/

What I have in mind is creating a small declarative language for user interfaces, with special attention to ncurses- or other textmode programs.

A related project has been to explore a design approach that composes ncurses programs using hierarchical state machines driven by libev's event pump. This is something that got started when I forked Tobias Rapp's mcplay, which is a rewrite in C of the old cplay frontend for mpg123/ogg123. Initially, I only intended to add some UI features like displaying info from the ID3 tags. But mcplay is itself very old now and uses glib-1.2, which I consider an abomination. Last year my forked program began crashing somewhere deep in the bowels of glib and was a royal pain to debug. So I cut the Gordion Knot and began replacing the glib stuff with my own code for linked lists and libev for the event loop. Eventually I grew frustrated with some of the convoluted structure inherited from mcplay and decided to redo the whole thing from scratch. I finished my rewrite earlier this year and have been thinking about ways to do it even better... Still too many global variables and impure functions, for example. Thinking about those flaws is what has me thinking about data structures for layout and "immediate mode user interfaces".

Sorry, I don't yet have my "ncplay" code in an Internet-accessible repository, but will happily email a copy to anyone who would like to take a look at it. Just send me a private message here on nixers.

I'll welcome any pointers to other resources related to declarative approaches to user interface layout.
ckester
Members
Here's a screenshot of the current iteration of ncplay

https://pasteboard.co/JmR865s.png

This is running in an st terminal under spectrwm and MX Linux. Mononoki font.

The file selection pane on the left is toggle-able.

The currently-playing song is shown with green text in the playlist pane,
while the gray bar is the current cursor position.

Songs can be marked for deletion or movement within the playlist,
which can be sorted by pathname, title, artist, album, or a genre column which is not shown here.
Random shuffle is also supported.

The number of playlist columns shown can be changed using a command which removes the rightmost column;
if only the titles are currently shown, repeating the command replaces them with the filepaths, and then back to showing them all (including the genre field). This probably isn't the most intuitive UI design, but it works well enough for now.

If the "stop after current song" command is active, it will be indicated by a red square just to the left of the timer in the lower right corner. Infinite looping of the playlist is indicated by a yellow square to the right of the timer.

The blank line underneath the progressbar and filepath is reserved for a vi-style commandline interface which is not yet implemented. (Currently all commands are single keystrokes.)

469K, statically linked and stripped when using musl libc, ncursesw, libev, and libid3tag. I need to do some analysis to see if I can get that smaller.

As you can see, it no long bears much resemblance to the version of mcplay I started with!
freem
Members
(17-08-2020, 03:16 PM)ckester Wrote: I
What I have in mind is creating a small declarative language for user interfaces, with special attention to ncurses- or other textmode programs.

I'd be interesting to hear more on that. Ideally, IRC would be great, but we can share pieces of min on forums, too
ckester
Members
(17-08-2020, 10:03 PM)freem Wrote:
(17-08-2020, 03:16 PM)ckester Wrote: I
What I have in mind is creating a small declarative language for user interfaces, with special attention to ncurses- or other textmode programs.

I'd be interesting to hear more on that. Ideally, IRC would be great, but we can share pieces of min on forums, too

I'll keep you in mind if I ever get beyond the info-gathering stage.

My main interest at this point is in data structures that can be used to generate an immediate-mode UI after being updated by pure functions in response to input events. As indicated above, this interest is mostly the result of a postmortem analysis of what I see as the flaws remaining in the current iteration of ncplay, which has become one of my main playgrounds for exploring ways to structure programs.

(I'm sticking with textmode programs partly because they avoid many of the complexities of GUI apps, but mainly because they appeal to my old fart sense of aesthetics. Dittos for C. But there are some ideas from the GUI or web programming world and other programming language communities that I think might be interesting to bring over into the text-based C programming world.)

Some more links re declarative UIs:

https://flutter.dev/docs/get-started/flu...eclarative

https://www.wearemobilefirst.com/blog/sw...rogramming

https://hackage.haskell.org/package/grapefruit-ui

Note that most discussions of declarative UIs are in the context of a framework, where once the application developer has declared the UI the framework takes care of implementing and updating it. I.e., the interest is in it mostly as a labor-saving device. My interest in different: I see it as a way to structure programs in a more functional style and I'm interested to see if this results in cleaner, more maintainable code. I'm pursuing elegance --- not labor-avoidance (which I suspect really means more bloat under the hood or behind the scenes.)
phillbush
Long time nixers
Inspired by wmutils I'm working on some window management utilities that operate on EWMH, I call them ewmhutils. They are a collection of scripts that use wmctrl(1) and xprop(1) to do some EWMH manipulations, such as pcd(1): print current desktop/workspace number, ndesks(1): print number of desktops, wstat(1): print window state (whether it is hidden, maximized, fullscreen, etc).

I'll probably convert those scripts to C.
I have already converted to C the one that change workspace focus, because the script was too slow. I'll probably post it in github soon.

I'm also working on changemon(1), a wm-agnostic utility that uses Xinerama to change the focused monitor.
For example:

Code:
$ changemon right   # focus monitor on the right of current one
$ changemon next    # focus next monitor
$ changemon 3       # focus monitor 3

And also, I'm working on shod(1), my EWMH-compliant window manager.
shod(1) is the project I'm less proud of, because of the number of bugs it has. I use shod as my daily wm, however.
venam
Administrators
(18-08-2020, 12:08 AM)phillbush Wrote: Inspired by wmutils I'm working on some window management utilities that operate on EWMH, I call them ewmhutils.
Maybe it's better to call it a wmctrl clone.
z3bra
Grey Hair Nixers
(18-08-2020, 12:08 AM)phillbush Wrote: I'll probably convert those scripts to C.

Check out my WM: glazier. It uses a standalone tool named ewmh(1) to offload EWMH stuff from the WM. The code is (IMO) relatively simple and easy to read.

This way you can have a clean WM doing only what it should, and implement only the subset of EWMH you need !

That could also help you get familiar with handling EWMH properties in C (note that I do not use xcb/xcb_ewmh.h for it, but plain old Atoms directly, so one less dependency, yeeha!)
phillbush
Long time nixers
(18-08-2020, 02:30 AM)venam Wrote: Maybe it's better to call it a wmctrl clone.
Hehe. I wrote it mostly to understand X Atom and property handling. So it's more an exercise for me than an utility for others to use, so that justify reinventing the wheel. As is shod(1), an exercise for me to better understand X event handling and window management.

The only utility that I wrote for others to use is changemon, which I think there is nothing like it yet.

(18-08-2020, 05:12 AM)z3bra Wrote: Check out my WM: glazier. It uses a standalone tool named ewmh(1) to offload EWMH stuff from the WM. The code is (IMO) relatively simple and easy to read.
I have already checked ewmh(1) and glazier(1)! I think that it is a harder work to separate both utilities, as most of ewmh hints need the wm to keep track of some client states and configuration. But you have done this harder work in an elegant way. Do you think in add other _NET_WM_STATEs other than _NET_WM_STATE_FULLSCREEN? I think that _NET_WM_STATE_MAXIMIZED_* could be implemented the same way as _NET_WM_STATE_FULLSCREEN, with properties keeping track of the unmaximized window size. And _NET_WM_STATE_HIDDEN could be implemented with a property containing a list of hidden windows.
z3bra
Grey Hair Nixers
From what it's worth, EWMH hints are always set on a window, meaning that the current state doesn't have to be tracked in memory by the WM. What is nit tracked though is the previous state (eg. when going fullscreen), so you need a way to save it. Most WM keep an in-memory map of all windows with their attributes, but this seems redundant to me. I prefer defining my own set of atoms, and save the states here. The advantage of this method is that your WM is stateless, so more robust to restart/crash/... Another advantage is composability, beause you expose it for external tools to use, meaning that tools like wmutils can make use of this atoms to do whatever they want.
Being stateless was my first objective when writing glazier, as I wanted a WM that's fully compatible with wmutils, and extensible by it.

As for your question about EWMH atoms, why not ?
I though I was the only one using it, so I only bothered implementing my needs. I'd totally accept patches !
ckester
Members
(17-08-2020, 08:58 PM)ckester Wrote: 469K, statically linked and stripped when using musl libc, ncursesw, libev, and libid3tag. I need to do some analysis to see if I can get that smaller.

After tweaking the CFLAGS and LDFLAGS used to build the libs and ncplay itself, I've got it down to 329K.

I'm still looking into using netbsd-curses instead of ncurses, but hit a snag trying to compile it with musl libc. I know the sabotage linux folks have it working with musl, so I know this is solvable. I just need to take some time to figure it out.
jkl
Long time nixers
I rewrote one of my Twitter bots in Rust (it was my last active Python project - finally I can uninstall it on that server!) because it was intriguing to do something with Rust and the Python installation was broken again.

Now I feel the sudden urge to hold a lecture about why Rust is a horrible language and nobody should ever use it. Arguably, it is a very fast language, but the syntax hurts my brain.
opFez
Members
(22-10-2020, 09:51 AM)jkl Wrote: I rewrote one of my Twitter bots in Rust (it was my last active Python project - finally I can uninstall it on that server!) because it was intriguing to do something with Rust and the Python installation was broken again.

Now I feel the sudden urge to hold a lecture about why Rust is a horrible language and nobody should ever use it. Arguably, it is a very fast language, but the syntax hurts my brain.

I'd suggest you check out Zig. It's like a more modern C, if you like those kind of low-level fast languages. Some of the syntax is inspired by Rust, but it looks so much nicer imo.
jkl
Long time nixers
Go is a more modern C, and I like it. :-)
Despite the performance difference.
neeasade
Grey Hair Nixers
a few months ago I wrote a bunch of color utilities for working in various colorspaces in emacs. I was exploring different ideas, and sort of left a bunch of sexp's all over the place. Now I'm cleaning up the helpers I created during that time so that they all have a consistent interface. I'm also trying to distill a blog post out of the link reading I did at the time. This is a list of references I mostly went through:

;; https://en.wikipedia.org/wiki/CIELAB_color_space
;; LAB only: https://en.wikipedia.org/wiki/Standard_i...lluminants
;; https://peteroupc.github.io/colorgen.html
;; http://colorizer.org/
;; https://github.com/yurikhan/yk-color/blo...k-color.el
;; https://www.w3.org/TR/WCAG20/#relativeluminancedef
;; emacs shipped color.el
phillbush
Long time nixers
I'm playing with The One True Awk™ to make some scripts.

The first one is a testbench generator for verilog modules.
This isn't very UNIXy, but it's something I was needing for my CPU Architecture classes and couldn't find one that suited my needs (I found one written in Python, but the generator wasn't very smart and only covered a small subset of what I wanted), so I wrote one myself.

And also a manpage to markdown converter.
I wrote this to post the manpages I wrote for my programs in the github wiki page.

AWK is indeed a extremelly useful application.
Books on AWK are on my reading queue.
Both scripts are public domain and written in POSIX AWK.
mcol
Nixers
This week I wrote a little program to convert BDF fonts into FIGfonts, the font format that figlet uses. Half way through making it, I discovered in the depths of github a pre-existing perl script with an identical name (bdf2flf) that does the exact same thing, but I marched on anyway for the C practice.

It lets me print things like this in any cool bitmap font:
Code:
██

██████       ████     ██    ██     ██████   ██  ████     ██████
██    ██       ██       ████     ██  ██     ████         ██
██    ██       ██       ████     ████       ██             ██
██    ██     ██████   ██    ██     ██████   ██         ████████
(This font tamzen.)
vain
Long time nixers
(29-10-2020, 05:27 PM)mcol Wrote: This week I wrote a little program to convert BDF fonts into FIGfonts
Neato!

How flexible is figlet, actually? Would it be possible to do “square” pixels?
mcol
Nixers
(30-10-2020, 01:28 PM)vain Wrote: Would it be possible to do “square” pixels?

For sure. I actually initially planned to add a '--small' option to the converter to use "▀", "▄" and "█" but decided I'd wait until I actually need it (maybe a bored afternoon project). The block I printed above is also "square pixels", just using the whole-block character ("█") for the foreground. This is equivalent to the first example in your post that uses just spaces, except this of course uses a foreground colour rather than background colour.

Figlet fonts just store a 2D array of characters (like the 6 above for the chars in 'nixers') for all of the characters in the font, so pretty much any characters can be included in them.
s0kx
Members
Trying to turn mbox files into clean html with python. Code is still pretty messy, but the design is starting to look okay I think..

[Image: 0f.png]

Not sure if I'm going to finish this, but recommendations are welcome. For example, maybe quoted text should be colored slightly differently?