[callpath] add depth (optional) parameter

For the 'callpath' verb, the output can be adjusted to limit the printing
the stack depth.

i.e. '%{callpath:3}' will print '~.a.b.c'
diff --git a/format.go b/format.go
index 1b11655..7160674 100644
--- a/format.go
+++ b/format.go
@@ -14,6 +14,7 @@
 	"path/filepath"
 	"regexp"
 	"runtime"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -81,7 +82,7 @@
 	"s",
 	"s",
 	"s",
-	"s",
+	"0",
 	"",
 }
 
@@ -162,7 +163,7 @@
 //     %{message}   Message (string)
 //     %{longfile}  Full file name and line number: /a/b/c/d.go:23
 //     %{shortfile} Final file name element and line number: d.go:23
-//     %{callpath}  Callpath like main.a.b.c...c  "..." meaning recursive call
+//     %{callpath}  Callpath like main.a.b.c...c  "..." meaning recursive call ~. meaning truncated path
 //     %{color}     ANSI color based on log level
 //
 // For normal types, the output can be customized by using the 'verbs' defined
@@ -179,6 +180,9 @@
 // "%{color:bold}%{time:15:04:05} %{level:-8s}%{color:reset} %{message}" will
 // just colorize the time and level, leaving the message uncolored.
 //
+// For the 'callpath' verb, the output can be adjusted to limit the printing
+// the stack depth. i.e. '%{callpath:3}' will print '~.a.b.c'
+//
 // Colors on Windows is unfortunately not supported right now and is currently
 // a no-op.
 //
@@ -216,12 +220,12 @@
 		}
 
 		// Handle layout customizations or use the default. If this is not for the
-		// time or color formatting, we need to prefix with %.
+		// time, color formatting or callpath, we need to prefix with %.
 		layout := defaultVerbsLayout[verb]
 		if m[4] != -1 {
 			layout = format[m[4]:m[5]]
 		}
-		if verb != fmtVerbTime && verb != fmtVerbLevelColor {
+		if verb != fmtVerbTime && verb != fmtVerbLevelColor && verb != fmtVerbCallpath {
 			layout = "%" + layout
 		}
 
@@ -275,6 +279,12 @@
 			output.Write([]byte(r.Time.Format(part.layout)))
 		} else if part.verb == fmtVerbLevelColor {
 			doFmtVerbLevelColor(part.layout, r.Level, output)
+		} else if part.verb == fmtVerbCallpath {
+			depth, err := strconv.Atoi(part.layout)
+			if err != nil {
+				depth = 0
+			}
+			output.Write([]byte(formatCallpath(calldepth+1, depth)))
 		} else {
 			var v interface{}
 			switch part.verb {
@@ -314,8 +324,6 @@
 						v = formatFuncName(part.verb, f.Name())
 					}
 				}
-			case fmtVerbCallpath:
-				v = formatCallpath(calldepth + 1)
 			default:
 				panic("unhandled format part")
 			}
@@ -351,14 +359,19 @@
 	panic("unexpected func formatter")
 }
 
-func formatCallpath(calldepth int) string {
+func formatCallpath(calldepth int, depth int) string {
 	v := ""
 	callers := make([]uintptr, 64)
 	n := runtime.Callers(calldepth+2, callers)
 	oldPc := callers[n-1]
 
+	start := n - 3
+	if depth > 0 && start >= depth {
+		start = depth - 1
+		v += "~."
+	}
 	recursiveCall := false
-	for i := n - 3; i >= 0; i-- {
+	for i := start; i >= 0; i-- {
 		pc := callers[i]
 		if oldPc == pc {
 			recursiveCall = true
@@ -369,7 +382,7 @@
 			recursiveCall = false
 			v += ".."
 		}
-		if i < n-3 {
+		if i < start {
 			v += "."
 		}
 		if f := runtime.FuncForPC(pc); f != nil {
diff --git a/log_test.go b/log_test.go
index 9e1d18c..c7a645f 100644
--- a/log_test.go
+++ b/log_test.go
@@ -44,14 +44,13 @@
 	rec(log, r-1)
 }
 
-func TestLogCallpath(t *testing.T) {
+func testCallpath(t *testing.T, format string, expect string) {
 	buf := &bytes.Buffer{}
 	SetBackend(NewLogBackend(buf, "", log.Lshortfile))
-	SetFormatter(MustStringFormatter("%{callpath} %{message}"))
-	//	SetFormatter(MustStringFormatter("%{callpath} %{message}"))
+	SetFormatter(MustStringFormatter(format))
 
-	log := MustGetLogger("test")
-	rec(log, 6)
+	logger := MustGetLogger("test")
+	rec(logger, 6)
 
 	parts := strings.SplitN(buf.String(), " ", 3)
 
@@ -60,7 +59,7 @@
 		t.Errorf("incorrect filename: %s", parts[0])
 	}
 	// Verify that the correct callpath is registered by go-logging
-	if !strings.HasPrefix(parts[1], "TestLogCallpath.rec...rec.a.b.c") {
+	if !strings.HasPrefix(parts[1], expect) {
 		t.Errorf("incorrect callpath: %s", parts[1])
 	}
 	// Verify that the correct message is registered by go-logging
@@ -69,6 +68,15 @@
 	}
 }
 
+func TestLogCallpath(t *testing.T) {
+	testCallpath(t, "%{callpath} %{message}", "TestLogCallpath.testCallpath.rec...rec.a.b.c")
+	testCallpath(t, "%{callpath:-1} %{message}", "TestLogCallpath.testCallpath.rec...rec.a.b.c")
+	testCallpath(t, "%{callpath:0} %{message}", "TestLogCallpath.testCallpath.rec...rec.a.b.c")
+	testCallpath(t, "%{callpath:1} %{message}", "~.c")
+	testCallpath(t, "%{callpath:2} %{message}", "~.b.c")
+	testCallpath(t, "%{callpath:3} %{message}", "~.a.b.c")
+}
+
 func BenchmarkLogMemoryBackendIgnored(b *testing.B) {
 	backend := SetBackend(NewMemoryBackend(1024))
 	backend.SetLevel(INFO, "")