我有PSTricks
一個自訂目錄樹的實現,我覺得它非常有吸引力。我基本上想將整個事情轉換為TikZ
.我設法實現了非常基本的想法TikZ
:我可以建立一個目錄和一個檔案。但我不知道如何將它們相對於前一個項目定位。我確實知道dirtree
包,但我確實喜歡文件和目錄的符號。
\par
在 PSTricks 程式碼中,為每個新項目(檔案或目錄)新增一個段落。我猜我確實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
之前將原樣傳遞給 TikZ 的程式碼。forest
相關節點的上下文仍然可用,我們可以使用eg(.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}