Directory Structure Graphical Treefication
JavaScript (ES6), 237 128 bytes
f=(s,r=`.\n`+s.replace(/^ */gm,"$&└── "),q=r.replace(/^(.*)( |└)(?=.+\n\1[|└])/m,(_,i,j)=>i+`|├`[+(j>' ')]))=>q==r?r:f(s,q)
Where \n
represents the literal newline character. Explanation: r
is created from s
by prepending the .
line and inserting the └──
at the end of each line's indent. This is now correct for the last line of the input, but each └
must be "extended" upwards as far as possible. This is the job of q
, which searches for a └
and recursively replaces the spaces directly above it with |
s unless it reaches another └
which gets turned into ├
instead. The recursion ends when no further replacements can be made. Note that if the character above the └
is a space or a └
then the text to the left of the └
is always the same as that on the previous line so I can just use \1
to test that the one character is above the other.
Retina, 88 bytes
m`^ *
$&├──
{4}
|
T+`|├` └`(?<=(.)*).(?!.+¶(?>(?<-1>.)*)[|├└])
^
.¶
Try it online!
I suppose I could technically count this as one byte per character by swapping out some characters, reading the source as ISO 8859-1 and then finding a single-byte encoding for the output which contains ├
and └
, but I can't be bothered to work out the details right now. (For the record, that would be 72 bytes.)
Explanation
Stage 1: Substitution
m`^ *
$&├──
We start by matching the indentation on each line and inserting ├──
.
Stage 2: Substitution
{4}
|
Next, we match every group of 4 spaces and replace the first with a |
. Now all that needs fixing is |
that go to the bottom of the output and ├
that should be └
. Both of those cases can be recognised by looking at the character directly below the one we potentially want to change.
Stage 3: Transliteration
T+`|├` └`(?<=(.)*).(?!.+¶(?>(?<-1>.)*)[|├└])
The (?<=(.)*)
counts how many characters precede the match on the current line to measure it's horizontal position. Then the lookahead skips to the next line with .+¶
, matches as many characters as we've captured in group 1
with (?>(?<-1>.)*)
(to advance to the same horizontal position) and then checks whether the next character (i.e. the one below the actual match) is one of |├└
. If that's the case, the match fails, and in all other cases it succeeds and the stage substitutes spaces for |
and └
for ├
.
This won't fix all characters in a single run, so we apply this stage repeatedly with the +
option until the output stops changing.
Stage 4: Substitution
^
.¶
All that's left is the first line, so we simply match the beginning of the string and prepend a .
and a linefeed.