[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)