;; Copyright 2001 Matthew Danish <mrd@debian.org>
;; Under the terms of the GNU General Public License version 2
;; http://www.gnu.org/

(defun interleave (token seq)
  (cond
   ((<= (length seq) 1)
    seq)
   (t
    (cons (car seq)
	  (mapcan (lambda (x)
		    (list token x))
		  (cdr seq))))))


;; It's ugly, but it does its job. :)
(defmacro reference-guide-latex (stream title author &rest body)
  (labels ((escape-string
	    (str)
	    
	    (let ((len (length str))) 
	      (with-output-to-string
		(stream)

		(do ((i 0 (1+ i)))
		  ((>= i len) t)
		  (cond
		    ((and (char= (aref str i) #\-)
			  (< i (- len 1))
			  (char= (aref str (+ i 1)) #\-))
		     (princ "-\\/" stream))
		    ((or (char= (aref str i) #\{)
			 (char= (aref str i) #\})
			 (char= (aref str i) #\#)
			 (char= (aref str i) #\$)
			 (char= (aref str i) #\%)
			 (char= (aref str i) #\&)
			 (char= (aref str i) #\~)
			 (char= (aref str i) #\_)
			 (char= (aref str i) #\^))
		     (princ "\\" stream)
		     (princ (aref str i) stream))
		    ((char= (aref str i) #\\)
		     (princ "$\\backslash$" stream))
		    (t
		     (princ (aref str i) stream)))))))

	   (escape-control-chars
	    (l)

	    (typecase l
	      (string (escape-string l))
	      (list (mapcar #'escape-control-chars l))
	      (t l))))
    `(progn
       (format ,stream "\\documentclass[twocolumn]{article}
\\usepackage[T1]{fontenc}
\\usepackage[latin1]{inputenc}
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\makeatletter
\\renewcommand{\\section}{\\@startsection{section}{1}{0pt}{2\\baselineskip}%
{\\baselineskip}{\\large\\sffamily\\centering}}
\\makeatother
\\setcounter{secnumdepth}{0}
\\catcode`<=13
\\def<#1>{$\\langle${\\itshape #1}$\\rangle$}
\\lhead{~A}
\\rhead{\\textsc{~A}}
\\begin{document}~%
" ,title ,author)
       ,@(mapcar (lambda (heading)
		   `(progn
		      (format ,stream "\\section{~A}~%~%" ,(cadar heading))
		      ,@(mapcar (lambda (command)
				  `(progn
				     (format ,stream "\\paragraph{~A}~%~%" ,(apply #'concatenate 'string (interleave " \\\\ " (escape-control-chars (cdar command)))))
				     ,@(mapcar (lambda (l)
						 (let ((line (escape-control-chars l)))
						   (typecase line
						     (string
						      `(format ,stream "~A" ,line))
						     (list
						      (case (car line)
							((:program)
							 `(format ,stream "\\texttt{~A}" ,(apply #'concatenate 'string (cdr line))))
							((:keyword)
							 `(format ,stream "\\textit{~A}" ,(apply #'concatenate 'string (cdr line))))
							((:filename)
							 `(format ,stream "\\textsf{~A}" ,(apply #'concatenate 'string (cdr line))))
							((:commands)
							 `(format ,stream
								  "~%\\begin{quote}~%~A~%\\end{quote}~%"
								  ,(apply #'concatenate 'string (interleave " \\\\ " (cdr line))))))))))
					       (cdr command))
				     (format ,stream "~%~%")))
				(cdr heading))
		      (format ,stream "~%~%")))
		 body)
       (format ,stream "\\end{document}~%"))))



(defmacro reference-guide-html (stream title author &rest body)
  (labels ((escape-string
	    (str)

	    (with-output-to-string
	      (stream)

	      (do ((i 0 (1+ i)))
		  ((>= i (length str)) t)
		(cond
		 ((char= (aref str i) #\<)
		  (princ "&lt;" stream))
		 ((char= (aref str i) #\>)
		  (princ "&gt;" stream))
		 (t
		  (princ (aref str i) stream))))))

	   (escape-control-chars
	    (l)

	    (typecase l
	      (string (escape-string l))
	      (list (mapcar #'escape-control-chars l))
	      (t l))))
		    
    `(progn
       (format ,stream "<HTML>~%<HEAD>~%<TITLE>~A</TITLE>~%</HEAD>~%<BODY><CENTER><H1>~A</H1>~%<BR>~%<B>~A</B></CENTER>~%~%"
	       ,title ,title ,author)
       ,@(mapcar (lambda (heading)
		   `(progn
		      (format ,stream "<H3>~A</H3>~%" ,(cadar heading))
		      ,@(mapcar (lambda (command)
				  `(progn
				     (format ,stream "<B>~A</B>~%~%" ,(apply #'concatenate 'string (interleave " <BR> " (escape-control-chars (cdar command)))))
				     ,@(mapcar (lambda (l)
						 (let ((line (escape-control-chars l)))
						   (typecase line
						     (string
						      `(format ,stream "~A" ,line))
						     (list
						      (case (car line)
							((:program)
							 `(format ,stream "<FONT FACE=\"FIXED\">~A</FONT>" ,(apply #'concatenate 'string (cdr line))))
							((:keyword)
							 `(format ,stream "<I>~A</I>" ,(apply #'concatenate 'string (cdr line))))
							((:filename)
							 `(format ,stream "<FONT FACE=\"Helvetica\">~A</FONT>" ,(apply #'concatenate 'string (cdr line))))
							((:commands)
							 `(format ,stream
								  "~%<P><CENTER><CODE>~A</CODE></CENTER></P>~%"
								  ,(apply #'concatenate 'string (interleave " <BR> " (cdr line))))))))))
					       (cdr command))
				     (format ,stream "<BR><BR>~%~%")))
				(cdr heading))
		      (format ,stream "~%~%")))
		 body)
       (format ,stream "</BODY>~%</HTML>~%"))))

	

(defvar apt-dpkg-ref
  '("APT and Dpkg Quick Reference Sheet"
    "Matthew Danish"
    
    
    ((:heading "Common APT usage")
    
     ((:command "apt-get install <package>")
      "Downloads <package> and all of its dependencies, and installs or upgrades them. This will also take a package off of "
      (:keyword "hold")
      " if it was put on. See below for more info on "
      (:keyword "hold."))

     ((:command "apt-get remove [--purge] <package>")
      "Removes <package> and any packages that depend on it.  --purge specifies that packages should be "
      (:keyword "purged")
      ", see "
      (:program "dpkg -P")
      " for more information.")

     ((:command "apt-get update")
      "Updates packages listings from Debian mirrors, should be run at least once a day if you install anything that day, and every time after "
      (:filename "/etc/apt/sources.list")
      " is changed.")

     ((:command "apt-get upgrade [-u]")
      "Upgrades all packages installed to newest versions available. Will not install new or remove old packages. If a package changes dependencies and requires installation of a new package, it will not be upgraded, it will be put on "
      (:keyword "hold")
      " instead. "
      (:program "apt-get upgrade")
      " will not upgrade packages put on "
      (:keyword "hold")
      " (that is the meaning of "
      (:keyword "hold")
      "). See below for how to manually put packages on "
      (:keyword "hold")
      ". I suggest the `-u' option as well, because then you can see what packages are going to be upgraded.")

     ((:command "apt-get dist-upgrade [-u]")
      "Similar to "
      (:program "apt-get upgrade")
      ", except that "
      (:keyword "dist-upgrade")
      " will install or remove packages to satisfy dependencies.")

     ((:command "apt-cache search <pattern>")
      "Searches packages and descriptions for <pattern>.")

     ((:command "apt-cache show <package>")
      "Shows the full description of <package>.")

     ((:command "apt-cache showpkg <package>")
      "Shows a lot more detail about <package>, and its relationships to other packages.")

     ((:command "synaptic" "gdebi" "gdebi-kde" "dselect" "aptitude" "gnome-apt")
      "Graphical front ends to "
      (:keyword "APT")
      " (some of these may be in their own package, that must be installed before use). While "
      (:program "dselect")
      " is arguably the most powerful, it's also the oldest and hardest to use."))


    ((:heading "Common Dpkg usage")

     ((:command "dpkg -i <package.deb>")
      "Installs a Debian package file; one that you downloaded manually, for example.")

     ((:command "dpkg -c <package.deb>")
      "Lists the contents of <package.deb>, a .deb file.")

     ((:command "dpkg -I <package.deb>")
      "Extracts package information from <package.deb>, a .deb file.")

     ((:command "dpkg -r <package>")
      "Removes an installed package named <package>")

     ((:command "dpkg -P <package>")
      "Purges an installed package named <package>.  The difference between "
      (:keyword "remove")
      " and "
      (:keyword "purge")
      " is that while "
      (:keyword "remove")
      " only deletes data and executables, "
      (:keyword "purge")
      " also deletes all configuration files in addition.")
     
     ((:command "dpkg -L <package>")
      "Gives a listing of all the files installed by <package>.  See also "
      (:program "dpkg -c")
      " for checking the contents of a .deb file.")

     ((:command "dpkg -s <package>")
      "Shows information on the installed package <package>.  See also "
      (:program "apt-cache show")
      " for viewing package information in the Debian archive and "
      (:program "dpkg -I")
      " for viewing package information extracted from a .deb file.")

     ((:command "dpkg-reconfigure <package>")
      "Reconfigures an installed package, if it uses "
      (:keyword "debconf")
      " ("
      (:keyword "debconf")
      " provides that consistent configuration interface for package installation).  You can reconfigure "
      (:keyword "debconf")
      " itself if you want to change the front-end or priority of questions asked. For example, to reconfigure "
      (:keyword "debconf")
      " with the dialog front-end, you simply run: "
      (:commands "dpkg-reconfigure --frontend=dialog debconf"))

     ((:command "echo ``<package> hold'' | dpkg --set-selections")
      "Put <package> on "
      (:keyword "hold")
      " (command line method)")
     
     ((:command "dpkg --get-selections ``<package>''")
      "Get the current status of <package> (command line method)")

     ((:command "dpkg -S <file>")
      "Searches for <file> in package database, telling you which installed packages have that file in them. To search for a file or list the contents of a package without installing it, you can use apt-file command line tool."))



    ((:heading "Building Debian packages from Source")

     ((:command "apt-get source [-b] <package>")
      "Download the source Debian package for <package> and extract it. You must have deb-src lines in your "
      (:filename "/etc/apt/sources.list")
      " for this to work. If you supply the `-b' option and you are currently root, then the package will be automatically built if possible.")

     ((:command "apt-get build-dep <package>")
      "Download and install the packages necessary to build the source Debian package <package>.  This feature is only present in "
      (:program "apt")
      " version 0.5 and up.  Currently this means that woody and above contain this functionality.  If you have an older version of "
      (:program "apt")
      " then the easiest way to find out the build dependencies is to look in the "
      (:filename "debian/control")
      " file in the source package directory.  A common usage of this command is in conjunction with "
      (:program "apt-get source -b")
      ".  For example (as root): "
      (:commands "apt-get build-dep <package>"
		 "apt-get source -b <package>")
      "Will download the source package, all of its build dependencies, and attempt to compile the source package.")

     ((:command "dpkg-source -x <package.dsc>")
      "If you have downloaded the source package for a program manually, which includes several files such as a .orig.tar.gz (or .tar.gz if it is Debian native), a .dsc, and a .diff.gz (if it is not Debian native), then you can unpack the source package using this command on the .dsc file.")

     ((:command "dpkg-buildpackage")
      "Builds a Debian package from a Debian source tree.  You must be in the main directory of the source tree for this to work.  Sample usage: "
      (:commands "dpkg-buildpackage -rfakeroot -uc -b")
      "Where `-rfakeroot' instructs it to use the "
      (:program "fakeroot")
      " program to simulate root privileges (for ownership purposes), `-uc' stands for ``Don't cryptographically sign the changelog'', and `-b' stands for ``Build the binary package only''")

     ((:command "debuild")
      "A handy wrapper script around "
      (:program "dpkg-buildpackage")
      " that will automatically take care of using "
      (:program "fakeroot")
      " or not, as well as running "
      (:program "lintian")
      " and "
      (:program "gpg")
      " for you. This script is provided by (:program "devscripts"), so you need to install this package first."))

    ((:heading "Fixing dependencies")
     ((:command "dpkg --configure --pending")
      "If dpkg quits with an error while "
      (:program "apt-get install, upgrade, or dist-upgrade")
      "ing try running this to configure the packages that were already unpacked. Then try "
      (:program "apt-get install, upgrade, or dist-upgrade -f")
      ", and then try "
      (:program "apt-get install, upgrade, or dist-upgrade")
      " again. Repeat as needed. This usually resolves most dependency problems (also, if it mentions a specific package for some reason, you might want to try installing or removing that package)")

     ((:command "apt-get install -f" "apt-get upgrade -f" "apt-get dist-upgrade -f")
      "Attempt to fix dependencies while doing one of the above. Note that "
      (:program "apt-get install -f")
      " does not require a <package> argument."))

    ((:heading "See Also")
     ((:command "man <package>")"To learn more about this commands you can always consult their man pages, e.g. man apt-get, man dpkg. You can also find information about this and more tools, HOWTOs, manuals, etc at http://www.debian.org/doc/."))))


(defmacro output-document (stream type doc)
  (ecase type
	 ((:latex)
	  `(reference-guide-latex . (,stream . ,(symbol-value doc))))
	 ((:html)
	  `(reference-guide-html . (,stream . ,(symbol-value doc))))))


(with-open-file (stream "apt-dpkg-ref.tex" :direction :output)
		(output-document stream :latex apt-dpkg-ref))

(with-open-file (stream "apt-dpkg-ref.html" :direction :output)
		(output-document stream :html apt-dpkg-ref))


(quit) 
  
	     
   
