1

I have a simple directory structure:

 foo/a.tex
 foo/b.tex

a.tex simply uses environment to get contents from b.tex:

\environment b
\starttext
A \tikz \draw (0,0) -- (1,1);
\stoptext

and b.tex has only tikz module invokation:

cat b.tex
\usemodule[tikz]

When I call context within directory foo all is OK (cd foo and context a.tex), but when I run in the parent directory (foo):

$ context foo/a.tex

then I get the error:

tex error       > tex error on line 3 in file foo/a.tex: Undefined control sequence

<line 3.3>
    A \tikz
     \draw (0,0) -- (1,1);

1     \environment b
2     \starttext
3 >>  A \tikz \draw (0,0) -- (1,1);
4     \stoptext
5
6

I suspect this is because \environment does not support relative paths from the ConTeXt file and it uses relative path from running command.

My ConTeXt version is:

context --version
mtx-context     | ConTeXt Process Management 1.06
mtx-context     |
mtx-context     | main context file: /home/xan/bin/context-current/tex/texmf-context/tex/context/base/mkiv/context.mkiv
mtx-context     | current version: 2025.02.28 18:16
mtx-context     | main context file: /home/xan/bin/context-current/tex/texmf-context/tex/context/base/mkxl/context.mkxl
mtx-context     | current version: 2025.02.28 18:16
6
  • 1
    As Brian M. Hunt says, I could use --path: context --path=a a/a.tex or put \usepath[a] in the file a.tex. So it seems the paths are relative to running command directory not the document itself. Is it any way to change it? Commented Mar 14 at 9:43
  • 3
    Do you miss /a and /b where you at the top show your structure, i.e., is it foo/a/a.tex and foo/b/b.tex you are using? Commented Mar 14 at 10:31
  • @mickep Corrected: I run context within foo directory. Commented Mar 15 at 15:05
  • yes, but you say you have foo/a.tex and foo/b.tex i.e. all files are in a single directory, where you run context. Commented May 1 at 5:44
  • 1
    do you have foo/a/a.tex and foo/a/b.tex? Commented May 1 at 5:45

1 Answer 1

2
+50

The best solution is to use the --path=<…> argument, but you don't seem to want to use that solution. An alternative solution is to add

\ctxlua{context.usepath{file.dirname(environment.inputfilename)}}

to the top of the input file, which will automatically add the file's parent directory to the list of files to search.

But if you don't want to add this to the top of all of your files, you can add something similar to the file cont-loc.mkxl, which is automatically input for each run. I wouldn't recommend this solution though, since it will make your documents non-portable.

$ tree -al foo/
foo/
├── a.tex
└── b.tex

1 directory, 2 files

$ cat foo/a.tex
\environment b
\starttext
A \tikz \draw (0,0) -- (1,1);
\stoptext

$ cat foo/b.tex
\usemodule[tikz]

$ cd foo/

$ context a.tex > /dev/null && echo Good || echo Bad
Good

$ cd ..

$ context foo/a.tex > /dev/null && echo Good || echo Bad
Bad

$ context --path=./foo foo/a.tex > /dev/null && echo Good || echo Bad
Good

$ TEXMFHOME=./foo context foo/a.tex > /dev/null && echo Good || echo Bad
Good

(Now modify `a.tex`)

$ cat foo/a.tex
\usepath[./foo]
\environment b
\starttext
A \tikz \draw (0,0) -- (1,1);
\stoptext

$ context foo/a.tex > /dev/null && echo Good || echo Bad
Good

$ mkdir bar && cd bar/

$ context ../foo/a.tex > /dev/null && echo Good || echo Bad
Bad

$ cd ..

(Now modify `a.tex`, again)

$ cat foo/a.tex
\ctxlua{context.usepath{file.dirname(environment.inputfilename)}}
\environment b
\starttext
A \tikz \draw (0,0) -- (1,1);
\stoptext

$ context foo/a.tex > /dev/null && echo Good || echo Bad
Good

$ cd bar/

$ context ../foo/a.tex > /dev/null && echo Good || echo Bad
Good

$ cd ..

(Now reset `a.tex` back to the original)

$ cat foo/a.tex
\environment b
\starttext
A \tikz \draw (0,0) -- (1,1);
\stoptext

$ mkdir -p $(mtxrun --resolve-path TEXMFCONFIG | head -1)/tex/context/

$ echo '\ctxlua{context.usepath{file.dirname(environment.arguments.input)}}' > $(mtxrun --resolve-path TEXMFCONFIG | head -1)/tex/context/cont-loc.mkxl

$ context foo/a.tex > /dev/null && echo Good || echo Bad
Good

$ cd bar/

$ context ../foo/a.tex > /dev/null && echo Good || echo Bad
Good

\ctxlua is the command that you use to run Lua code inline in ConTeXt (similar to \directlua). Any functions in the context table map to TeX macros; see the CLD Manual §2.2 for more details. So the following two lines are precisely equivalent:

\ctxlua{context.usepath { "/some/path/" }} % Option 1

\usepath[/some/path/] % Option 2

ConTeXt has a macro that gives us the name of the current file (\jobname), but it doesn't have any macros to extract the directory component of a path. However, there is a Lua function that does this (file.dirname), so we can use that instead. But cont-loc.mkxl is loaded early in the compile process, before \jobname is populated, so we instead need to use the alternative Lua variable environment.arguments.input.

Putting this all together gives us

\ctxlua{context.usepath{file.dirname(environment.arguments.input)}}
11
  • Can you give more information about \ctxlua{context.usepath...? Commented May 2 at 7:49
  • 1
    @somenxavier Sure, see the edit. Commented May 2 at 7:58
  • Do you know if there is something similar in LaTeX? Something which treats the original problem? Commented May 2 at 8:15
  • @somenxavier Similar to \usepath, or similar to context.macro_name { "arguments" }? Commented May 2 at 8:16
  • 1
    @MaxChernoff that shouldn't work by default, should it? (or not for arbitrary directories, anyway?) Commented May 2 at 11:11

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.