QZ qz thoughts
a blog from Eli the Bearded
Tag search results for blog Page 5 of 20

vi and tags


The vi editor, and the significant vi-clones, as well as Emacs and other editors, support a thing called a "tags file". It's essentially a set of bookmarks or a book's "Index" section fore text files.

The intended use is you run a program that indexes your source code and creates the tag entries for you. For example, with ctags you can run it and have it scan source code in dozens of languages (not just C-like ones, such as Java and Go, but also Postscript, Fortran, and others) and produce a file that tells the editor how to find function and variable declarations. (For Emacs, use the etags program to similar effect.)

The tags functionality is very useful when editing code. I keep tags files in source directories for all of my multi-year projects. You can begin and edit session by running vi -t pickle to open the editor to the file and line that pickle() is defined. Say inside pickle() you find a call to spices() and want to know what it does, position your cursor in the word and hit <ctrl-]>, you jump there. Return to where you were with a :pop. Without the keyword handy to <ctrl-]> upon, you can instead :tag spices as well.

For people using vim as their vi of choice, it might help to know that the entirety of the :help system is built using tags, just slightly tweaked for where to look for the tags file. If you know how to use help in Vim, you know how to use tags. And :help tags can probably teach you something you didn't already know about them.

The tags files are a little more mysterious. Normally people don't create or edit them by hand, but you can or you can create programs to create them for your own special needs.

The basic format, and all I'll cover here, is a text file with three tab separated columns. The first column is the tag name, eg pickle. The second column is the file name, relative to where the tags file is located. The third column is a ex-mode movement within the file. Usually the movement is a search, something like /^int pickle(recipe_t rec)$/ that will unambigously find a single line in the file. But line numbers also work just fine. And search with line number offset works for niche needs, eg /^int pickle(.*)$/+2 to start out on the variable declarations if your syntax looks like the following sample. With :set scrolloff=3 to put some space above the cursor, it may be more useful for you.

#include "brine.h"

int pickle(recipe_t rec)
{
    long     cuke;
    int      salt;
    spices_t spicing = spices(rec);

    /* ... */
}

In traditional vi any command you could put on a : line would work in the movement column, including things like :! rm *. I know Vim has tightened that, and I believe the other vi-clones have as well. If Vim doesn't like any movement in a tags file, it will ignore the whole file.

One trick I have found useful is programmatically generated tags files created with a wrapper program. Rather than have a giant file with all tags, I have a database that I can query and then it generates a tags file (with a single entry) and invokes vim -t main to jump to the exact file and line for me. This can make my query easier to form than remembering a specific tag keyword and does not involve a large flat file with huge redundancy.

Deja Google News Groups


Those of us who still read Usenet proper have probably all seen instances of 10+ year old threads getting a new post by someone who found it on Deja News or it's Google successor. Eg, last month I saw this reply to a twenty five year-old post.

Newgroups: comp.editors
Date: Fri, 26 Feb 2021 19:21:33 -0800 (PST)
Injection-Info: google-groups.googlegroups.com; [...]
Message-ID: <42d18ee7-712f-41f4-b4af-dba9988b192an@googlegroups.com>
Subject: Re: Maximum line length in Vi
From: Tejasvi S Tomar <tstomar@outlook...>

On Monday, April 17, 1995 at 12:30:00 PM UTC+5:30, Paul Fox wrote:
> G. Ioannou (gi...@cus.cam.ac.uk) wrote:
> : ed
> : Vim
> : Vile
> : They all worked fine with lines over 2000 characters in length, but I
> : don't know the exact limit.
> lines on vile, at least, are limited by the size of an int.
> anyone know what it is in vim?
> paul
> ---------------------------------
> paul fox, p...@foxharp.boston.ma.us (arlington, ma)

It seems there isn't any limit. https://www.oreilly.com/library/view/learning-the-vi/9780596529833/ch15s10.html

Anyway today I encountered a new twist on this. Instead of replying to decade(s) old post through Deja Google, someone instead hunted down my Wikipedia user page and answered a question of mine about Usenet II (dead for at least ten years) on the User Talk page. Really, I had no pressing care about why 4gh was used for the "Distribution" header. I knew it was a reference to some sci-fi book, but didn't really care more than that. And if I did care, the Usenet II page at Wikipedia has had the answer for a while: Usenet II, diff=prev, oldid=181389883

(The same person who added the reference in 2008 is the person who who answered me today on User Talk.)

It makes me wonder if people used to (or maybe still do) get the problem of people writing letters about long ago published stuff after finding it in a library.

C. R. Boffo
123 Main St
Small Town
14 January 1958
Mark Twain
345 Taylor St
San Francisco
Dear Sir,

I am writing to you in regards your piece about the jumping frog trainer that lived in Calaveras County. I don't know if Jim Smiley is training frogs for use in jumping contests, but he should be aware that California law now has mandates about frogs kept for jumping contests. I would also like to say that feeding lead to frogs as that stranger did to Dan'l is just cruel.

