У меня есть PSTricks
реализация пользовательского дерева каталогов, которая мне кажется довольно привлекательной. По сути, я хочу преобразовать все это в TikZ
. Мне удалось реализовать самую простую идею в TikZ
: я могу создать каталог и файл. Но я понятия не имею, как расположить их относительно предыдущего элемента. Я знаю оdirtree
package, но мне нравятся символы для файлов и каталогов.
В коде PSTricks добавляется новый параграф \par
для каждого нового элемента (файла или каталога). В TikZ
мне нужно позиционировать отдельные узлы относительно друг друга, я полагаю. Поэтому мне нужно сохранить имя или местоположение последнего узла. Как это можно сделать? Или есть совершенно другой способ?
Рабочий код PSTricks
Благодарности Дж. Стиру
Код:
\documentclass{standalone}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{graphicx}
\usepackage{pstricks, pst-node, pstricks-add}
% ---------------------------
% PST-Directory-Tree
% ---------------------------
% Counter
\newcounter{leaves}
\newcounter{directories}
\newlength{\parskipnew}
\setlength{\parskipnew}{\parskip}
% Environment
\newenvironment{directory}[2][\linewidth]{%
\setcounter{leaves}{0}%
\addtocounter{directories}{1}%
\edef\directoryname{D\thedirectories}%
\begin{minipage}[t]{#1}%
\setlength{\parindent}{\linewidth}%
\addtolength{\parindent}{-\dirshrink\parindent}%
\parskip2pt%
\noindent%
\Rnode[href=-\dirshrink]{\directoryname}{%
\parbox[t]{#1}{%
\parbox[c]{0.65cm}{%
\centering%
\includegraphics[scale=0.7]{Figures/Icons/ordner}%
}%
\hspace{.2em}\texttt{#2}}%
}%
\par
}
{\end{minipage}\vspace{0.5\parskipnew}}
% Commands
\newcommand{\file}[2][]{%
\addtocounter{leaves}{1}%
\edef\leaflabel{L\theleaves\directoryname}%
\par
\Rnode{\leaflabel}{%
\parbox[t]{\dirshrink\linewidth}{%
\parbox[c]{0.65cm}{%
\centering\includegraphics[scale=0.7]{Figures/Icons/datei}%
}%
\hspace{.2em}\texttt{#2}\hfill#1}%
}%
\ncangle[angleA=270,angleB=180,armB=0,nodesepA=3pt,nodesepB=2pt]{\directoryname}{\leaflabel}%
\par%
}
%
\newcommand{\dir}[2][]{%
\addtocounter{leaves}{1}%
\edef\leaflabel{L\theleaves\directoryname}%
\par
\Rnode{\leaflabel}{%
\parbox[t]{\dirshrink\linewidth}{%
\parbox[c]{0.65cm}{%
\centering%
\includegraphics[scale=0.7]{Figures/Icons/ordner}%
}%
\hspace{.2em}\texttt{#2}\hfill#1%
}%
}%
\ncangle[angleA=270,angleB=180,armB=0,nodesepA=3pt,nodesepB=2pt]{\directoryname}{\leaflabel}%
\par%
}
%
\newcommand{\fother}[2][]{%
\addtocounter{leaves}{1}%
\edef\leaflabel{L\theleaves\directoryname}%
\par
\Rnode{\leaflabel}{%
\parbox[t]{\dirshrink\linewidth}{%
\hspace{0.5em}\normalfont{\textit{#2}}\hfill#1
}%
}%
\ncangle[angleA=270,angleB=180,armB=0,nodesepA=3pt,nodesepB=2pt]{\directoryname}{\leaflabel}%
\par%
}
%
\newcommand{\dirfile}[1]{%
\addtocounter{leaves}{1}%
\edef\leaflabel{L\theleaves\directoryname}%
\par
\Rnode{\leaflabel}{%
\parbox[t]{\dirshrink\linewidth}{#1}%
}%
\ncangle[angleA=270,angleB=180,armB=0,nodesepA=3pt,nodesepB=2pt]{\directoryname}{\leaflabel}%
\par%
}
%
\newcommand{\dirshrink}{0.967}
%
\newcommand{\optional}[1]{{\normalfont\mdseries$<$\hspace{0.05em}{\itshape #1}\hspace{0.15em}$>$}}
% ---------------------------
% Document
% ---------------------------
\begin{document}
\begin{pspicture}(6,12.5)
\psset{linewidth=0.5pt}
\rput[lb](0,0.5){
\begin{directory}{\optional{Project}}
\dirfile{%
\begin{directory}{Figures}
\file{fig-1.eps}
\file{fig-1.pdf}
\file{fig-1.png}
\file{fig-2.eps}
\file{fig-2.pdf}
\file{fig-2.png}
\end{directory}%
}
% %
\dirfile{%
\begin{directory}{Scripts}
\file{install\_package\_A.sh}
\file{install\_package\_B.sh}
\file{install\_package\_C.sh}
\end{directory}
}
% %
\dirfile{%
\begin{directory}{Sections}
\file{section-1.tex}
\file{section-2.tex}
\file{section-3.tex}
\file{literature.bib}
\end{directory}
}
% %
\file{project.kilepr}
\file{project.tex}
% %
\end{directory}}
\end{pspicture}
\end{document}
Результат:
Начальный код TikZ
\documentclass{standalone}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{graphicx}
% \usepackage{pstricks, pst-node, pstricks-add}
\usepackage{tikz}
\usetikzlibrary{backgrounds}
\usetikzlibrary{fit}
\usetikzlibrary{positioning}
% ---------------------------
% PST-Directory-Tree
% ---------------------------
% Counter
\newcounter{leaves}
\newcounter{directories}
\newlength{\parskipnew}
\setlength{\parskipnew}{\parskip}
% Environment
\newenvironment{directory}[2][\linewidth]{%
\setcounter{leaves}{0}%
\addtocounter{directories}{1}%
\edef\directoryname{D\thedirectories}%
\begin{minipage}[t]{#1}%
\setlength{\parindent}{\linewidth}%
\addtolength{\parindent}{-\dirshrink\parindent}%
\parskip2pt%
\noindent%
\node (i1\directoryname) {\includegraphics[scale=0.7]{Figures/Icons/ordner}};
\node[right = .2em of i1\directoryname] (i2\directoryname) {\texttt{#2}};
\begin{scope}[on background layer]
\node[fit={(i1\directoryname) (i2\directoryname)}, fill=lightgray, inner sep=0pt] (\directoryname) {};
\end{scope}
}
{\end{minipage}\vspace{0.5\parskipnew}}
% Commands
\newcommand{\file}[2][]{%
\addtocounter{leaves}{1}%
\edef\leaflabel{L\theleaves\directoryname}%
\node[below right= 0.5ex and 0.5em of \directoryname.south](i1\leaflabel) {\includegraphics[scale=0.7]{Figures/Icons/datei}};%
\node[right = .2em of i1\leaflabel] (i2\leaflabel) {\texttt{#2}};
\node[fit={(i1\leaflabel) (i2\leaflabel)}, inner sep=0pt] (\leaflabel) {};
\draw (\directoryname.south) |- (\leaflabel.west);
}
%
\newcommand{\dirshrink}{0.967}
%
\newcommand{\optional}[1]{{\normalfont\mdseries$<$\hspace{0.05em}{\itshape #1}\hspace{0.15em}$>$}}
% ---------------------------
% Document
% ---------------------------
\begin{document}
\begin{tikzpicture}(10,10)
\begin{directory}{\optional{Project}}
\file{fig-1.eps}
\file{fig-2.eps}
\end{directory}
\end{tikzpicture}
\end{document}
Необходимые файлы изображений
решение1
Я только что понял, что вы предоставили изображения для иконок. О, ну. Вот чистое решение TikZ. По крайней мере, оно используетлескоторый основан на TikZ. Кроме того, он использует две pic
s для иконок, которые затем используются в дереве.
Это позволяет использовать новую edges
библиотеку длялескоторый включает folder
стиль для деревьев каталогов. Он также может рисовать папки, но они не очень похожи на папки или файлы, поэтому, вероятно, не оправдают ваших ожиданий. Здесь стиль используется только для автоматизации структурного вида дерева.
Этомногопроще с edges
библиотекой, так как раньше для этого требовалась настройка подходящего стиля дерева.
Загружаем пакеты и нужную нам библиотеку.
\documentclass[tikz, border=10pt, multi]{standalone}
\usepackage{forest}
\useforestlibrary{edges}
\begin{document}
Применить значения по умолчанию из edges
библиотеки. Если вы планируете рисовать другие виды деревьев, поместите это в группу TeX, чтобы ограничить область действия.
\forestapplylibrarydefaults{edges}
Мы создаем две pic
буквы S для иконок.
\tikzset{%
Для форм папок mkdir
.
mkdir/.pic={%
\draw [pic actions] (-1.5ex,-1ex) -- ++(0,2ex) -- ++(.25ex,.25ex) -- ++(1.25ex,0) -- ++(.25ex,-.25ex) -- ++(1.25ex,0) |- cycle;
},
Для файловых форм touch
.
touch/.pic={%
\draw [pic actions] (-1ex,-1.5ex) |- ++(1.25ex,3ex) edge ++(.75ex,-.75ex) |- ++(.75ex,-.75ex) |- cycle;
}
}
Теперьлес-специфичный стиль, optional
который мы будем использовать вместо \optional{}
.
\forestset{%
optional/.style={%
content/.wrap value={$<$\hspace{0.05em}\normalfont\itshape ##1\hspace{0.15em}$>$},
}
}
Теперь о самом дереве в forest
окружающей среде.
\begin{forest}
Сначала немного настройки.
for tree={
Примените эти настройки ко всему дереву.
font=\ttfamily,
Мы хотим, чтобы дерево росло вправо, т.е. под углом, 0
и нам нужно поменять порядок дочерних элементов на обратный, иначе оно получится перевернутым.
grow'=0,
Примените folder
стиль, который задает pstree
структуру шрифта.
folder,
Все терминальные узлы являются файлами, а все остальные — каталогами. Таким образом, мы можем автоматически добавлять значки, проверяя, есть ли у каждого узла какие-либо дочерние элементы (нетерминальные) или нет (терминальные).
if n children=0{
Нам нужно немного отложить корректировку, чтобы установить исходное содержимое. Затем мы добавим немного места слева, чтобы освободить место для значка.
before typesetting nodes={
content/.wrap value={\hspace*{2.5ex}#1},
},
Мы добавим аннотацию TikZ, которая отрисует pic
для значка в соответствующем месте. tikz
Значение указывает код, который будет передан в TikZ как есть после рисования дерева, но до forest
завершения среды. Контекст соответствующего узла по-прежнему доступен, и мы можем использовать , например, (.west)
для доступа к west
якорю текущего узла, чтобы разместить pic
соответствующим образом.
tikz={%
\pic [xshift=1.5ex] at (.west) {touch};
}
}{
Теперь делаем то же самое для нетерминальных узлов. pic
Здесь варьируются только интервал и .
before typesetting nodes={
content/.wrap value={\hspace*{3.5ex}#1},
},
tikz={%
\pic [xshift=2ex] at (.west) {mkdir};
}
}
},
Теперь перейдем к самому дереву, начнем с корня, optional
к которому мы хотим применить стиль.
[Project, optional
Первый подкаталог
[Figures
и его содержимое, которое на языке дерева является дочерними узлами.
[fig-1.eps]
[fig-1.pdf]
[fig-1.png]
[fig-2.eps]
[fig-2.pdf]
[fig-2.png]
]
Конец первого подкаталога. Начало второго подкаталога, который является вторым потомком корневого узла дерева.
[Scripts
А его содержимое, как и прежде, — дети.
[install\_package\_A.sh]
[install\_package\_B.sh]
[install\_package\_C.sh]
]
Продолжайте добавлять подкаталоги и их содержимое.
[Sections
[section-1.tex]
[section-2.tex]
[section-3.tex]
[literature.bib]
]
Последние две записи находятся на уровне чуть ниже корня, но они сами по себе являются файлами, т.е. дочерними элементами корня, которые также являются конечными узлами.
[project.kilepr]
[project.tex]
Закройте корень.
]
И закончим елку.
\end{forest}
\end{document}
ПЕРЕСМОТРЕННЫЙ ВАРИАНТ
Однако нам может понадобиться больше гибкости. Например, нам может понадобиться более простое изменение размера иконок/символов для файлов и каталогов, а также управление расстояниями между путем и иконкой, с одной стороны, и иконкой и именем, с другой.
Мы можем сделать это с помощью немного более мощного набора настроек TikZ и некоторых модификацийлесcode. Для меня самой сложной частью этого оказалось выяснить, как использовать кратные измерения внутри forest
. Например, как сказать ему сдвинуть что-то на 10 раз больше определенной длины или что-то в этом роде. В конце концов, я использовал для этого регистр измерения scratch, но я не уверен, что это самое эффективное решение.
Начнем, как и прежде, с настройки TikZ.
\tikzset{%
Мы хотим, чтобы некоторые макросы содержали различные измерения, чтобы их можно было легко изменять. Для этого мы будем использовать 4 макроса.
\mkdirsize
для базового размера значка каталога (ширина = 12 x базовый размер);touchsize
для базового размера значка файла (ширина = 8 x базовый размер);\iconsep
для расстояния между значком и названием;\iconsepfrompath
для расстояния между путем и значком.
Их можно будет изменять как стили TikZ.
mkdir size
;touch size
;icon sep
;icon sep from path
.
Вот конфигурация:
mkdir size/.store in=\mkdirsize,
touch size/.store in=\touchsize,
icon sep/.store in=\iconsep,
icon sep from path/.store in=\iconsepfrompath,
Мы гарантируем, что все параметры имеют значение по умолчанию.
mkdir size=.25ex,
touch size=.25ex,
icon sep=1.5ex,
icon sep from path=1ex,
Теперь мы хотим, чтобы наши pic
s основывались на значениях mkdir size
и touch size
.
Мы также помещаем самую левую точку каждого значка pic
в положение x=0
, а не сдвигаем ее влево, поскольку это упрощает правильную настройку расположения значков в дереве.
mkdir/.pic={%
\draw [pic actions] (0,-4*\mkdirsize) -- ++(0,8*\mkdirsize) -- ++(\mkdirsize,\mkdirsize) -- ++(5*\mkdirsize,0) -- ++(\mkdirsize,-\mkdirsize) -- ++(5*\mkdirsize,0) |- cycle;
},
touch/.pic={%
\draw [pic actions] (0,-6*\touchsize) |- ++(5*\touchsize,12*\touchsize) edge ++(3*\touchsize,-3*\touchsize) |- ++(3*\touchsize,-3*\touchsize) |- cycle;
},
}
Мы также хотим адаптировать преамбулу дерева для использования значений icon sep
и icon sep from path
.
\begin{forest}
Однако начнем мы как и прежде.
for tree={
font=\ttfamily,
grow'=0,
folder,
Изменения касаются указания того, где должны быть узлы и пространства, которое должно быть вставлено перед содержимым основного узла. С этим битом у меня были проблемы. Это работает, но это может быть не самым эффективным или действенным решением.
if n children=0{
before typesetting nodes={
Мы используем измерение регистра скретча, чтобы рассчитать, сколько места следует добавить к содержимому узла.
tempdima=\iconsepfrompath+\iconsep+8*\touchsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
Затем нам также необходимо сместить вправо pic
на соответствующую величину.
tikz={%
\pic [xshift=\iconsepfrompath] at (.west) {touch};
},
}{
В случае с узлами каталога есть сложность, потому что один из них находится в корне, и его pic
не следует сдвигать прямо сюда, и к содержимому узла нужно добавить меньше места. Поэтому мы рассмотрим этот случай отдельно.
if level=0{
Не перемещайте символ каталога.
tikz={%
\pic at (.west) {mkdir};
},
Добавьте пробел к узлу, но не добавляйте значение, icon sep from path
так как это не имеет значения для корневого каталога.
before typesetting nodes={
tempdima=\iconsep+12*\mkdirsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
Теперь перейдем к некорневым каталогам.
}{
tikz={%
\pic [xshift=\iconsepfrompath] at (.west) {mkdir};
},
before typesetting nodes={
tempdima=\iconsepfrompath+\iconsep+12*\mkdirsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
},
},
},
Полный код:
\documentclass[tikz, border=10pt, multi]{standalone}
\usepackage{forest}
\useforestlibrary{edges}
\begin{document}
\forestapplylibrarydefaults{edges}
\tikzset{%
mkdir/.pic={%
\draw [pic actions] (0,-4*\mkdirsize) -- ++(0,8*\mkdirsize) -- ++(\mkdirsize,\mkdirsize) -- ++(5*\mkdirsize,0) -- ++(\mkdirsize,-\mkdirsize) -- ++(5*\mkdirsize,0) |- cycle;
},
touch/.pic={%
\draw [pic actions] (0,-6*\touchsize) |- ++(5*\touchsize,12*\touchsize) edge ++(3*\touchsize,-3*\touchsize) |- ++(3*\touchsize,-3*\touchsize) |- cycle;
},
mkdir size/.store in=\mkdirsize,
touch size/.store in=\touchsize,
icon sep/.store in=\iconsep,
icon sep from path/.store in=\iconsepfrompath,
mkdir size=.25ex,
touch size=.25ex,
icon sep=1.5ex,
icon sep from path=1ex,
}
\forestset{%
optional/.style={%
content/.wrap value={$<$\hspace{0.05em}\normalfont\itshape ##1\hspace{0.15em}$>$},
},
}
\begin{forest}
for tree={
font=\ttfamily,
grow'=0,
folder,
if n children=0{
before typesetting nodes={
tempdima=\iconsepfrompath+\iconsep+8*\touchsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
tikz={%
\pic [xshift=\iconsepfrompath] at (.west) {touch};
},
}{
if level=0{
tikz={%
\pic at (.west) {mkdir};
},
before typesetting nodes={
tempdima=\iconsep+12*\mkdirsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
}{
tikz={%
\pic [xshift=\iconsepfrompath] at (.west) {mkdir};
},
before typesetting nodes={
tempdima=\iconsepfrompath+\iconsep+12*\mkdirsize,
content/.wrap value={\expandafter\hskip \foresteregister{tempdima}#1},
},
},
},
},
[Project, optional
[Figures
[fig-1.eps]
[fig-1.pdf]
[fig-1.png]
[fig-2.eps]
[fig-2.pdf]
[fig-2.png]
]
[Scripts
[install\_package\_A.sh]
[install\_package\_B.sh]
[install\_package\_C.sh]
]
[Sections
[section-1.tex]
[section-2.tex]
[section-3.tex]
[literature.bib]
]
[project.kilepr]
[project.tex]
]
\end{forest}
\end{document}
решение2
Это не совсем ответ на ваш вопрос, но я считаю, что это полезный макет, который можно легко поддерживать и изменять. Он также допускает некоторую нестандартную структуру. Я пока не разобрался, как включать значки файлов. Он также работает лучше всего, если вы сохраняете столбцы управления вкладками достаточно хорошо выровненными.
\documentclass{standalone}
\usepackage{menukeys}
\newmenumacro{\nixfile}[/]{hyphenatepaths}
\newmenumacro{\nixpath}[/]{hyphenatepathswithfolder}
\newmenumacro{\winpath}[bslash]{hyphenatepathswithfolder}
\newmenumacro{\winfile}[bslash]{hyphenatepaths}
\begin{document}
\begin{minipage}{\textwidth}
\begin{tabbing}
\hspace{1em}\=\hspace{1em}\=\hspace{1em}\=\hspace{12em}\=\\\kill
\nixpath{root/path } \>\>\>\> Main Root \+\\
\nixpath{subfolder } \>\>\> Specialized subfolder \+\\
\nixfile{subfile } \>\> Some file \-\\
\nixfile{wierd/file} \>\>\> Important subfile, unimportant subfolders \\
\nixfile{file } \>\>\> Main file \\
\end{tabbing}
\end{minipage}
\end{document}