├── LICENSE ├── README.md └── src2pdf /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Juan Pablo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # source-code-to-pdf 2 | 3 | ## Origins 4 | 5 | This useful utility was born out of the necessity of putting the source code of a friend's app into a PDF. 6 | I couldn't find anything ready to use, but [@terdon](http://superuser.com/users/151431/terdon) created a [fantastic script](http://superuser.com/a/601412/610059) that uses **LaTeX**, I took it and crafted this horrible, but useful, big BASH script. :) 7 | 8 | ## How to use 9 | 10 | **WARNING**: tested ONLY in Ubuntu 14.04 11 | 12 | ``` 13 | cd to-your-awesome-project-root 14 | wget https://raw.githubusercontent.com/eljuanchosf/source-code-to-pdf/master/src2pdf 15 | chmod +x src2pdf 16 | vim src2pdf 17 | # Edit the variables in the top of the file 18 | ./src2pdf my_source_code 19 | ``` 20 | 21 | The output file will be `my_source_code.pdf`, but also the *LaTeX* file will be left in case you want to use it. 22 | 23 | ### File types 24 | 25 | There is one **very important** code block. It is used to specify which files we want to include and what languages are they written: 26 | 27 | ```sh 28 | # The language # File pattern # Exclude files 29 | file_types[0]="php|-name '*.php'|! -name '*.blade.php'" 30 | file_types[1]="html|-name '*.blade.php'|" 31 | ``` 32 | 33 | In the example, I go for `php` and `.blade.php` files. 34 | Since Python's *Pygments* doesn't have a *blade* format, I set it as HTML. In this way, Pygments will know what language to use when doing the syntax highlightning. 35 | 36 | You can add as many groups as you want. Copy, paste and replace. 37 | 38 | Each group's section is sepparated by a pipe (|): 39 | * The first section is the language name according to Pygments specification. 40 | * The second section is a pattern on what files do you want to include. 41 | * The third section is a pattern on what files do you want to *exclude*. 42 | 43 | There is nothing more to it... enjoy! (let me know if you use it!) 44 | 45 | ## Want to contribute? 46 | 47 | Fork, modify, commit, push, pull request. :) 48 | -------------------------------------------------------------------------------- /src2pdf: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Check everything is installed: 4 | PYTHON_PATH=$(which python) 5 | return_status_1=$(echo $? 2> /dev/null) 6 | PIP_PATH=$(which pip 2> /dev/null) 7 | return_status_2=$(echo $?) 8 | #TEX_PATH=$(which texlive-latex-extra 2> /dev/null) 9 | #return_status_3=$(echo $?) 10 | sudo apt-get -y -qq install python python-pip texlive-latex-extra 11 | pip install --user Pygments 12 | 13 | tex_file=$1 14 | 15 | # EDIT THESE VARIABLES!!!! 16 | doc_title="My App Name" 17 | author="Who Am I" 18 | abstract=$(cat <$tex_file ## Print the tex file header 41 | \documentclass{article} 42 | \usepackage{minted} 43 | \usepackage{url} 44 | \urlstyle{same} % omit this command if you want monospaced-font look 45 | \newcommand\purl[1]{\protect\url{#1}} % "protected url" 46 | EOF 47 | } 48 | 49 | input_doc_header () { 50 | tex_file=$1 51 | cat <>$tex_file 52 | \begin{document} 53 | \title{$doc_title} 54 | \author{$author} 55 | 56 | \maketitle 57 | 58 | \newpage 59 | \begin{abstract} 60 | $abstract 61 | \end{abstract} 62 | 63 | \newpage 64 | \tableofcontents 65 | 66 | \newpage 67 | \section{Introduction} 68 | $introduction 69 | \section{Source code} 70 | EOF 71 | } 72 | 73 | input_section () { 74 | newdirectory=$1 75 | olddirectory=$2 76 | if [ "$newdirectory" != "$olddirectory" ]; then 77 | IFS='/' read -r -a structure <<< "$newdirectory" 78 | IFS='/' read -r -a oldstructure <<< "$olddirectory" 79 | for level in "${!structure[@]}"; do 80 | if [ "${structure[$level]}" != "${oldstructure[$level]}" ]; then 81 | case $level in 82 | 0) level_command="\subsection" 83 | ;; 84 | 1) level_command="\subsubsection" 85 | ;; 86 | 2) level_command="\paragraph" 87 | ;; 88 | *) level_command="\subparagraph" 89 | ;; 90 | esac 91 | file_title=${structure[$level]} 92 | echo "$level_command{\purl{/$file_title}}" >> $tex_file ## Create a section for each file 93 | fi 94 | done 95 | fi 96 | olddirectory=$newdirectory 97 | } 98 | 99 | input_listings () { 100 | olddirectory="/" 101 | for file in "${files_to_process[@]}"; do ## Loop through each file 102 | 103 | file_title=$file 104 | directory=$(dirname "${file}") 105 | 106 | if [ -d "./${file}" ]; then 107 | echo "Skipping ./${file}" 108 | else 109 | echo "\newpage" >> $tex_file ## start each section on a new page 110 | input_section $directory $olddirectory 111 | echo "\subparagraph{\purl{/$file_title}}" >> $tex_file ## Create a section for each file 112 | echo "\inputminted[linenos]{$language}{$file}" >> $tex_file 113 | fi 114 | done 115 | } 116 | 117 | input_minted_header $tex_file 118 | input_doc_header $tex_file 119 | for i in "${!file_types[@]}"; do 120 | IFS='|' read -r -a file_type <<< "${file_types[$i]}" 121 | language=${file_type[0]} 122 | files_to_include=${file_type[1]} 123 | files_to_exclude=${file_type[2]} 124 | 125 | # Get the list of files to process 126 | cmd="find . -type d \( -name storage -o -name vendor \) -prune -o -type f $files_to_include \ 127 | ! -regex '.*/\..*' ! -name '.*' $files_to_exclude ! -name '*~' ! -name 'src2pdf' \ 128 | | sed 's/^\..//'" 129 | files_to_process=( $(eval $cmd) ) 130 | input_listings 131 | done 132 | echo "\end{document}" >> $tex_file 133 | 134 | pdflatex -shell-escape $tex_file -output-directory . && pdflatex -shell-escape $tex_file -output-directory . 135 | find . -name "$tex_file.*" ! -name "$tex_file.pdf" -type f -exec rm -f {} + 136 | ## This needs to be run twice for the TOC to be generated 137 | --------------------------------------------------------------------------------