CTANIFY(1)

🌸 CTANIFY β€” the manual page, bestie edition 🌸

okay so this is the manual for ctanify, a lil Perl script that gets your LaTeX package all dressed up and ready for the CTAN runway. she's from section 1 of the manual (that's what the (1) means, iykyk). let's get into it πŸ’…


✨ NAME ✨

ctanify β€” prep a package for upload to CTAN. that's it, that's the whole job πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

ctanify [--pkgname=string] [--[no]auto] [--tdsonly=filespec ...]
[--[no]unixify] [--[no]skip] [--tdsdir=dirname ...]  [--tex=macro_pkg]
[--[no]miscify] [--[no]tds] filespec[=dirname] ...

ctanify [--help]

ctanify [--version]

πŸ’– DESCRIPTION πŸ’–

so ctanify is for the devs out there who have a LaTeX package and wanna distribute it via the Comprehensive TeX Archive Network (aka CTAN, the main character of TeX package hosting ✨).

you hand her a list of filenames, and she builds you a tarball (a .tar.gz file, bestie) with all those files laid out in CTAN's preferred structure. and get this β€” the tarball also contains a ZIP (.zip) file with copies of every file laid out in the standard TeX Directory Structure (TDS), which makes it super easy to get your package into the TeX Live distribution. two-for-one, we love to see it 🫢


πŸ’… OPTIONS πŸ’…

ctanify accepts the following command-line options:

  • -h, --help β€” spit out basic usage info and dip. that's it 😌
  • -V, --version β€” print ctanify's version number and dip.
  • -p string, --pkgname=string β€” say your package name out loud instead of letting her figure it out. normally ctanify uses the base name of the first .ins or .sty file you list as the package name. this name becomes the base name of the tarball she produces. πŸ‘‘
  • --noauto β€” do NOT auto-add files to the tarball. normally ctanify automatically includes every file mentioned in a .ins file. this turns that off.
  • -t filespec, --tdsonly=filespec β€” name a subset of the files on the command line that should go only into the TDS ZIP file, not into the CTAN package directory. wildcards are allowed (quote them if you need to!), and you can use --tdsonly multiple times on the same command line. 🌈

at least one filename must be specified on the command line, fr fr. ctanify automatically places files in the TDS tree based on their extension, but you can override that by explicitly giving a target TDS directory using the form filespec=dirname. wildcards are allowed for the filespec (quoted if necessary) πŸŽ€


🌟 ADDITIONAL OPTIONS 🌟

these ones are unlikely to be necessary in ordinary usage β€” they exist for special circumstances that may arise. iykyk energy.

  • -d dirname, --tdsdir=dirname β€” instead of making a tarball for CTAN, just create the package TDS tree rooted in directory dirname. lowkey a different mode entirely.
  • -T macro_pkg, --tex=macro_pkg β€” assert that the files you're packaging for CTAN target a TeX macro package that isn't LaTeX. some common examples of macro_pkg are "generic", "plain", and "context". 🧚
  • -nou, --no-unixify β€” store text files unmodified instead of converting their end-of-line character to Unix format (a single linefeed character with no carriage-return character). yes even though CTAN prefers receiving all files with Unix-format end-of-line characters. she's telling you, you're just choosing chaos πŸ™ˆ
  • -nok, --no-skip β€” force ctanify to include files like Unix hidden files, Emacs backup files, and version-control metadata files. all of which CTAN dislikes receiving. πŸ’€
  • -m, --miscify β€” rename directories containing a single file to "misc". (for example, rename "tex/latex/mypackage/mypackage.sty" to "tex/latex/misc/mypackage.sty".) this was common practice in the past but is now strongly discouraged β€” consider this your warning bestie.
  • -nos, --no-tds β€” do not embed a .tds.zip file in the generated tarball.

😭 DIAGNOSTICS 😭

