Is it possible to pass <$projectfile> as an argument to the Compile processing bash script?

Hello! and Happy New Year!

Hello. I am trying to pass the absolute path of the main Scrivener file to my post-compile processing script (bash). I know we can pass <$inputfile> and <$outputname> as arguments to the script. But is it possible to pass other metadata placeholders to the script? Is there something like <$projectfile> that could work?

Thanks for the help!

I’m sure I’m not the only one wondering: To what end?

A Scrivener Project is not a file, but a folder or Package containing possibly hundreds of files.

Yes, I know. LOL. But I am wondering if it is possible to pass the path to the .scriv project to a Compile script via a placeholder (like <$projectfile>) as an argument. I am hoping that Compile can trigger Squarto to do the post-processing, but it needs to know where the .scriv project is located. (Since Scrivener can export the compiled Markdown file anywhere on the system, I do not want to assume, or require, that it be in the same directory.)

I have made a program called Squarto that processes my .scriv project (which contains information about the structure of the Binder and many other things) + the compiled Markdown document to produce the hierarchical folder/file structure needed by Quarto. Quarto is a program that is used in academic/technical writing that includes equations, citations, tables, computer code that should be executed in preparation of a final product. It is built on top of Pandoc and can output web sites, PDF, Word .docx, and much more. Basically, the workflow is:

Write in Scrivener > Compile > process by Squarto > process by Quarto > product

If you’re interested, there are two threads where some bits are discussed:

I will update the main Squarto thread soon with a full description and screenshots. The program works well. Once I get it polished and easily installable on other systems, I hope to upload to GitHub.

2 Likes

@AmberV, @nontroppo, and @kewms,
Happy new year!
Do you happen to know whether it is possible to pass the .scriv project path to a Compile script using a placeholder?

No. A project doesn’t know – or need to know – its own location.

Why does your script need that information? Generally speaking, it is poor practice (and entirely unsupported) for a script to poke around in the project itself, rather than using the information passed to it by the Compile command.

My project (Squarto) analyzes the Binder structure and other details that are contained in the XML of the .scrivx file inside the .scriv project. Squarto is a post-compile processor that builds the folder/file hierarchy of a Quarto book. It does a lot of other powerful things, such as allow storage of arbitrary files in the Binder (like LaTeX templates and Quarto extensions) and knows how to copy them into the right place; it moves images into a figures directory; it creates a references.bib alias to a Zotero library; it auto-populates the _quarto.yml configuration file; and it tweaks Markdown to the flavor expected by Quarto; and more. To do all this, it uses the Markdown document compiled by Scrivener, and it needs to read the .scrivx file.

Squarto works amazingly well as a command-line tool when I manually provide the paths to the bits that it needs. But I’m trying to set it up in my Scrivener project so that it will run automatically after compilation.

1 Like

Right, I don’t know a way from post-processing; we only have access to the compile folder. Perhaps there is some shell trick to find the calling process and its open files to reverse engineer it, but at least looking at the ENV variables available I don’t remember seeing anything that would help. Using Activity monitor the open files do not seem to include the projects:

There is possibly an Applescript API that gives you the documents opened for a particular app?

set appName to "Scrivener"
tell application appName
	try
		return path of front document
	on error
		try
			return POSIX path of (get file of front document)
		on error errorMessage
			return errorMessage
		end try
	end try
end tell

Doesn’t work for Scrivener as it doesn’t support even this minimal Applescript :disappointed_relieved:

I managed to find a workaround using Keyboard Maestro. The Compile process starts with the KM macro, which is pretty simple:

  • Activate Scrivener
  • Select “Show Project in Finder” in the Menu “File” – At this point, Scrivener opens a Finder window with the .scriv project file already selected.
  • Set variable “scrivener_project_path” to text %FinderSelection% – grabs the path from the selected file
  • Set system clipboard to scrivener_project_path
  • Activate Scrivener again
  • Select “Compile…” in the menu “File”
  • Press button “Title:Compile” when enabled

At this point, the KM macro is finished, and the rest is handled by Scrivener. I type the desired name of the compiled .md file and click Export. Scrivener then processes and saves the compiled .md file, and then it runs the post-processing bash script using three arguments that stand for the (1) compiled_md_file as provided by the Scrivener placeholder, (2) output_dir, and (3) bib_file:

<$inputfile> "squarto_output" "path/to/Zotero/MY_LIBRARY.bib"

So where is the specification of the path to the Scrivener project, aka scriv_file? (That was my whole dilemma, after all…) Well, that happens within the bash script itself, using the pbpaste command to insert the contents of the system clipboard that was just grabbed via the KM macro:

# Get path to .scriv project file (via system clipboard, using KM macro)
path_to_scriv_file=$(pbpaste)

# Get path to Scrivener-compiled .md file (via the first Scrivener argument)
compiled_md_file="$1"
dir=$(pwd)
path_to_compiled_md_file="$dir/$compiled_md_file"

# Get path to output_dir (via the second Scrivener argument)
# This may be a relative path, so it will be expanded
path_to_output_dir="$2"
path_to_output_dir=$(eval echo "$path_to_output_dir")

# Get path to .bib file (via the third Scrivener argument)
# This may be a relative path, so it will be expanded
path_to_bib_file="$3"
path_to_bib_file=$(eval echo "$path_to_output_dir")

The parameters are printed to a log file to help with debugging.

Finally, Squarto is run by the bash script using all of these parameters…

# Run Squarto
echo "Running Squarto..."
squarto build --scriv_file=$path_to_scriv_file --compiled_md_file=$path_to_compiled_md_file --output_dir=$path_to_output_dir --bib_file=$path_to_bib_file --bib_file_as_alias

and I open a Finder window at the location of the output (which is a Quarto book).

I did not include the command for quarto render in the bash script. I usually run quarto preview once at the beginning, and I mainly wanted this workflow to rebuild the folders/files so that any active Quarto preview (in a browser window) can refresh the contents while I’m working. It’s reasonably close to a live preview (but may still take some time if Quarto needs to execute code).

Last, I assigned a hotkey so that when I’m working in Scrivener, I can deploy my workflow in seconds.

It works very well… but the perfectionist in me is still pained by the fact that I have to rely on a hack via KM to get this done, and I couldn’t do it simply by using a <$projectfile> placeholder as an argument (best choice) or via an AppleScript command to Scrivener (which doesn’t seem to have much in terms of AppleScript support, let alone Shortcuts). Oh well… I’m thankful that tools like KM exist! And thanks, @nontroppo, for mentioning your AppleScript attempt, which got me thinking about ways to grab the scriv_file path somehow from the Scrivener window itself, before entering into the Compile modal window. I appreciate the help.

2 Likes