Yours sincerely,
C. R. Boffo

Any relation of "C. R. Boffo" to the .a https://en.wikipedia.org/wiki/Colorado_River_toad "bufo "lick for high" toads" is surely coincidental.

Namecheap, Grr


Yesterday qaz.wtf was briefly unavailable. The domain registration expired. This happened for number of reasons, some mine, some I'm going to blame on Namecheap.

First, what I did wrong: I put an overly strong spam filter rule in place that was marking all mail from them as spam. In particular the rule was indiscriminate about source when the domain was (a) using registrar-services.com for DNS and (b) using DNS with a SOA serial number that parsed as less than a day old. In fairness, it is a very effect rule. Here's a sample of the domains from the last 100 messages that deleted:

mail[.]forhealth[.]bar Oct 2020; medicarepro[.]xyz Oct 2020; diabetesfrepro[.]xyz Oct 2020; mail[.]diabetes2type[.]casa Oct 2020; carbosfix[.]xyz Oct 2020; mail[.]pocketdrone[.]work Oct 2020; goldplatedscoin[.]xyz Oct 2020; mail[.]fevertrhermal[.]casa Oct 2020; whowhpremium[.]xyz Oct 2020; mail[.]dxpgaget[.]work Oct 2020; mail[.]machinepower[.]bar Oct 2020; mail[.]trackerss[.]bid Oct 2020; royalbalance[.]cam Oct 2020; mail[.]pocketdron[.]work Oct 2020; stopsqribble[.]bid Oct 2020; shinehead[.]bid Oct 2020; mail[.]neckmassager[.]casa Oct 2020; audigrow[.]bid Nov 2020; mail[.]learnpiano[.]work Nov 2020; mail[.]heatromwave[.]casa Nov 2020; BayAreaTechSummit[.]com Nov 2020; mail[.]waxremove[.]casa Nov 2020; mail[.]gpstrack1[.]work Nov 2020; mail[.]gps1track[.]work Nov 2020; mail[.]zoom2dipro[.]casa Nov 2020; mail[.]strategys[.]bid Nov 2020; lifeprotect[.]uno Nov 2020; oxyrobot[.]bid Nov 2020; survivlife[.]uno Nov 2020; survivlife[.]uno Nov 2020; mail[.]musichall[.]casa Nov 2020; mail[.]discovery1[.]casa Nov 2020; mail[.]diabetesremedy[.]work Nov 2020; mail[.]zoomzoom[.]work Nov 2020; yourbusinesstips[.]biz Nov 2020; mail[.]goodhealth[.]casa Nov 2020; vanses[.]icu Nov 2020; mail[.]dailmulti[.]bid Nov 2020; mail[.]zoompro[.]casa Nov 2020; mail[.]heatpad[.]co Dec 2020; mail[.]foodgrow[.]bid Dec 2020; mail[.]shinehead[.]bid Dec 2020; mail[.]bagtrack[.]work Dec 2020; rewardtoshop[.]com Dec 2020; rivalo[.]com Dec 2020; rivalo[.]com Dec 2020; mail[.]techvisions[.]bid Dec 2020; mail[.]vestwoding[.]icu Dec 2020; brutualloss[.]icu Dec 2020; drawlace[.]buzz Dec 2020; 247blindco[.]co[.]uk Dec 2020; 247blindco[.]co[.]uk Dec 2020; 247blindco[.]co[.]uk Dec 2020; 247blindco[.]co[.]uk Dec 2020; mail[.]easysurveyrewards[.]best Dec 2020; zind[.]us Dec 2020; zind[.]us Dec 2020; herpesyl[.]icu Dec 2020; mail[.]digitalbrand[.]icu Dec 2020; mail[.]offertrend[.]icu Dec 2020; offerworld[.]icu Dec 2020; offerworld[.]icu Dec 2020; mail[.]offerhad[.]icu Dec 2020; healingsystem[.]icu Dec 2020; myshedesplan[.]icu Dec 2020; boosterday[.]best Dec 2020; brutualloss[.]icu Dec 2020; mail[.]shinehead[.]bid Dec 2020; mail[.]remedypro[.]us Dec 2020; tactnutri[.]icu Dec 2020; mail[.]feverfix[.]icu Dec 2020; mail[.]sugartonic[.]icu Dec 2020; mail[.]mechanism[.]icu Dec 2020; mail[.]ecomdeals[.]icu Dec 2020; mail[.]dealsbreeze[.]icu Jan 2021; mail[.]vestwoding[.]icu Jan 2021; mail[.]heatsawy[.]icu Jan 2021; mail[.]capitalreward[.]icu Jan 2021; mail[.]capitalreward[.]icu Jan 2021; mailserviceemailout1[.]namecheap[.]com Jan 2021; mail[.]energyy[.]bid Jan 2021; mail[.]speechrewards[.]icu Jan 2021; mail[.]usonly[.]bid Jan 2021; mail[.]certifiedstate[.]cam Jan 2021; thecsi[.]com Jan 2021; coloradocareerproject[.]com Jan 2021; mailserviceemailout1[.]namecheap[.]com Jan 2021; mail[.]healthrequired[.]work Jan 2021; mail[.]doorbellclub[.]work Jan 2021; mail[.]hollyb1ook[.]work Jan 2021; mail[.]safehealth[.]work Jan 2021; mail[.]remedypro[.]us Jan 2021; mail[.]yourtone[.]casa Jan 2021; mail[.]healthmonitor[.]casa Jan 2021; mailserviceemailout1[.]namecheap[.]com Jan 2021; mail[.]voidemodems[.]casa Jan 2021; mail[.]entend4ded[.]casa Feb 2021; mailserviceemailout1[.]namecheap[.]com Feb 2021; slotcrime[.]guru Feb 2021; mailserviceemailout1[.]namecheap[.]com Feb 2021

