我有PSTricks
一个自定义目录树的实现,我觉得它很有吸引力。我基本上想将整个目录转换为TikZ
。我设法让最基本的想法运行起来TikZ
:我可以创建一个目录和一个文件。但我不知道如何将它们相对于前一个项目定位。我知道dirtree
包,但我确实喜欢文件和目录的符号。
在 PSTricks 代码中,\par
每个新项目(文件或目录)都会添加一个新段落。TikZ
我猜我确实必须将各个节点相对于彼此定位。因此,我必须保存最后一个节点的名称或位置。如何做到这一点?或者有其他完全不同的方法吗?
工作 PSTricks 代码
致谢 J. Stier
代码:
\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
的值指定将在绘制树之后但在forest
环境结束之前按原样传递给 TikZ 的代码。相关节点的上下文仍然可用,我们可以使用例如(.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 设置和一些修改来实现这一点森林代码。对我来说,最棘手的部分是弄清楚如何在内部使用维度的倍数forest
。例如,如何告诉它将某个东西移动 10 倍特定长度或其他长度。最后,我为此使用了临时维度寄存器,但我不确定这是最有效的解决方案。
像以前一样,我们从一些 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}