For the following, it is assumed that two folders are needed to host all the generated files: one for the output PDF file (suppose the folder name is PDF) and the other for all the auxiliary files generated by pdflatex (I neamed the folder AuxDirectory). Two approaches are considered: TeXstudio and Latexmk.
TeXstudio
First, TeXstudio needs to understand where to put the output files. SO, two options will be changed: --aux-directory
for auxiliary files and --output-directory
for PDF output file.
Go to Options > Configure TeXstudio > Commands
. In pdfLaTeX field, add --aux-directory=AuxDirectory --output-directory=PDF before %.tex
.
In case of using BibTeX:
In BibTeX field, change it from bibtex.exe %
to bibtex.exe AuxDirectory/% -include-directory=AuxDirectory
. This is very important step to make the bibliography tool able to find aux files.
In case of using Biber:
In Biber field, change it from biber.exe %
to bibtex.exe AuxDirectory/%
.
To make TeXstudio able to locate PDF output file for external pdf readers, in the left tab menu, go to Build > Additional Search Paths:
and write the folder name you wish to store log file into (I chose AuxDirectory) and the folder name that TeXstudio asks the external PDF viewer to go there to open the file.
Now, you are able to make a clean and well organized directory for the LaTeX project.
Latexmk
Latexmk is a powerful automation tool and also smart. More information is given in its documentation. The same previous options (--aux-directory
and --output-directory
) are used since the same engine/compiler is given.
For example, if you want to compile a file named main.tex
using latexmk you have to run this command (providing that the command current directory is the same as the one hosting main.tex
)
latexmk -quiet -bibtex -aux-directory=AuxDirectory --output-directory=PDF -pdf -pdflatex="pdflatex -synctex=1 -interaction=nonstopmode" main.tex
Latexmk is very smart and able to determine the required number of pdfLaTeX and BibTeX runs to properly generate the PDF output file.
Additionally, if you found it very annoying to open the command window each time you want to compile your document, you can create a bash file that opens the command window and runs the previous command by just double-clicking it.
In order to do so, create a file with extension .bat
in the same working directory of main.tex
and edited it to have
cmd /k latexmk -quiet -bibtex -aux-directory=AuxDirectory --output-directory=PDF -pdf -pdflatex="pdflatex -synctex=1 -interaction=nonstopmode" main.tex.
Any other suggestions/improvements are highly appreciated.
Here is a solution to your question after the update.
The idea is to store the text in an internal macro for each combination of term and dictionary and later call this macro to get the text, but of course, without having to use the internal macro itself. For this, two macros are needed, \dictionary{<dictionary>}{<term>}
to get the text and \DefineDictionaryEntry{<dictionary>}{<trem>}{<text>}
to define the text. For example, after
\DefineDictionaryEntry{matlab}{power}{The function power ...}
the line
\dictionary{matlab}{power}
will give out
The function power ...
The core for these macros looks like this:
\newcommand*{\DefineDictionaryEntry}[3]{%
\expandafter\def\csname dict@#1@#2\endcsname{#3}%
}
\newcommand*{\dictionary}[2]{
\csname dict@#1@#2\endcsname
}
In the example above the first line will define a macro \dict@matlab@power
, which is then called with \dictionary
. Now, this is barely usable, because in case of typos it will lead to odd error messages and/or results. It would be nice to check, if the dictionary and the term exists and
give out an understanable error message if necessary.
In order to check, if a dictionary exists, the macro \NewDictionary{<dictionary>}
defines an internal macro, which is later used for checking. The core for this looks like this:
\newcommand*{\NewDictionary}[1]{%
\expandafter\def\csname dict@#1\endcsname{y}%
}
Here too, some checking should be done.
From the LaTeX core the command \@ifundefined{<macro name>}{<code for macro undefined>}{<code for macro defined>}
can be used to check, if a macro does exist. And \PackageError{<package name>}{<error message>}{<help text>}
is used for error messages.
Additionally, packages normaly start with \ProvidesPackage{<package name>}[<date> <version> <short description>]
and in packages other packages are loaded with \RequirePackage{<package name>}
.
All this can be put in a package dictionary
, which is then used by the other packages (matlab
, maths
, etc.) to define the terms.
% dictionary.sty
\ProvidesPackage{dictionary}[2017/10/07 v1.00 Simple dictionary package.]
\newcommand*{\dictionary}[2]{
\@ifundefined{dict@#1}{%
% error message, dictionary does not exist
\PackageError{dictionary}{%
The dictionary #1 does not exist or is not loaded.\MessageBreak
Nothing will be printed.%
}{%
You may have a spelling error in your call or you forgot\MessageBreak
to load the package. Please check and correct this.
}%
}{%
\@ifundefined{dict@#1@#2}{%
% error message, dictionary entry does not exist
\PackageError{dictionary}{%
The term #2 does not exist in dictionary #1.\MessageBreak
Nothing will be printed.%
}{%
You may have a spelling error in your call or the term\MessageBreak
is not defined yet. Please check and correct this.
}%
}{%
% the core, for e.g. \dictionary{math}{power} the internal
% command \dict@math@power is called
\csname dict@#1@#2\endcsname
}%
}%
}
\newcommand*{\DefineDictionaryEntry}[3]{%
\@ifundefined{dict@#1}{%
% error message, dictionary does not exist
\PackageError{dictionary}{%
The dictionary #1 does not exist or is not loaded.\MessageBreak
The new term #2 will not be defined.
}{%
You may have a spelling error in your call or you forgot\MessageBreak
to load the package. Please check and correct this.
}%
}{%
\@ifundefined{dict@#1@#2}{%
% the core, for e.g. \DefineDictionaryEntry{math}{abs}{The abs ...} the internal
% command \dict@math@abs is defined with the meaning 'The abs ...'
\expandafter\def\csname dict@#1@#2\endcsname{#3}%
}{%
% error message, term already defined
\PackageError{dictionary}{%
The term #2 is already defined in dictionary #1.\MessageBreak
You can not redefine it.
}{%
You may have a spelling error or you just copied the line\MessageBreak
and forgot to change the term. Please check and correct this.
}%
}%
}%
}
\newcommand*{\NewDictionary}[1]{%
\@ifundefined{dict@#1}{%
% the core, for e.g. \NewDictionary{mathuser} the internal
% command \dict@mathuser is defined. With this, It's possible
% to check, if the dictionary exists
\expandafter\def\csname dict@#1\endcsname{y}%
}{%
% error message, dictionary already exists
\PackageError{dictionary}{%
The dictionary #1 already exist.\MessageBreak
You can not define it again.
}{%
You may have a spelling error or you just copied the line\MessageBreak
and forgot to change the dictionary name.\MessageBreak
Please check and correct this.
}%
}%
}
Now the other packages are simple:
matlab.sty
:
% matlab.sty
\ProvidesPackage{matlab}[2017/10/07 v1.00 Dictionary for matlab.]
\RequirePackage{dictionary}
\NewDictionary{matlab}
\DefineDictionaryEntry{matlab}{power}{The function power ...}
\DefineDictionaryEntry{matlab}{abs}{The function abs ...}
% more definitions here
maths.sty
% maths.sty
\ProvidesPackage{maths}[2017/10/07 v1.00 Dictionary for math.]
\RequirePackage{dictionary}
\NewDictionary{math}
\DefineDictionaryEntry{math}{power}{The power ...}
\DefineDictionaryEntry{math}{abs}{The absolute ...}
% more definitions here
Please note that for \ProvidesPackage
the <package name>
must be the file name without .sty
.
Other packages can be written the same way:
% mathuser.sty
\ProvidesPackage{mathuser}[2017/10/07 v1.00 Dictionary for math by User.]
\RequirePackage{dictionary}
\NewDictionary{mathuser}
\DefineDictionaryEntry{mathuser}{test}{This is a test entry, written by User.}
With all this, in the document you need to load all the dictionaries you want to use:
\documentclass[10pt,a4paper]{article}
\usepackage{matlab}
\usepackage{maths}
\usepackage{mathuser}
% dictionaries and their entries can also be defined in the preamble
\NewDictionary{mydict}
\DefineDictionaryEntry{mydict}{addition}{Additionally, we learned about addition}
\begin{document}
Test the terms:
\dictionary{matlab}{power}
\dictionary{math}{power}
\dictionary{matlab}{abs}
\dictionary{math}{abs}
\dictionary{mathuser}{test}
\dictionary{mydict}{addition}
\end{document}
Best Answer
Latexmk actually has a subroutine for adding items to search paths. You can write
This takes care of using the correct operating-system-dependent separator between items in the variable. It also gracefully handles the case where the search-path variable doesn't already exist.
This subroutine is not yet documented, but it will be in the next release.
Documentation of ensure_path
The first parameter is the name of one of the system's environment variables for search paths. The remaining parameters are values that should be in the variable. For each of the value parameters, if it isn't already in the variable, then it is prepended to the variable; in that case the environment variable is created if it doesn't already exist. For separating values, the character appropriate the the operating system is used -- see the configuration variable
$search_path_separator
.Example:
(In this example, the trailing
//
is documented by TeX systems to mean that latex, pdflatex, etc search for files in the specified directory and in all subdirectories.)Technically
ensure_path
works by setting Perl's variable$ENV{var}
, wherevar
is the name of the target variable. The changed value is then passed as an environment variable to any invoked programs.