There are six messages, from two domains, that are inappropriately caught there. One of those was quasi-spam. Looking at the last 1000, there's only one more "ham" message caught. Seven out of a thousand is a pretty good track record, but when five of those seven are important that does sting. That's the part that's my fault.

Now onto Namecheap.

Almost all of my hostnames at Namecheap are set up to autorenew, with care selecting the ones that are not. At the same time, I have a credit card on file at Namecheap, and it is selected as my default payment method. I don't remember when, but I likely changed my card on file in late 2020, when I had a bunch of things to renew in the October to November period. I know I have twentish pieces of email from them in that period that didn't get deleted.

So it turns out that having autorenew selected and having a card on-file and "default is not sufficent to actually autorenew stuff. You also need to find the hidden configuration page (it is not the regular "edit card" page) that selects a card as enabled for autorenew. Serious, WTF?. Why isn't it with all the other configuration for a credit card?

Anyway, I use my own site regularly, and noticed the outage quickly. It did take a while for all DNS servers to get the message. I was seeing Cloudflare (1.1.1.1), eg, reporting the Namecheap parking page long after Google (8.8.8.8) had it restored.

Grrr.

ASCII art and "ASCII" art


I first had email, and first saw a :-) smiley face in 1990. It was about that time, also, that I was exposed to concrete poetry. Both the smiley and the pictures of words poetry were influential on my mind.

I've had a long lasting love of ASCII art and things near to it since. The first program I saw that could create ASCII art from another image was pbmtoascii from the netpnm package. It worked, but it was kinda disappointing. I had seen, and even made myself, hand drawn ASCII art that was much better than the output of that tool.

$ pnmscale -w 60 < fine.pgm |pgmtopbm |pnminvert |pbmtoascii
 ooo" M o"o" oMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMo"
