diff --git a/CHANGELOG.md b/CHANGELOG.md index 0adccf6..0ee578a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # NEXT +- add `(lookup-file)` message to notify editor of file lookups - fix TeX build date to use SOURCE_DATE_EPOCH if set, otherwise falling back to the current date (previously hardcoded to Feb 8, 2025). - fix zealous JSON escaping diff --git a/EDITOR-PROTOCOL.md b/EDITOR-PROTOCOL.md index 2eb25f7..4b5180f 100644 --- a/EDITOR-PROTOCOL.md +++ b/EDITOR-PROTOCOL.md @@ -209,3 +209,14 @@ The paths are printed relative to the root file. They might be non-existent on t Right now, this is implemented by hooking into SyncTeX: - only text files are tracked (not graphics) - the indices printed are the SyncTex input indices; they should be attributed no other meaning than being monotonic and useful to detect backtracking occurrences + +### File lookups + +``` +(lookup-file kind status "path") +``` + +Output by TeXpresso when it tries to look up a file. +- `kind`: either `read` or `write`. +- `status`: either `successful` or `failed`. +- `path`: the path to the file. diff --git a/Makefile b/Makefile index c435c28..9be3c6c 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,6 @@ all: @echo "# Or:" @echo "# build/texpresso -texlive test/simple.tex" @echo "# build/texpresso -tectonic test/simple.tex" - @echo "#" common: $(MAKE) -C src/common @@ -110,4 +109,7 @@ test-stream: test-stream-pipe: test/test_stream.sh -.PHONY: all dev clean config texpresso common texpresso-xetex re2c compile_commands.json fill-tectonic-cache test-texlive test-tectonic test-texpresso test-stream test-stream-pipe test-open-base64 +test-request-file: + bash test/test-request-file.sh + +.PHONY: all dev clean config texpresso common texpresso-xetex re2c compile_commands.json fill-tectonic-cache test-texlive test-tectonic test-texpresso test-stream test-stream-pipe test-open-base64 test-request-file diff --git a/emacs/texpresso.el b/emacs/texpresso.el index 979c7ad..af91d03 100644 --- a/emacs/texpresso.el +++ b/emacs/texpresso.el @@ -319,6 +319,8 @@ standard output. This function interprets one of these." ((eq tag 'input-file)) + ((eq tag 'lookup-file)) + (t (message "Unknown message in texpresso output: %S" expr))))) (defun texpresso--stdout-filter (process text) diff --git a/src/frontend/editor.c b/src/frontend/editor.c index dac5b1d..184bc42 100644 --- a/src/frontend/editor.c +++ b/src/frontend/editor.c @@ -586,3 +586,24 @@ void editor_notify_file_opened(int index, const char *path, int len) case EDITOR_JSON: fprintf(stdout, "\"]\n"); break; } } + +void editor_notify_lookup(const char *path, int len, bool read, bool success) +{ + const char *kind = read ? "read" : "write"; + const char *status = success ? "successful" : "failed"; + switch (protocol) + { + case EDITOR_SEXP: + fprintf(stdout, "(lookup-file %s %s \"", kind, status); + break; + case EDITOR_JSON: + fprintf(stdout, "[\"lookup-file\", \"%s\", \"%s\", \"", kind, status); + break; + } + output_data_string(stdout, path, len); + switch (protocol) + { + case EDITOR_SEXP: fprintf(stdout, "\")\n"); break; + case EDITOR_JSON: fprintf(stdout, "\"]\n"); break; + } +} diff --git a/src/frontend/editor.h b/src/frontend/editor.h index 6aef93f..025faed 100644 --- a/src/frontend/editor.h +++ b/src/frontend/editor.h @@ -136,5 +136,6 @@ void editor_flush(void); void editor_synctex(const char *dirname, const char *basename, int basename_len, int line, int column); void editor_reset_sync(void); void editor_notify_file_opened(int index, const char *path, int len); +void editor_notify_lookup(const char *path, int len, bool read, bool success); #endif // EDITOR_H_ diff --git a/src/frontend/engine_tex.c b/src/frontend/engine_tex.c index 7651017..0850c84 100644 --- a/src/frontend/engine_tex.c +++ b/src/frontend/engine_tex.c @@ -496,6 +496,7 @@ static void answer_query(fz_context *ctx, struct tex_engine *self, query_t *q) log_fileentry(ctx, self->log, e); record_seen(self, e, INT_MAX, q->time); a.tag = A_PASS; + editor_notify_lookup(q->open.path, strlen(q->open.path), q->tag == Q_OPRD, false); channel_write_answer(self->c, p->fd, &a); break; } @@ -529,6 +530,7 @@ static void answer_query(fz_context *ctx, struct tex_engine *self, query_t *q) log_fileentry(ctx, self->log, e); record_seen(self, e, INT_MAX, q->time); a.tag = A_PASS; + editor_notify_lookup(q->open.path, strlen(q->open.path), q->tag == Q_OPRD, false); channel_write_answer(self->c, p->fd, &a); break; } @@ -620,6 +622,7 @@ static void answer_query(fz_context *ctx, struct tex_engine *self, query_t *q) int n = strlen(q->open.path); a.open.path_len = n; a.tag = A_OPEN; + editor_notify_lookup(q->open.path, n, q->tag == Q_OPRD, true); memmove(channel_get_buffer(self->c, n), q->open.path, n); channel_write_answer(self->c, p->fd, &a); break; diff --git a/src/frontend/main.c b/src/frontend/main.c index cbe436a..658ec0c 100644 --- a/src/frontend/main.c +++ b/src/frontend/main.c @@ -1461,7 +1461,9 @@ bool texpresso_main(struct persistent_state *ps) break; } } - if (ps->initialize_only) + if (ps->initialize_only && + (send(page_count, ui->eng) > 0 || + (send(get_status, ui->eng) == DOC_TERMINATED && stdin_eof))) { fprintf(stderr, "[info] Initialize mode: terminating engine process\n"); quit = 1; diff --git a/test/request-file.tex b/test/request-file.tex new file mode 100644 index 0000000..4219056 --- /dev/null +++ b/test/request-file.tex @@ -0,0 +1,5 @@ +\documentclass[12pt]{article} +\begin{document} +Hello. +\input{texpresso_ci_missing_file.tex} +\end{document} diff --git a/test/test-request-file.sh b/test/test-request-file.sh new file mode 100755 index 0000000..73460b3 --- /dev/null +++ b/test/test-request-file.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Test request-file: engine requests a missing file via Q_OPRL (non-blocking), +# test provides the file, engine restarts and processes it successfully. +set -e + +FIFO=$(mktemp -u /tmp/texpresso-fifo-XXXXXX) +OUTFILE=$(mktemp /tmp/texpresso-out-XXXXXX) +mkfifo "$FIFO" +trap 'rm -f "$FIFO" "$OUTFILE"; kill "$PID" 2>/dev/null || true' EXIT + +TARGET="texpresso_ci_missing_file.tex" + +# Start texpresso in background, reading stdin from FIFO, stdout to file +SDL_VIDEODRIVER=dummy build/texpresso -test-initialize test/request-file.tex \ + < "$FIFO" > "$OUTFILE" 2>/dev/null & +PID=$! + +# Open FIFO for writing (unblocks texpresso's stdin) +exec 3>"$FIFO" + +# Wait for request-file for the target file (ignore .aux etc.) +TIMEOUT=120 +while ! grep -q "request-file \"$TARGET\"" "$OUTFILE" 2>/dev/null; do + sleep 0.5 + TIMEOUT=$((TIMEOUT - 1)) + if [ $TIMEOUT -le 0 ]; then + echo "FAIL: timeout waiting for request-file" + echo "stdout contents:" + cat "$OUTFILE" + exit 1 + fi + if ! kill -0 "$PID" 2>/dev/null; then + echo "FAIL: texpresso exited before emitting request-file for $TARGET" + echo "stdout contents:" + cat "$OUTFILE" + exit 1 + fi +done + +echo "Got request-file for: $TARGET" + +# Provide the missing file content +printf '(open "%s" "Included content.\\n")\n' "$TARGET" >&3 +exec 3>&- + +# Wait for texpresso to finish (it exits after page_count > 0 in -test-initialize mode) +if wait "$PID"; then + echo "PASS: request-file test" +else + echo "FAIL: texpresso exited with error" + exit 1 +fi