6

In the code below, made using the "AI" Claude, there is too much copying and pasting of lines like the ones shown below. What is the best way to refactor the full code?

 archivefile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{orange!80}{\faFileArchive}\ ##1 } } } 

Here is the full code.

\documentclass{article} \usepackage{forest} \usepackage{fontawesome5} \definecolor{foldercolor}{RGB}{124,166,198} \definecolor{filecolor}{RGB}{88,88,88} \forestset{ dir tree/.style={ for tree={ font = \sffamily, grow' = 0, child anchor = west, parent anchor= south, anchor = west, calign = first, inner ysep = 1pt, inner xsep = 1.75pt, text depth = 0pt, edge path = { \noexpand \path[draw, \forestoption{edge}] (!u.south west) +(7.5pt,0) |- (.child anchor)\forestoption{edge label}; }, before typesetting nodes={ if n=1 {insert before={[,phantom]}} {} }, fit = band, before computing xy = {l = 15pt}, } }, open/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{foldercolor}{\faFolderOpen}\ ##1 } } }, closed/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{foldercolor}{\faFolder}\ ##1 } } }, file/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{filecolor}{\faFile}\ ##1 } } }, codefile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{filecolor}{\faFileCode}\ ##1 } } }, pdffile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{red!70}{\faFilePdf}\ ##1 } } }, textfile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{filecolor}{\faFile*}\ ##1 } } }, imagefile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{blue!70}{\faFileImage}\ ##1 } } }, archivefile/.style={ before typesetting nodes={ content/.wrap value={ \textcolor{orange!80}{\faFileArchive}\ ##1 } } }, } \begin{document} \subsection*{Exemple d'arborescence de fichiers} \begin{forest} dir tree [system, open [config, closed [settings.conf, textfile] [database.yml, codefile] ] [doc, open [manual.pdf, pdffile] [README.md, textfile] [images, closed [logo.png, imagefile] [banner.jpg, imagefile] ] ] [lib, closed [utils.py, codefile] [helpers.js, codefile] [archive.zip, archivefile] ] [test, open [test\_unit.py, codefile] [test\_integration.py, codefile] [fixtures, closed [data.json, file] ] ] ] \end{forest} \subsection*{Exemple simple} \begin{forest} dir tree [system, open [config, closed] [Dog, closed] [lib, closed] [test, closed] ] \end{forest} \end{document} 

enter image description here

9
  • 1
    what do you mean by 'factorise'? I know how to do this for integers ... I guess it has a different meaning here. (this is not a criticism. I just do not know lots of the terminology people use here.) you might mean 'parametise`, but I think you'd say that ... Commented 17 hours ago
  • 1
    your code would be less verbose if you used features from forest 2.1 rather than only those from older versions. Commented 17 hours ago
  • 1
    should this code have an attribution? it's hard to believe you came up with this by reading a current copy of the manual, so I'm assuming it was written 8+ years ago, possibly pre forest 2.0, but certainly pre 2.1.5. Commented 16 hours ago
  • The attribution comes from a guy named Claude. ;-) Commented 15 hours ago
  • 1
    @cfr I think that they meaning "refactoring", a software technique to improve complex systems, that is often simply used to mean "correct the rookie errors". See martinfowler.com/books/refactoring.html Commented 1 hour ago

1 Answer 1

13

I do not know what is meant by 'factorise' here1.

Strategies:

  1. Use features of Forest 2.1, published 8 years ago, rather than relying only on those available in older versions.
  2. Use standard TikZ methods to simplify the code and reduce duplication e.g. styles.
  3. Optionally, use handlers to make the code more succinct.

(1) greatly simplifies the code. (2) greatly reduces duplication. (3) has costs as well as benefits, but an implementation is now included below.

\documentclass[border=10pt,tikz]{standalone} \usepackage[edges]{forest} \usepackage{fontawesome5} \definecolor{foldercolor}{RGB}{124,166,198} \definecolor{filecolor}{RGB}{88,88,88} % ateb: https://tex.stackexchange.com/a/755230/ % cwestiwn projetmbc: https://tex.stackexchange.com/q/755225/ % but the original origin isn't identified - looks like Medina's? \forestset{ fa dir tree/.style={ for tree={ font = \sffamily, folder, grow' = 0, inner ysep = 1pt, inner xsep = 1.75pt, }, }, fa/.style 2 args={ before typesetting nodes={ content/.process={Ow{content}{ \textcolor{#1}{#2}\ ##1 }% }, }, }, open/.style={ fa={foldercolor}{\faFolderOpen}, }, closed/.style={ fa={foldercolor}{\faFolder}, }, file/.style={ fa={filecolor}{\faFile}, }, codefile/.style={ fa={filecolor}{\faFile}, }, pdffile/.style={ fa={red!70}{\faFilePdf}, }, textfile/.style={ fa={filecolor}{\faFile*}, }, imagefile/.style={ fa={blue!70}{\faFileImage}, }, archivefile/.style={ fa={orange!80}{\faFileArchive}, }, } \begin{document} \begin{forest} fa dir tree [system, open [config, closed [settings.conf, textfile] [database.yml, codefile] ] [doc, open [manual.pdf, pdffile] [README.md, textfile] [images, closed [logo.png, imagefile] [banner.jpg, imagefile] ] ] [lib, closed [utils.py, codefile] [helpers.js, codefile] [archive.zip, archivefile] ] [test, open [test\_unit.py, codefile] [test\_integration.py, codefile] [fixtures, closed [data.json, file] ] ] ] \end{forest} \begin{forest} fa dir tree [system, open [config, closed] [Dog, closed] [lib, closed] [test, closed] ] \end{forest} \end{document} 

more complex and simpler pair of trees

Edit

I would not recommend using a loop here for reasons explained in the comments.

If anything, I would use a handler, as mentioned above.

The reason I don't necessarily recommend this is that you do not really gain much in this case in terms of concision or flexibility. The number of file/directory types is small and the above definitions are very short. Moreover, they are very clear: anybody who knows only a little pgf/tikz will see immediately how to define an additional style, if required.

I like custom handlers, but they obviously are that much less efficient2, and they can make code more obscure. It's not clear to me that the code above is better rewritten this way:

\documentclass[border=10pt,tikz]{standalone} \usepackage[edges]{forest} \usepackage{fontawesome5} \definecolor{foldercolor}{RGB}{124,166,198} \definecolor{filecolor}{RGB}{88,88,88} % ateb: https://tex.stackexchange.com/a/755230/ % cwestiwn projetmbc: https://tex.stackexchange.com/q/755225/ % but the original origin isn't identified - looks like Medina's? \forestset{ fa dir tree/.style={ for tree={ font = \sffamily, folder, grow' = 0, inner ysep = 1pt, inner xsep = 1.75pt, }, }, fa/.style 2 args={ before typesetting nodes={ content/.process={Ow{content}{ \textcolor{#1}{#2}\ ##1 }% }, }, }, /handlers/.fa/.code 2 args={% \edef\projetmbctemptpath{\pgfkeyscurrentpath}% \pgfkeys{% \pgfkeyscurrentpath/.style={% fa={#1}{#2}, }, }% }, open/.fa={foldercolor}{\faFolderOpen}, closed/.fa={foldercolor}{\faFolder}, file/.fa={filecolor}{\faFile}, codefile/.fa={filecolor}{\faFile}, pdffile/.fa={red!70}{\faFilePdf}, textfile/.fa={filecolor}{\faFile*}, imagefile/.fa={blue!70}{\faFileImage}, archivefile/.fa={orange!80}{\faFileArchive}, } \begin{document} \begin{forest} fa dir tree [system, open [config, closed [settings.conf, textfile] [database.yml, codefile] ] [doc, open [manual.pdf, pdffile] [README.md, textfile] [images, closed [logo.png, imagefile] [banner.jpg, imagefile] ] ] [lib, closed [utils.py, codefile] [helpers.js, codefile] [archive.zip, archivefile] ] [test, open [test\_unit.py, codefile] [test\_integration.py, codefile] [fixtures, closed [data.json, file] ] ] ] \end{forest} \begin{forest} fa dir tree [system, open [config, closed] [Dog, closed] [lib, closed] [test, closed] ] \end{forest} \end{document} 

This produces exactly the same output and the style definitions are more concise, but it is also rather less obvious what they do. Compare e.g.

 /handlers/.fa/.code 2 args={% \edef\projetmbctemptpath{\pgfkeyscurrentpath}% \pgfkeys{% \pgfkeyscurrentpath/.style={% fa={#1}{#2}, }, }% }, open/.fa={foldercolor}{\faFolderOpen}, 

with

 open/.style={ fa={foldercolor}{\faFolderOpen}, }, 

In both cases, you'd have to lookup the fa style, but in the first, you also have to figure out what .fa does and that means looking up what \pgfkeyscurrentpath refers to, unless you happen to know already3.

However, if you have dozens of these, just annotate the code with an explanation and use the handler.

1I think this is something you do with numbers - paradigmatically, integers. 2But probably not a priority since we are using forest already. 3In which case, you probably wouldn't be asking this question :-).

7
  • I talk about code refactoring : en.wikipedia.org/wiki/Code_refactoring Commented 15 hours ago
  • Could we also use a kind of loop for all the textfile/.style={fa={filecolor}{\faFile*},} like lines? Commented 15 hours ago
  • @projetmbc you could, but I do not think it would be worth the trouble for code this short and simple. your can't use a \foreach type loop because it forms a group. you cannot use .list because you have 3 arguments. you could use 2 levels of split. i.e. the first split sends the arguments to a style which splits each argument into three and passes those to code which creates the style. but you need a lot of more complex code to avoid duplicating a small amount of simple, easily understood code. I would not consider that an improvement. a handler would be better, IMHO. Commented 15 hours ago
  • @projetmbc or you could use one .list and then split. or you could loop using your favourite implementation of loops over \forestset. e.g. you could do it with expl3. but then you have the problem of syntax and cat code differences. pgf + expl3 does not mix well, in my experience. that's even more true of forest. Commented 15 hours ago
  • 1
    @projetmbc see edit above. I would rather this than a loop, though split could be made to work here, if required. Commented 12 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.