Tikz externalize issue when using pdflatex with -output-directory - latex

When using pdflatex with -output-directory I run into issues when externalizing tikz figures. While the .md5 files are created where I expect them the command creating the externalized picture files (.pdf, .log, .dpth) fails. My assumption is that this happens because the pdflatex to create these files does not inherit the -output-directory option and thus fails to create the files in the right spot.
This is a minimal example showing the behavior.
main.tex:
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize[prefix=tikz/]
\begin{document}
Test externalize in combination with -output-directory
\tikzsetnextfilename{testpicture}
\begin{tikzpicture}
\node {Node};
\end{tikzpicture}
\end{document}
bash:
mkdir -p build/tikz
pdflatex -output-directory build -shell-escape main.tex
error:
===== 'mode=convert with system call': Invoking 'pdflatex
-shell-escape -halt-on-error -interaction=batchmode -jobname
"tikz/testpicture" "\def\tikzexternalrealjob{main}\input{main}"'
======== This is pdfTeX, Version 3.14159265-2.6-1.40.16
(TeX Live 2015/Debian) (preloaded format=pdflatex)
\write18 enabled.
entering extended mode
! I can't write on file `tikz/testpicture.log'.
resulting directory structure (output of tree):
.
├── build
│   ├── main.aux
│   ├── main.auxlock
│   ├── main.log
│   ├── main.pdf
│   └── tikz
│   └── testpicture.md5
└── main.tex
So again, as far as I understand the log file creation fails due to the lack of a tikz directory in the working directory of the pdflatex command executed by the externalization.
Are my assumptions correct? If they are, how should how I should proceed with this?

As far as I have found out the easiest solution is to create a symlink in your main folder to the tikz folder inside build. Like so: ln -s build/tikz .
This was the solution I found in the documentation of another tikz externalizing library.