M oo"o" M o" MMMMM"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM "
o"o M "o M "oMMMMM"oM "MoM oMMMMMoo""MMM"ooM"o""" oMMMMMMM "
o" " M o"o"  MMMMMMMoMoMoMMoMMMMMoMMoMMMMoMMMoMMoM"MMMMMMM "
o""oo o o o"o""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM o"
o"M M M"oM M "o""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"o"o"
"o"" "" o"" ""o"ooo""""M"M"MMMMMMMMMMMMMMMMMMMMMMM""" o"o"oM
MM"MMMMMoo"M"oo ooo"oooMoMoooooo MMM M"o"oo" ooooo"o"M o ooo
MMMM"MM oM"oM"oMoM""MMMMM"MMM"MM MM MMMMMMMMMooooooooooMMM o
""MMMMM Mo"" "   o"M MoMMMMMMMMo"MM MMMoMMM"MM"MM"MM"MMMo"oM
 MM"MM" o     o MoM"o"M"MMoMMMM MM"MMM"MMoMMMMMMMMMMM"MM"o"M
 MMM o"Mo"Mo"o"M Mo" M""MMMMMoM M"oMMMMM"MMMo"MoMMoMMM"o"M"M
 M"o"o"oM" """" "ooM"oMo"MoMMMM"oMMMMM"MMMMM"o"M"MMM""oMMM"M
o"oM"oMo "M"M"M"Mo"oM"o"ooM""MooMMMoMMMMMoM"oM MMM"o"Mo"o"Mo
M Mo"M" "M"oM oMoo""o"oMM  " "MMMM"MMM"MMM"oMM MM MM"Mo"M"oM
"MoM"   o"M MMM"""MM MM"     "M"MMMMM""""M"M"Mo"oM"M"oMoM"Mo
"Mo"     "oMMM     "oMMo    o MM"""       "M MoM"M"oMMooMM"M
"M    o  M MMM      "oMo "   o"oM     "    MM MM"oMMo"MoMM"M
M        "o"MMo    o M M""" M"Mo     o    M"MoM"oMMoMMMoM"M"
o   "    ""o""Mo"o o"M"oMM"M"oMoo o     o MMMoM MMo"MoMM"M"M
         M"M"oooMo"M M"oM M"oMo"ooo oo"M MMoMM"MMoMM"MoM"MoM
o "  "   M"o"M M M "oo" M"oMo"oMo"oM"o"o"MoM"M"MoMMMMMoM"MoM
M       M"M M"oMoo" M "oo " ""o M oooMM"MMo"MMM"MoMoMM"M"MoM
o Moo"o"M M"o"oM M"o" o   "o"MMM"oMoMoMMMo"MMoMM"o"" """"o""
 "oo" M"o"M M"o"oM Mo"oo oo"o"Mo"MooMMoM"M"MoM"Moo""""" " M
o"Mo "o" M "o"o"o"o"oM M oo"Mo" MM MoMM"M"Mo"M"Mo"MMoMoMMMM
 MM "M M M M M M M"o"o"oM M "oMo"Mo"MoMM"M"oMM"Mo"M"M"MoMMM
"oMo""M "o M M M M M M"o"o"o"oM"Mo"MMo"MM"M"oMMMo""MMM"MoMM
"oM "M M Mo M Mo"oM M M M Mo "Mo"oMMoM"MoMM"M "oo"""o"""o"o"
"o"o"oMo M M M"oM M"o"oM Mo" MM"M"oM"M"Mo" oo"M M""Mo"M"oM M

Eventually I learned there is a higher quality option to the program.

$ pnmscale -w 120 < fine.pgm |pgmtopbm |pnminvert |pbmtoascii -2x4
//,|>|i:(<>/|,HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM?`S
SSS?!:?</:?? MMMMH##MMMMMMMHMMMMMHMHMMMMMMMMMMMMMMMMMMMMMH`S
??|!|::?://S!MMMMM}{&|'RTk:=MMMMM|?>dMMMk|qHT|9:?/:MMMMMMM S
::\\>\\\:i|>`HMMMM6HHJbM|Md?MMMMHJ6$dMMMkdMRJLHd?P&M]MMMM}i:
SSS>\:\,,:<??:HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMH,\:
SS|$?S4?(L||/S>/*MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM",}$\
\\</|+`:?:`^`<??>,??"*##HHHHMMMMMMMMMMMMMMMMMMMMHH*"?:,/($([
RH&HHHH6'<&ST&v:$???$vd&pbqdoooo.MMP$$$?$$??::<v>\\\%%>/.vv,
M9MHH6R|S}&\S1%$?H*/H9H9RM9MH6M&:MM:HHH6H6H6H#\b????vo#H&M!?
<9&6M9M:F1>?^'''.<$[\9R6MHHHDM&}|MH:MRHRM6RMH9R6H6MHH&H9H/?k
|HHHHH/\:.    ./$S1S|JRHMHH6M9M!HM\M&RMHHHH&H6MHHHHHRMH&P|&H
:&M$?\$$$Z$}1?$S$>$?v??#RMMHHMH.H\HRMHH&RM9M9T&RM9M&M&F?/Z&&
:H?&|;4S%\??<^????>$&$S+:#HMHHP|?MH6M9RM96M&P??&6HHM>?d&1&$k
|&iD?D#d:&)&ZZ$\?F1%F$$$$?Z?HModH6MH9MHR6M&R|H/H6M$?S&H$|19|
&:/S&]>-?$S$>???$?<$Z+dM*"`"\?MHHHHHHHHHMH$d9&|9*>&$H&?${&$9
HFS$/-  :$S\MMM*"*Hb`HMT .- -`MM9M9RM**+#bR&$&L\{S6H>b$L$&kR
$Fk? .` :Z|MMR- .  ?|&M: .. -:Md#>*'  . .``H?&d1H&>b&kH+RH$&
DZ' . .  &:MM|.- ` .??Mc: ., $v$/-  `. .. .&9)DH$?HH&1&FkM&&
R  - . . |\?MM\ : -.\<?$PP??{47Z- . - .  .d&1c>$$9HH&1&FkkHZ
: .- -   |S}?*&qv\`,&Z/S$$$Z$k&S:   .   >,H&1&k?6&9H&H&S&$9{
 -. `.`  %&4%F>><1Z/|%$$$?FS$$Z/S\;_\v\&\/RH&H$HH&&DR66&&9S&
:- - . `.9%&4SFS$?!?o:<?$$\%Tk$S1%Z$$>::&6kM&FHH&RH&RH19&$9&
b.- -  /7/Z|$7/$?://?$-\b:?/'!???:?v/&M&&kH\6&HH&19H1&&19&19
//?+>|\$$%}S1?$S|k%|//:   '|?HRMP/FPd9&RH17H&&&FR/+^$???$$?\
:S$|S:%Z>}S$?($??|}Z\\\/,v$>??HT/&ZS&&9&1H?M%HH&|???"":`""?:
!ZF$ /||:S:(|||\\\4|?%|$S;v?&1;:H&>&FDFRH$1}&FkR|&9&H&#9&RM:
i$&||)S/?(|))))))?S??S4|%Z/|Z}&/&7/FRHFDF&k$RH&&|:M&DHHH&RH-
i&$||S}!%&:?SS?((((((((|$$?<:$$FR%FFk&9&S$&H$$R6k|9HFRH9&&M.
|&?||SF>|%Z:$S?SSSS?\\\??\\\`&$$|&&&&ZH&19?&&<???:?+?\<+*++|
|Z$\:S$$ $Z:\(}S4%$?L$$)?Z%||&ZH&&&&Z&&&1^`v>T/Z\\$&)F$$$14|

But that still seemed lack luster to me. About 21 years ago, the date I have in the file is 27 Dec 1999, I wrote my own tool that turns gray scale ("pgm") images instead of bitmap ("pbm") images into ASCII art.

pnmscale -w 60 -h 30 < /tmp/fine.pgm | pgmtoascii
zzxxxzmmzzmzzxOWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWmxz
mmmmmzzzzzzz;WWWWMOOWWWWWWMMWWWWWWWMWWWWWWWWWWWWWWWWWWWWWM,z
mmmmzzzzzzzzxWWWWWYYUmxOYCxXWWWWMXXzUWWWUzUOUXUmYzzWWWWWWM,z
zxzzzzzzzzxz,MWWWWOMOUYMYWUXWWWWOYOUUWWWCUWOUUOUXYUWOWWWWY+z
mmmzx++;++xzmxOWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWO+z+
XXXYYYYYYXmmzmxzUWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWMYzUXm
mmmmmzzzmxmzxzXXmzmXYUCOMMMWWWWWWWWWWWWWWWWWWWWWWOUYXzxmXYYY
OOCCCMMOzmYUYXz+XmmmXmXUUYYYXXXm;WWUYYYYYYYmxmXmzmXXXXmx,xzz
MMMMMMMxYUUUUUUUmOUUOMMMMMMMMMMO+WWxMMMMMMMMMUXXXmmzzXUCOMmm
UCMMMMM+UUYmx;,.,zUYzCMMMMMMMMMUXWMzMMMMMMMMMMMMMMMMMMMMMUmC
+CMMMMUz+,    ,zUUUUmYMMMMMMMMMzCWzOMMMMMMMMMMMMMMMMMMMMUmCC
+OMUmzYUUUYXmXUUUUYmmXXCWMWWWMWxMmOMMMMMMMMMMYOMMMMMMMCmYCCU
+OYUmxUYXmmmmmmmmzXUUUUmzCWWWWUmXMMMMMMMMMMMCmmMMMMMCXXCCCCC
xUmCXCUY+UUUUUUUUUUUUUYYUmUUOWXCMWMMMMMMMMMCmCzOMMUXYCOYXCCY
U+UYUUU;mUUUXXXXXXmYUXCWUx;++UMMWMMMMMMMMMUYCOmCUXUCCCYYUCUC
OCUUX;. +UUXMWWUXYOYzOWX.....;MMMMWMMUUUUCOCUOYxYCOOUYUXUCCC
CUCz... ,UmMWM;....XYUW;.....+MOUUX;......zCXCUUOOUYCCCUCCCC
UU;.... .YzWWU......mXWU,..,,zXXX;  .......CCXOOUYCOCCCCCCCC
U,.....  mXYWW+....,+XmYYXmzYUUU,   ...  .YOOUUUUOOCCOOOCCCU
+......  zUXmUCXx;;zYUUUUUUUUUUU,      .x+OOOOUXOOOOOOOCCCCU
.......  XUUUUXXXXYYYYUUUYUUUUUUYz+;+xmUzUOOOOCOOOOOOOCCCCUC
+.....  ;UUYUUUYYXzmmxmXYYYUUUUUUUUUYXmmUOCOOOOOOOOOOOOCCCCC
U,.... ;YYYXYYYYXmxzXY,Xm+zxzzzmmxmmmUOOOCOUOOOOOOOOOCOOCCCC
xzXzz;XYYYYYYYYYYYYzxz,...,mXMMWUYOUUOOOOOCUCOOOUYXXXXXXYYYY
+XXXm+YYXYXYYYXYYYYYYmz+;xXXXXOUXCUYOOOOCOUOUOOOmXmx+++++xm+
xUUY;XXmzmxmXXXXXXXYYYYXmzzmCUzxCCXCOOOOOUCUCOOOXUMOCUUCOOO+
mUUmxYYzmX+zXXXXXXXXYYYYYYYxYUUYCUYCCCCOCCUUCCOOXXOOMOOOOOO+
mUUzmUUxmYzzXXXXXXXXXXXXXXXX+UUCCYCCCCCCCCUCCOOOUzOOOOOOOOO;
mUUxzUUzzYX+YYXXXXXXmXXXXXXX,CCUXUCCCCCCCCUCUXXXXxXXYYYYYYmm
mUUm+UUY;YU+YYYYYYYYYYYYXXYmxCCCCCCCCUCCCz+xmYYYUUUUUUYYYYYY

Later I did things like convert ASCII art back into images in various ways. asciiversion2color is not a great program (and didn't even work for me today, because pamarith has been is named pnmarith on this system, a hazard of the netpbm tools being old and reaching different places from different paths, but when I did git it working:

$ pnmscale -w 120 fine300.ppm > fine.ppm
$ asciiversion2color fine.ppm textfine.ppm
pnmarith: promoting second file to PPM
pnmarith: promoting second file to PPM
pnmarith: promoting second file to PPM
HTML version in textfine.ppm.html
$  cjpeg textfine.ppm > textfine.jpg
This is fine, in three color ASCII art

asciiversion2color creates three pbmascii images, one for each RGB channel (in the "ppm" pixmap), converts the ASCII to text-in-image form, then combines the three with a slight offset.

And texttopnm lets you specify an arbitrary tile for each character, as a way of introducing fonts. It has some code for UTF-8 fonts, but I've mostly used it with historic fonts.

$ (echo scale=5; echo 9/14 ) | bc
.64285
$ pnmscale -w 60 fine300.pgm | pnmscale -yscale .64285 > fine60.pgm
$ pgmtoascii fine60.pgm > fine60.txt
$ texttopnm -s .ppm -d font/9x14 fine60.txt 9x14.pgm
$ pnminvert 9x14.pgm |pnmtopng > 9x14.png
This is fine, IBM circa 1981 style

The 9x14 font is the IBM Monochrome Display Adapter hardware font from circa 1981. Quoting Wikipedia:

Each character is rendered in a box of 9×14 pixels, of which 7×11 depicts the character itself and the other pixels provide space between character columns and lines. [...] Each character cell can be set to one of 256 bitmap characters stored in ROM on the card, and this character set cannot be altered from the built-in hardware code page 437. The only way to simulate "graphics" is through ASCII art.

Most recently, I found someone else's code that was created for emulating monochrome bitmap graphics using Braille characters in Unicode in terminal windows. I loved it immediately, and forked it to add a pbmtodots still image converter.

⢅⢌⢔⠔⡔⡪⢊⢆⢣⢒⢕⢱⢑⢡⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠑⡪
⠕⡕⢕⠕⡱⡡⡃⡇⢕⠜⡰⡱⢀⣿⣿⣿⣿⡿⠿⠿⣿⣿⣿⣿⣿⣿⢿⢿⣿⣿⣿⣿⣿⢿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠈⡪
⡣⡣⡣⢃⡣⡊⡢⢃⢕⢡⠪⡰⢨⣿⣿⣿⣿⣿⡗⢼⣞⠸⠃⣟⢹⣯⡐⠶⣿⣿⣿⣿⣿⢸⣅⡒⠿⣿⣿⣿⣗⠰⢶⣾⢹⡇⢻⠩⠏⠔⣂⣿⣿⣿⣿⣿⣿⣿ ⡪
⢌⢌⠪⠪⡰⢑⢅⠇⡆⡣⠱⠱ ⣿⣿⣿⣿⣿⣯⣽⣷⣸⣥⣿⢸⣿⣍⣥⣿⣿⣿⣿⣷⣸⣯⣩⣵⣿⣿⣿⣗⣼⣿⣟⣸⣇⣷⣼⣌⡛⣛⣿⣹⣿⣿⣿⣿⡗⠠⡣
⢕⢜⢜⢔⠔⡰⡠⡀⡄⡔⢔⢔⢕⡈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠠⡅⣁
⡪⡪⡪⡎⡏⡮⡺⡱⡝⣜⡜⡔⡅⡣⡢⡉⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠛⡰⡽⢜⠔
⠕⠏⠞⠎⠇⠗⠙⣁⣍⡈⠚⠓⠑⠣⡣⣣⣒⢆⢍⣉⠛⠟⠿⠿⢿⢿⢿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⡿⠟⠛⢋⢡⢄⠞⠝⡵⣱⢫
⡿⣾⣳⣷⣯⣿⡿⣯⠃⣔⢏⣏⡯⣒⢆⡡⢬⣡⣡⣡⣩⣤⢦⣾⣴⡶⣴⣴⣤⣤⣤⣤⠠⣿⣿⡟⣩⣩⣩⣉⣍⣩⣉⣉⠡⠥⣥⢤⡢⡆⡧⡫⡣⡳⡱⠑⠂⡤⣄⣅
⣿⢿⣽⡷⣿⢾⣟⠇⢼⢕⡯⣪⣺⢕⡯⣲⡩⢷⠟⠞⢿⡾⣿⢷⣯⣿⣻⣾⣻⣯⣿⡽⢐⣿⣿⡂⣽⡿⣽⣯⡿⣯⣿⣻⢿⣶⢦⣥⣡⣉⣌⣨⢤⣤⣴⡿⣽⣻⠇⡙
⡟⢻⣯⣿⣻⣿⣿⡈⢧⡳⡫⠚⠘⠈⢀ ⢀⢴⢝⡵⣊⢽⣟⣿⡷⣿⣻⣯⣿⡾⣷⡏⢸⣿⡿⢐⣿⣟⡿⣾⣟⡿⣾⣻⢿⣽⢿⣽⡿⣯⡿⣯⣟⣿⣯⡿⣯⡟⣨⢷
⡂⣽⡷⣿⣻⣾⠻⡃⡁⡁  ⠐ ⢀⡴⡹⣕⢯⢎⡇⣸⣿⣽⣿⢿⣯⡿⣾⣟⣿⡃⣽⣿⢃⣿⣻⣽⣿⢿⣽⡿⣯⣿⢿⣽⡿⣷⢿⣯⡿⣯⣿⢾⡷⣟⡟⣠⣟⣽
⡐⣽⣿⢏⠴⢡⢺⣪⢗⡽⣱⣣⢖⡞⣕⣏⢯⢎⡗⠝⣠⢕⡙⠷⣿⣟⣿⡿⣿⣽⣿⠠⡿⢃⣾⣿⣽⡷⣿⣻⣷⣿⢿⣽⣿⡋⢿⣻⡿⣯⣿⢿⣽⣻⡻⢃⢼⣺⣺⣺
⠠⡷⡏⣼⢨⡘⢵⢕⣕⢩⢚⠸⠑⠫⢚⢘⣡⢥⢴⢝⡵⣝⢼⢢⡑⢻⣿⣻⣟⣿⡝⡜⢥⣿⡷⣿⣽⢿⣯⡿⣾⣻⡿⣷⢟⢰⡩⣟⣿⢿⣽⣿⠯⢓⡼⣽⢽⣺⡺⣞
⡆⢟⢨⣗⡇⣟⣶⣥⢁⢞⡵⣫⢏⢯⡺⡕⡧⣳⣫⢞⡞⡮⡫⣃⣏⣤⣋⡛⢿⢿⣤⣾⡿⣷⣿⣯⡿⣿⣽⢿⣯⣿⢿⡽⡢⣟⡆⣟⣿⣟⢗⢣⢮⣳⣯⢓⢱⣻⣽⢱
⢷⡈⣼⢪⢗⡵⡛⠂⠸⡕⡯⣺⠹⣘⣨⣌⣍⣌⡚⠵⣫⢚⣼⣿⠟⠉⠈⠉⢂⠻⣿⡾⣿⡿⣾⣻⣿⣯⣿⣻⣿⣽⢛⡴⡯⣗⡇⢽⡞⢥⢾⢽⢽⣺⡪⣎⢮⡗⡧⣟
⢯⣟⢵⣫⡞⠈  ⠩⣫⢮⢣⣾⣿⣿⠛⠛⠛⢿⣦⠑⣽⣿⠇⠂⠈ ⠂ ⠈⣿⢿⣯⣿⣻⡿⣾⠻⠫⠟⠽⢷⣻⣟⠽⡽⣕⠁⣮⢿⢽⢯⠟⣴⢽⢆⢯⡺⣯⢷
⢟⣺⣽⠊ ⢀⠈ ⠈⢮⡃⣿⣿⡿⠁⢀ ⠂ ⠹⣇⢽⣿⡁⠠ ⠂⠈⡀⠨⣿⡻⠿⠝⠟⠁⠠ ⠄ ⢀ ⠱⣳⡏⣽⢵⣫⢷⣻⡛⣥⡯⣗⣿⢵⣫⡯⣗⣟
⡧⣗⠁ ⠄ ⠄ ⠈⠧⡃⣿⣿⣗ ⡀⠠⠈⢀ ⠗⠸⣿⣧⡀⠄⠐⢀⢄⢨⡢⣖⣕⠃  ⠠ ⡀⠐ ⡀ ⡷⡷⡱⣯⢿⡝⣢⣯⡷⡯⣗⣿⢽⣺⢯⢗⣟
⣟  ⠂ ⠂ ⠄ ⢭⢇⡹⣿⣷⣄ ⠠ ⢀⠠⠡⡧⣩⣉⡛⡓⢛⡡⣜⢮⡫⣞   ⠂ ⢀ ⠄  ⡮⣟⣯⣧⠫⡟⢬⣷⣯⢯⡯⣗⣿⢽⣺⣻⢽⡺
⠅ ⠐ ⠁ ⠂  ⢸⢕⣖⢍⠻⠷⡮⡤⠤⠐⣨⣺⢕⢗⣕⢗⡽⣕⢽⡪⡗⣝⡮⡂⠠ ⠠   ⢀⢤⢨⢯⣗⡷⣯⢷⣡⢿⣺⣞⣟⣾⣳⣻⢽⡺⣺⣻⢼
 ⠈ ⡈ ⠐ ⠂ ⢕⢗⡵⡫⣳⢕⡖⣖⢵⢻⢜⢜⢝⢵⢕⢯⢪⣺⡱⣫⢏⡮⣺⢕⡦⣄⢄⢄⣔⢼⣪⠃⣾⢽⣺⣻⡯⣟⣽⣽⣺⢾⣻⡾⣽⣺⡯⡯⣗⡧⣟
⡌ ⠄ ⠈ ⠄ ⠨⣫⢧⢫⡫⣺⢕⢽⢜⡕⢙⢬⣤⡑⠫⠺⡕⣗⢵⡹⣜⢵⢝⡼⣱⡣⡗⡯⡧⠓⡋⡤⣞⣿⢽⣺⣯⢯⣗⣷⢿⡽⣯⢷⣻⣷⢽⣺⡯⣗⣯⢷
⠷⠂ ⠈ ⠂ ⢤⢝⢎⢞⢕⡝⣜⢕⡯⣪⢔⠡⡒⡍⣋⠂⢶⢦⠌⣈⠊⢃⢋⢃⢋⣘⡈⡥⡤⡆⣷⣻⣽⣳⡯⣯⢺⣺⣻⢾⡽⣽⡽⣽⡽⣞⣞⣟⢾⣫⣗⣿⢽
⡒⢬⢺⠴⡤⡂⢕⡧⡫⡮⣣⡳⣹⢜⢵⢕⢧⢫⡣⡆⡡⠣⠂  ⡀⠁⢜⢪⡿⣿⢿⡏⢼⡽⡏⣾⣳⣟⣞⢷⣻⣝⢾⣫⣯⣯⡯⣗⢛⠳⡙⢓⢋⢋⣋⣚⣊⣚⢹
⠐⡵⡱⣹⠜⢐⢇⢏⠞⡎⡞⡜⣎⢞⢕⢕⢏⢎⡞⡵⢕⡕⡦⡡⡠⡠⣪⠏⢦⡙⢿⡏⢼⢽⡺⣱⣽⣺⡷⡯⣟⣾⢣⣟⢞⣾⡺⣯⢇⢢⣍⡈⡉⠉⠉⢈⠁⢉⣨⠐
⠸⣕⢽⡸⢀⢇⢇⡇⠕⡕⡅⢪⢪⢪⢪⢣⢫⢪⡪⡺⡱⣹⢜⢍⣊⢥⢔⠸⡯⣗⢍⠢⡯⣟⢕⣽⣺⣳⢯⣟⡷⣏⣾⡳⢽⣺⣽⢯⡇⢝⣷⡿⡾⡾⣞⣾⡾⣿⢽⡂
⠸⡵⣻⡊⠤⡫⡮⡊⢪⢪⡂⢕⢕⢕⢕⢕⢵⢱⢕⢝⡜⡎⡮⡣⣣⢇⡗⡅⢫⡳⣳⣪⡿⡽⣸⢮⣗⢿⡽⡾⣝⣞⣞⢼⣻⡺⣞⣿⢎⠸⣷⣻⣟⣿⣻⣾⡽⣯⢿⡀
⢸⡽⣺⡂⢹⡹⣪⡃⢹⢜⡆⠜⣜⢜⢜⢕⢕⢕⢕⢇⢇⢏⢎⢞⢜⡜⣜⢕⠨⣞⡕⣟⣞⡣⣟⣽⣺⡯⡯⡯⣗⡯⡮⣟⣼⢯⢷⢯⣗⠸⣻⣞⣷⣻⣞⣷⣻⣯⢿⠠
⠸⣺⢕⡇⠸⣪⢧⡃⠥⣳⢣⠘⡮⡺⣸⢜⢜⢜⢜⢜⢜⢜⢜⡜⡜⡜⡜⣜ ⡷⣝⣎⢖⡽⣕⣗⣷⢽⣫⡯⣗⣯⡫⣞⠷⠛⢋⣋⢬⣈⢙⠚⠞⠳⠝⠞⠗⠯⠓⢸
⡸⣕⢗⢇⠘⡵⡕⣗⠈⡞⣕⡂⢏⢞⢮⢺⡱⡫⣺⢱⡣⣳⢕⢵⢱⢕⢵⡑⢨⣽⢮⢗⣟⡮⣗⣗⣗⢟⡾⣽⢵⠓⠡⠤⡪⡝⡵⡱⣫⢺⡹⡝⣝⢞⡵⡳⡕⣗⢽⢱

It's no longer ASCII art, by a long strech, but it's very clearly identifiable in a modern text window.