here's what she yells at you and what it actually means:

  • "Failed to copy filename (No such file or directory)" this is typically caused by a .ins file that generates filename but that hasn't already been run through tex or latex to actually produce filename. ctanify does not automatically run tex or latex β€” you gotta do that manually yourself. see "CAVEATS" for more info. 🫠
  • "Modified filename to use Unix line endings (use --no-unixify to prevent this)" for consistency, CTAN stores all text files with Unix-style line endings (a single linefeed character with no carriage-return character). to help with that, ctanify automatically replaces non-Unix-style line endings. this message is just letting you know not to be alarmed when filename in the tarball has a different size than the original filename on disk (which ctanify never modifies). if there's a good reason to preserve the original line endings (and there rarely is), use the --no-unixify option to stop ctanify from altering any files when storing them in the tarball.
  • "Excluding filename (use --no-skip to force inclusion)" ctanify normally ignores files β€” even when specified explicitly on the command line β€” that CTAN prefers not receiving. these include files whose names start with "." (Unix hidden files), end in "~" (Emacs automatic backups), or that come from a CVS or .svn directory (version-control metadata files). if there's a good reason to submit such files to CTAN (and there rarely is), the --no-skip option stops ctanify from ignoring them.
  • "CTAN prefers having only PDF documentation (re: filename)" because PDF is so popular, CTAN wants as much documentation as possible distributed in PDF. this message is asking you to replace any PostScript or DVI documentation with PDF if you can. (and no, ctanify will still include PostScript and DVI documentation in the tarball β€” this is just a polite request, bestie, not a blocker πŸŽ€)
  • "Not including filename in the TDS tree (unknown extension)" ctanify places files in the TDS tree based on a table of file extensions. for example, all .sty files go in tex/latex/package-name. if ctanify doesn't know where to put a file, she doesn't put it anywhere. see the last paragraph of "OPTIONS" for how to explicitly specify a file's target location in the TDS tree. for common file extensions that happen to be missing from ctanify's table, consider also notifying ctanify's author at the address shown below under "AUTHOR". πŸ’Œ

🌈 EXAMPLES 🌈

πŸŽ€ The Common Case πŸŽ€

normally all you gotta do is tell ctanify the name of the .ins file (or .sty if the package doesn't use DocStrip) plus the prebuilt documentation, if any:

$ ctanify mypackage.ins mypackage.pdf README

  490347  mypackage.tar.gz

              1771  mypackage/README
             15453  mypackage/mypackage.dtx
              1957  mypackage/mypackage.ins
            277683  mypackage/mypackage.pdf
            246935  mypackage.tds.zip

                        1771  doc/latex/mypackage/README
                      277683  doc/latex/mypackage/mypackage.pdf
                       15453  source/latex/mypackage/mypackage.dtx
                        1957  source/latex/mypackage/mypackage.ins
                        1725  tex/latex/mypackage/mypackage.sty

ctanify outputs the size in bytes of the resulting tarball, each file within it, and each file within the contained ZIP file. and in that example above, notice how ctanify automatically did all of this for you πŸ‘‘

  • including mypackage.dtx (found by parsing mypackage.ins) in both the mypackage directory and the ZIP file,
  • including mypackage.sty (found by parsing mypackage.ins) in the ZIP file but β€” because it's a generated file β€” not in the mypackage directory, and
  • placing all files into appropriate TDS directories (documentation, source, main package) within the ZIP file.

now imagine what it'd take to manually produce an equivalent mypackage.tar.gz file. yeah. ctanify is definitely the simpler, quicker alternative, no cap. πŸ’…

🌸 Advanced Usage 🌸

ctanify assumes PostScript files are documentation, so she stores them under doc/latex/package-name/ in the TDS tree inside the ZIP file. but suppose a LaTeX package uses a set of PostScript files to control dvips's output. in that case, ctanify must be told to include those PostScript files in the package directory, not the documentation directory:

$ ctanify mypackage.ins "mypackage*.ps=tex/latex/mypackage"

🧚 FILES 🧚

  • perl β€” ctanify is written in Perl and needs a Perl installation to run.
  • tar, gzip β€” ctanify requires the GNU tar and gzip programs to create a compressed tarball (.tar.gz).
  • zip β€” ctanify uses a zip program to archive the TDS tree within the main tarball.

πŸ’œ CAVEATS πŸ’œ

listen up bestie, this part matters πŸ’–

ctanify does not invoke tex or latex on its own, e.g., to process a .ins file. the reason is that ctanify doesn't know in the general case how to produce all of a package's generated files. it was deemed better to do nothing than to risk overwriting existing .sty (or other) files, or to include outdated generated files in the tarball. in short: before running ctanify you should manually process any .ins files and otherwise generate any files that should be sent to CTAN. periodt. πŸ”₯

ctanify has been tested only on Linux. it may work on OS X. and apparently it works on Windows when run using Cygwin. volunteers willing to help port ctanify to other platforms are extremely welcome β€” main character energy, honestly 🫢


⭐ SEE ALSO ⭐

tar(1), zip(1), latex(1), Guidelines for uploading TDS-Packaged materials to CTAN (<http://www.ctan.org/TDS-guidelines>), A Directory Structure for TeX Files (<http://tug.org/tds/>),


πŸ‘‘ AUTHOR πŸ‘‘

Scott Pakin, scott+ctify@pakin.org β€” say hi for me πŸ’Œ


Copyright 2017 Scott Pakin

this work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. the latest version of this license is in

<http://www.latex-project.org/lppl.txt>

and version 1.3c or later is part of all distributions of LaTeX version 2008/05/04 or later.


✨ and that's the whole page bestie ✨ this was ctanify version v1.9.1, dated 2017-04-22 β€” go forth and get your package on CTAN, you're gonna slay πŸ¦‹πŸ’–πŸŒΈ