Skip to content

Latest commit

 

History

History
167 lines (163 loc) · 4.86 KB

clio.org

File metadata and controls

167 lines (163 loc) · 4.86 KB
\section{Introduction}
!The \texttt{clio} package implements functions to automate routine
!input and output operations in command-line programs.
Examples include
iterating over input files, and printing author and program
information. These operations are not complicated, and we could
re-write them whenever needed. But to achieve the level of uniformity
that makes a tool inconspicuous enough to stand a chance of being
useful, we delegate them to a package.

\section{Implementation}
The package contains hooks for imports, type declarations, 
and functions.
package clio

import (
	  //<<Imports>>
)

//<<Type declarations>>
//<<Functions>>
\subsection{Function \texttt{ParseFiles}}
!\texttt{ParseFiles} iterates over a set of files and applies the same
!function to each one. The arguments of that function are variadic and
!have the empty interface type.
func ParseFiles(files []string, fn FileAction, args ...interface{}) {
	  r := os.Stdin
	  if len(files) == 0 {
		  fn(r, args...)
	  } else {
		  //<<Iterate over files>>
	  }
}
!\texttt{FileAction} takes as first, and possibly only, argument an
!\texttt{io.Reader}. In addition, it can take variadic
!arguments of type empty interface.
type FileAction func(io.Reader, ...interface{})
We have used functions from the packages \texttt{io} and \texttt{os}.
"io"
"os"
The function is applied to each file in turn. 
for _, f := range files {
	  r, err := os.Open(f)
	  if err != nil {
		  log.Fatalf("couldn't open %q\n", f)
	  }
	  fn(r, args...)
	  r.Close()
}
We close the implementation of \texttt{ParseFiles} by importing the
\texttt{log} package.
"log"
\subsection{Function \texttt{PrintInfo}}
!\texttt{PrintInfo} prints the name of a program, its version, date of
!compilation, author names, their email addresses, and the program's
!license. Author names and email addresses are comma-separated.
func PrintInfo(name, version, date, authors, emails,
	  license string) {
	  fmt.Printf("%s %s, %s\n", name, version, date)
	  //<<Print authors and email addresses>>
	  fmt.Printf("License: %s\n", license)
}
aus := strings.Split(authors, ",")
ems := strings.Split(emails, ",")
if len(aus) == 1 {
	  //<<Print single author>>
} else if len(aus) > 1 {
	  //<<Print multiple authors>>
}
"strings"
fmt.Printf("Author: %s, %s\n", aus[0], ems[0])
fmt.Printf("Authors:\n")
for i, au := range aus {
	  fmt.Printf("\t%d) %s, %s\n", i+1, au, ems[i])
}
\subsection{Function \texttt{Usage}}
!\texttt{Usage} sets the response to a request for
!help.
This is achieved by setting the \texttt{flag.Usage} function.
func Usage(usage, purpose, example string) {
	  flag.Usage = func() {
		  o := flag.CommandLine.Output()
		  fmt.Fprintf(o, "Usage: %s\n%s\nExample: %s\n",
			  usage, purpose, example)
		  fmt.Fprintf(o, "Options:\n")
		  flag.PrintDefaults()
	  }
}
We import the \texttt{flag} and \texttt{fmt} packages.
"flag"
"fmt"
\subsection{Function \texttt{PrepLog}}
In \texttt{util} and elsewhere, we handle errors via the \texttt{log}
package. By default, this prefixes the error message with time and
date. For command line programs, we'd like error messages prefixed
with the name of the program and with date and time suppressed.

!\texttt{PrepLog} takes as argument the program name and sets
!this as the prefix for error messages from the \texttt{log} package.
func PrepLog(name string) {
	  m := fmt.Sprintf("%s: ", name)
	  log.SetPrefix(m)
	  log.SetFlags(0)
}