tikzexternal does not detect the -output-directory argument. Hence you have to modify the call to the compiler of the externalized images and add this argument by your own.
This also holds true for the inclusion of the image. You have to prefix the image here with the path of the output directory.
Those two points can be seen in the following MWE:
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize[prefix=tikz/]
\makeatletter
\tikzset{%
external/system call={%
pdflatex %
\tikzexternalcheckshellescape %
-halt-on-error %
-interaction=batchmode %
-output-directory="build" %
-jobname "\image" %
"\texsource"%
},
/pgf/images/include external/.code={%
\includegraphics{build/#1}%
},%
}
\makeatother
\begin{document}
Test externalize in combination with -output-directory
\tikzsetnextfilename{testpicture}
\begin{tikzpicture}
\node {Node};
\end{tikzpicture}
\end{document}
Some additional notes:
You can find the relevant code in pgf/frontendlayer/tikz/libraries/tikzexternalshared.code.tex
If your tex file is in a sub directory or you use -jobname you have to replace "\texsource" with something like "\string\def\string\tikzexternalrealjob{\tikzexternal#realjob}\string\input{path/to/tex/file/\tikzexternal#realjob}"
Edit
There is a shorter way to do this: Instead of setting external/system call, you can also set external/shell escape={-shell-escape\space-output-directory=build}. This will end up in \tikzexternalcheckshellescape.
For both methods (the original and the shorter one) to work with LuaLaTeX, you need \usepackage{shellesc}.

It could be a question with regards to the permissions as well.
Try with
chmod 777 tikz
right after you create the folder.
You could also try to move your main.tex file into the build folder to see if that changes things.

I found that symlinking as suggested by Artemis is indeed the easiest option, i.e.:
mkdir -p build/fig
ln -sf build/fig .
pdflatex -shell-escape -output-directory=build main.tex
Additionally, if you use \tikzexternalize[mode=list and make], you will also notice that the generated build/main.makefile can't be used as is either, because it uses files both in the base folder and in the build folder. To make it work, again, symlinking seems to be the easiest option, this time the file main.figlist (alternative would be copying files or modifying the makefile). The full process now looks as follows:
# Run once to create list of externalize figures:
mkdir -p build/tikz
ln -sf build/tikz .
pdflatex -output-directory=build main.tex
# Build externalized figures:
ln -sf build/main.figlist .
make -f build/main.makefile
# Run again to include externalized figures into document:
pdflatex -output-directory=build main.tex
# Cleanup:
rm tikz main.figlist
Furthermore, if you encounter problems with other packages you may need to also take into account Phobos' answer to ensure that the build directory is also known while building the individual figures, i.e.:
\tikzexternalize[
prefix=tikz/,
mode=list and make,
shell escape={-shell-escape\space-output-directory=build},
]

Related

Clarify file/dir list to include in duply profile

I have defined /tmp/ as my source directory. I want to backup only in1/ and in2/ subfolders from it. What lines do I need in profile's exclude file?
/tmp/a
├── in1
│   └── in.txt
├── in2
│   └── in.txt
└── out.txt
According to duplicity man page's dir/foo example, I tried:
+ in1/
+ in2/
- **
But that did not work and I got error as:
Reading globbing filelist /path/to/duply_profile/exclude
Fatal Error: The file specification
in1/
cannot match any files in the base directory
/tmp
Useful file specifications begin with the base directory or some
pattern (such as '**') which matches the base directory.
better use up-to-date man page from duplicity's website https://duplicity.us/stable/duplicity.1.html#file-selection
not sure why the example relative paths is in there, but as the error states you will need something along the lines
+ /tmp/in1/
+ /tmp/in2/
- **
feel free to post a bug ticket on https://gitlab.com/duplicity/duplicity/-/issues so maybe someday some kind soul would make it work with relative paths.
I figured that the following specification work:
+ **in1/
+ **in2/
- **

I don't want to ignore a file with no extension

I have a credentials file with no extension.
I would like to add this file to the docker to be available in the app directory.
Right now I have a file added in the root of the application but after building the image the file is missing
My dockerignore
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
Try +([^.])
https://unix.stackexchange.com/a/87649
The bash extended glob +([^.]) will match files without any . in their name. It requires that you have not unset shopt extglob (on modern bash installations, it should be set by default). The pattern means:
any number (but at least one) of characters other than .

Compile two versions of a document from the same latex source

How to automatically compile two versions of the same document, for example version without answers for the students and another version with answers for myself?
I have a small bash script to do a dual format.
function latex-ans () {
n=$(basename $1 .tex) # strip .tex in filename foo.tex -> foo
ln -s $n.tex $n-ans.tex # create a soft link (for instance foo-ans.tex -> foo.tex)
pdflatex '\def\withanswer{1} \input{'$n-ans'}' && pdflatex $n
% first format the version with answers and then the normal version
rm $n-ans.tex $n-ans.log
% remove useless files
}
If I have a file foo.tex, this commands formats both versions of the file and generates two pdf: foo.pdf and foo-ans.pdf. Thanks to the renaming of foo.tex through the ln -s, it also keeps separate foo.aux and foo-ans.aux to preserve useful information on both versions.
At the latex level, I basically do the same and use the macro \withanswers to configure my packages.
There are several packages that allow to conditionally exclude certain parts of the document, for example the exercise package.
With TeXstudio, the following magic comment can be used to automatically compile both versions at once (including repeated compilation for cross-references, bibliographies, indices etc.):
% !TeX program = latexmk -pdf -pdflatex="pdflatex -synctex=1 -interaction=nonstopmode -shell-escape" -jobname=% -pretex="\newcommand{\version}{noanswer}" -usepretex % | latexmk -pdf -pdflatex="pdflatex -synctex=1 -interaction=nonstopmode -shell-escape" -jobname=%_solution -pretex="\newcommand{\version}{}" -usepretex % | txs:///view-pdf "?am)_solution.pdf"
\documentclass{article}
% setting a default value in case it is compiled without the magic comment
\ifdefined\version
\else
\def\version{noanswer}
\fi
\usepackage[\version]{exercise}
\begin{document}
\begin{Exercise}[title={Title},label=ex1]
question text
\end{Exercise}
\begin{Answer}[ref={ex1}]
solution
\end{Answer}
\end{document}

massaging packages that install files outside of nix-store

I'm using nix package-manager on macOS (Sierra).
My intention is to write a nix expression that will install the existing fish nix package along with the Bass fish plugin.
There are no existing expressions in nixpkgs for Bass, but the git repo contains a Makefile. This Makefile attempts to copy files to the $HOME dir. This is a problem as installing files outside of the nix-store is clearly not desirable and $HOME is not set when I build my package.
I can recognise why it's not desirable for nix packages to install files outside of the nix-store - in functional programming terms it's akin to a side-effect. But I'm also not clear on how to solve my problem:
By default Fish requires plugins such as Bass to be installed under $HOME/.config/fish/. Fish does provide a means to customise the config path by specifying the environment variable XDG_CONFIG_HOME. So I was thinking of doing something like this:
Create an expression for Bass patching the Makefile to install the files under $out.
Create an expression that installs fish and uses Bass as a build input. Use wrapProgram to set XDG_CONFIG_HOME pointing to the Bass install path in the nix-store.
Does this sound like the right approach? Are there alternative/better ways of solving this?
Thanks
This is the solution that I have gone with:
Expression for bass:
nix_local/pkgs/fish_plugins/bass/default.nix
{stdenv, fetchFromGitHub}:
let
version = "0.0.1";
in
stdenv.mkDerivation rec {
name = "bass-${version}";
src = fetchFromGitHub {
owner = "edc";
repo = "bass";
rev = "1fbf1b66f52026644818016015b8fa9e0f639364";
sha256 = "12bp8zipjbikasx20yz29ci3hikw0ksqlbxbvi2xgi4g6rmj7pxp";
};
patchPhase = ''
substituteInPlace Makefile --replace \
"~/.config/fish" \
$out/.config/fish
'';
}
Expression for fish_with_config:
nix_local/pkgs/fish_with_config/default.nix
{stdenv, fish, bass, makeWrapper}:
let
version = "0.0.1";
in
stdenv.mkDerivation rec {
name = "fish-with-config-${version}";
src = ./.;
buildInputs = [fish bass makeWrapper];
installPhase = ''
mkdir -p $out/.config/fish/functions
cp -r $src/.config/* $out/.config
cp -r ${bass}/.config/fish/functions/* \
$out/.config/fish/functions/
mkdir -p $out/bin
ln -s ${fish}/bin/fish $out/bin/fish
wrapProgram $out/bin/fish --set XDG_CONFIG_HOME "$out/.config"
'';
}
The Fish program is wrapped in order for it's config to be stored in the nix-store. This enables us to symlink the functions from Bass and also copy any additional config files from the local $src dir. Additional plugins could be symlinked in the same way.
The local src dir for the derivation contains the following files:
pkgs/fish_with_config
├── .config
│   └── fish
│   ├── fishd.8c8590486f8c
│   └── functions
└── default.nix
The .config/fish/fishd.8c8590486f8c file is a "universal variable file" which Fish requires in order to operate. In a standard Fish installation this file is stored under ~/config/fish/ and is created the first time you enter interactive mode. The contents of this file would typically change over time as users interact with Fish settings.
The fish_with_config derivation stores the Fish config in the nix-store, which means it can't be modified at a latter date (not writable). This means all the config settings need to be done upfront as any attempts by the user to modify the settings will result in permission errors - this is obviously a little inconvenient, but not a show stopper for me.
It's probably worth noting that the universal variable file may change with different releases of Fish and as such if I was to build fish_with_config with a newer version of Fish I would first determine it's default content by running fish in a nix-shell and inspecting the auto generated file under ~/config/fish/.
In summary the above works nicely, I have access to bass and any additional user defined functions I choose to "bake in" (pkgs/fish_with_config/.config/fish/functions).
If you see anything that could be improved or handled more idiomatically let me know.

Synchronise pdf to Rnw in Knitr with texshop

Would anyone know how to get synctex to work from the pdf to the Rnw in knitr with texshop? It does work from Rnw to pdf. Many thanks.
This is how I worked this out. Not tried on multiple .Rnw files.
In TeXShop Preferences, make sure your "Sync Method" is set as "SyncTeX (TeX ≥ 2010)".
On your Mac, make the directory "~/Library/TeXShop/Rscripts" and put the R file "patchKnitrSynctex.R" downloaded from https://github.com/jan-glx/patchKnitrSynctex in this directory.
Create an executable file "Knitr.engine" including the following shell scripts and put it in "~/Library/TeXShop/Engines/":
#!/bin/bash
# export PATH=$PATH:/usr/texbin:/usr/local/bin # already on my path!
Rscript -e "library(knitr); knit('$1')"
latexmk -pdf -pdflatex='pdflatex -shell-escape -synctex=1 -file-line-error' "${1%.*}"
Rscript -e "source('~/Library/TeXShop/Rscripts/patchKnitrSynctex.R', echo=FALSE, encoding='UTF-8'); patchKnitrSynctex('${1%.*}')"
In R, install the package "patchDVI".
In your .Rnw file, add "% !TEX TS-program = Knitr" on the top line of the document. Also inside the .Rnw document somewhere around the top of the document add an R code chunk
<<setup, include=FALSE>>=
patchDVI::useknitr()
… #any other knitr global setups
#
Happy knitting!

Resources