[HN Gopher] Show HN: I wrote a program to convert lines of text ...
       ___________________________________________________________________
        
       Show HN: I wrote a program to convert lines of text into trees
        
       Author : birchb
       Score  : 215 points
       Date   : 2021-03-29 14:50 UTC (8 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | breck wrote:
       | Awesome. You really nailed it. In my experience the output for
       | spreadsheets turns out to be key so good job highlighting that
       | (https://github.com/birchb1024/frangipanni#output-for-
       | spreads...).
       | 
       | One suggestion: it may help to generalize the newline as the node
       | separator. You may already be doing this (my go is rusty) but
       | instead of
       | https://github.com/birchb1024/frangipanni/blob/7543b4ee15ae7...
       | be able to override the "newline" as the node separator, like
       | you've done with the "spacer" param.
       | 
       | What do you do when the same line is encountered?
        
         | shok3001 wrote:
         | really cool! But I think you should have called it "birch"! :)
         | 
         | Any way you could add build instructions to the README?
        
       | eevilspock wrote:
       | I love what it does for log files. Abbreviated example from the
       | README:                   May 10 03:17:06 localhost systemd:
       | Removed slice User Slice of root.         May 10 03:17:06
       | localhost systemd: Stopping User Slice of root.
       | 
       | becomes:                   May 10          03:17:06 localhost
       | systemd           : Removed slice User Slice of root           :
       | Stopping User Slice of root
        
       | kevmoo1 wrote:
       | Super cool, yo! Very unix - do one simple thing well.
        
       | amelius wrote:
       | Looks nice. Perhaps a next step could be an ncurses program that
       | allows you to fold/unfold the trees at arbitrary places, and
       | select entries to reveal their full path (useful for copy+paste).
        
       | mklein994 wrote:
       | Neat. I'll add this to my toolbox.
       | 
       | Somewhat unrelated: I discovered some time ago that the column
       | command (from util-linux) can print trees of hierarchical data
       | (up to 2 levels deep).
       | 
       | From the man page:                 $ echo -e '1 0 A\n2 1 AA\n3 1
       | AB\n4 2 AAA\n5 2 AAB' | column --tree-id 1 --tree-parent 2 --tree
       | 3       1  0  A       2  1  |-AA       4  2  | |-AAA       5  2
       | | `-AAB       3  1  `-AB
       | 
       | column(1): https://github.com/karelzak/util-
       | linux/blob/master/text-util...
        
       | [deleted]
        
       | birchb wrote:
       | Author here: Often I have to digest log files and lists of Azure
       | resource names. I prefer to work with hierarchies of things, so I
       | wrote this simple filter. Turns out to quite handy, especially
       | when combined with awk and its friends.
        
         | jarmitage wrote:
         | Great, very handy! Just FYI `readlink -f` doesn't work on macOS
         | 
         | May I suggest the name txtree?
        
         | jedberg wrote:
         | Very cool tool! Any chance that you're going to add it to
         | Homebrew?
        
       | AnonHP wrote:
       | This is really very nice and useful! I read through the examples
       | and thought about something that would be a good addition and
       | then see that "-skip" was just implemented! I can skip (pun
       | intended) using an additional layer of cut or awk because of
       | this.
       | 
       | The detailed examples are great too, showing different use cases
       | and features.
       | 
       | Thank you very much for creating this tool and sharing it.
        
       | densekernel wrote:
       | What a beautiful idea. Like the application of quick analysis of
       | ls or logs. Although now we are typically outputting JSON and
       | collecting for Kibana.
        
       | mdeck_ wrote:
       | In retrospect, it's not clear to me why I somehow expected this
       | project to be something more literally arboreal. I even got my
       | hopes up further when I clicked the link and saw that photo of
       | plumerias.
       | 
       | Yet, this project is cool enough that I'm not even disappointed.
        
       | rurban wrote:
       | Whoa, he wrote a parser.
       | 
       | This only happens every other decade or so.</sarcasm>
        
         | macintux wrote:
         | > Be kind. Don't be snarky. Have curious conversation; don't
         | cross-examine. Please don't fulminate. Please don't sneer,
         | including at the rest of the community.
         | 
         | https://news.ycombinator.com/newsguidelines.html
        
       | petethepig wrote:
       | Maybe this is not super relevant, but my favorite hack is that
       | any tree-like structure like this can be browsed with ncdu.
       | Here's a gist for breaking down redis traffic by command for
       | example:
       | https://gist.github.com/petethepig/0f33c910fb2edad8969a5775e...
        
         | loevborg wrote:
         | Whoa, I didn't know that! This is super useful as a general-
         | purpose tree viewer!
         | 
         | For the record, the relevant commands are
         | ncdu -o /tmp/files.json
         | 
         | and                   ncdu -f /tmp/files.json
        
         | rakoo wrote:
         | Neat! Is there some documentation on the format ?
        
           | mellosouls wrote:
           | https://dev.yorhel.nl/ncdu/jsonfmt
        
       | softwaredoug wrote:
       | TIL from the README, you can insert `img` tags into a markdown
       | file, and github will honor the align tag, etc
       | 
       | ```
       | 
       | <img src="frangipanni.jpg" alt="A Tree" width="200"
       | align="right">
       | 
       | ```
        
       | [deleted]
        
       | motohagiography wrote:
       | This looks like what I always wanted for normalizing data sets
       | and grepping logs but couldn't articulate. Thank you!
        
       | kazinator wrote:
       | $ find /etc/network | ./frangi.tl       etc:           network:
       | if-post-down.d:                   wireless-tools wpasupplicant
       | avahi-daemon                if-down.d:
       | resolvconf wpasupplicant avahi-autoipd
       | interfaces.d interfaces if-pre-up.d:                   wireless-
       | tools wpasupplicant ethtool                if-up.d:
       | ntpdate wpasupplicant 000resolvconf openssh-server ethtool avahi-
       | autoipd slrn avahi-daemon             $ find /etc/network |
       | ./frangi-cheat.tl        /etc/network                   /if-post-
       | down.d                                  /wireless-tools
       | /wpasupplicant                                  /avahi-daemon
       | /if-down.d                             /resolvconf
       | /wpasupplicant                             /avahi-autoipd
       | /interfaces.d                   /interfaces
       | /if-pre-up.d                               /wireless-tools
       | /wpasupplicant                               /ethtool
       | /if-up.d                           /ntpdate
       | /wpasupplicant                           /000resolvconf
       | /openssh-server                           /ethtool
       | /avahi-autoipd                           /slrn
       | /avahi-daemon            $ cat frangi-cheat.tl
       | #!/usr/bin/env txr       (let (old-path)         (whilet ((line
       | (get-line)))           (whenlet ((path (tok #/[^\/]*/ line))
       | (canon `@{path "/"}`)                     (pos (mismatch path
       | old-path)))             (let ((cpos (max 0 (+ pos -1 [sum [path
       | 0..pos] len]))))               (put-line `@{"" cpos}@{canon
       | [cpos..:]}`))             (set old-path path))))
       | $ cat frangi.tl       #!/usr/bin/env txr            (defstruct
       | (node name) list-builder         name              (:method equal
       | (me) me.name)              (:method ensure-child (me child-name)
       | (let ((children me.(get)))             (or (find child-name
       | me.(get))                 (let ((new-child (new (node child-
       | name))))                   me.(add new-child)
       | new-child))))              (:method print (me stream : pretty-p)
       | (let* ((old-im (set-indent-mode stream indent-code))
       | (old-id (get-indent stream))                  (children me.(get))
       | (is-bottom (none children .(get))))             (unwind-protect
       | (cond                 (children                   (put-line
       | `@{me.name}:` stream)                   (set-indent stream (+
       | old-id 4))                   [mapdo (op print @1 stream)
       | children]                   (when is-bottom
       | (put-char #\newline stream)))                 (t (put-string
       | `@{me.name} `) stream))               (set-indent-mode stream
       | old-im)               (set-indent stream old-id)))))
       | (let ((supernode (new (node :root))))         (whilet ((line
       | (get-line)))           (let ((path (tok #/[^\/]+/ line))
       | (node supernode))             (each ((comp path))
       | (set node node.(ensure-child comp)))))         (each ((top-child
       | supernode.(get)))           (pprinl top-child)))
        
         | kazinator wrote:
         | C version. Maybe this logic should be built into GNU find as an
         | option!                 $ find /etc/network | ./frangi-cheat
         | /etc/network                   /if-post-down.d
         | /wireless-tools                                  /wpasupplicant
         | /avahi-daemon                   /if-down.d
         | /resolvconf                             /wpasupplicant
         | /avahi-autoipd                   /interfaces.d
         | /interfaces                   /if-pre-up.d
         | /wireless-tools                               /wpasupplicant
         | /ethtool                   /if-up.d
         | /ntpdate                           /wpasupplicant
         | /000resolvconf                           /openssh-server
         | /ethtool                           /avahi-autoipd
         | /slrn                           /avahi-daemon            $ cat
         | frangi-cheat.c       #include <stdio.h>       #include
         | <stdlib.h>       #include <string.h>            int main(void)
         | {         char old_line[FILENAME_MAX] = "", line[FILENAME_MAX];
         | while (fgets(line, sizeof line, stdin)) {           char *p =
         | line, *o = old_line, *nl = strchr(line, '\n');
         | if (nl)             *nl = 0;                while (*p && *o) {
         | char *op = p;                  if (*o == '/' && *p == '/')
         | o++, p++;                  size_t lp = strcspn(p, "/");
         | size_t lo = strcspn(o, "/");                  if (lp == lo &&
         | !strncmp(p, o, lp)) {               p += lp;               o +=
         | lp;               printf("%*s", (int) (p - op), "");
         | continue;             }                  p = op;
         | break;           }                puts(p);
         | strcpy(old_line, line);         }              return
         | feof(stdin) ? EXIT_SUCCESS : EXIT_FAILURE;       }
         | 
         | Note: yes, we could swap pointers between two buffers instead
         | of strcpy.
        
       | roydivision wrote:
       | I find I think about things a lot in tree structures,
       | documentation, todo lists, technical information. I'm really keen
       | to give this a go in my work. Thanks!
        
       | jedberg wrote:
       | It's like super enhanced tree command! Very cool!
        
       | shipit wrote:
       | Exceptional!
       | 
       | I am a heavy user for `find <> | xargs grep` -- this makes my
       | life so much sweeter. Thank you @birchb!
        
       | kevinmgranger wrote:
       | I've been thinking about making something like this for a while,
       | this is great!
       | 
       | I always thought it was weird that "do one thing and one thing
       | well" stopped short of dealing with tree representations on the
       | commandline.
        
         | globular-toast wrote:
         | What do you mean? The only reason this didn't exist is nobody
         | did it yet. It doesn't contradict "do one thing and do it
         | well".
        
           | macintux wrote:
           | For me, the problem isn't that it doesn't do one thing well,
           | which is clearly does, it's that there are no other tools to
           | process trees.
           | 
           | So it fits well with the UNIX ethos of a small tool doing one
           | thing well, but not so much the concept of pipelines, which
           | is closely related.
           | 
           | Obviously not this tool's fault.
        
       | lnenad wrote:
       | This looks awesome, great job, thanks for sharing.
        
       | dvirsky wrote:
       | This is a really wonderful idea! Thanks, OP.
        
       ___________________________________________________________________
       (page generated 2021-03-29 23:01 UTC)