func fmtFn() filepath.WalkFunc {

	return func(pathThusFar string, f os.FileInfo, err error) error {

		if strings.HasSuffix(filepath.Dir(pathThusFar), f.Name()) {
			return nil
		}

		if f.IsDir() && !strings.HasSuffix(pathThusFar, string(os.PathSeparator)) {
			pathThusFar += string(os.PathSeparator)
		}
		if f.IsDir() {
			if *recurs && !stringInSlice(pathThusFar, excluded) {
				return nil
			} else {
				return filepath.SkipDir
			}
		} else if f.Mode().IsRegular() && strings.HasSuffix(f.Name(), ".proto") {
			parser.FixFloatingComments(pathThusFar)

			d, err := parser.ParseFile(pathThusFar, filepath.Dir(pathThusFar), *imp_path)
			if err != nil {
				fmt.Println("Parsing error in " + pathThusFar + "!")
				return err
			} else {
				header := parser.ReadFileHeader(pathThusFar)
				formattedFile := d.Fmt(f.Name())
				formattedFile = strings.TrimSpace(formattedFile)
				if len(header) != 0 {
					formattedFile = header + "\n" + formattedFile
				}

				fo, _ := os.Create(pathThusFar)

				fo.WriteString(formattedFile)
				fo.Close()

				fmt.Println("Successfully Formatted " + pathThusFar)
				return nil
			}
		} else {
			return errors.New(f.Name() + " cannot be processed.")
		}
	}

}
func parseAndTestFile(t *testing.T, filename string) {
	parser.FixFloatingComments(filename)

	d, err := parser.ParseFile(filename, "./")
	if err != nil {
		t.Error(err)
		os.Exit(1)
	} else {

		header := parser.ReadFileHeader(filename)

		formattedFile := d.Fmt(filename)
		formattedFile = strings.TrimSpace(formattedFile)
		if len(header) != 0 {
			formattedFile = header + formattedFile
		}

		// Test if formatted file can be parsed
		fo, err := os.Create("tempOutput.proto")
		if err != nil {
			t.Error(err)
		}
		defer os.Remove("tempOutput.proto")
		if len(formattedFile) > 0 {
			fo.WriteString(formattedFile)
		}
		fo.Close()

		_, err2 := parser.ParseFile("tempOutput.proto", "./", "../../../")
		if err2 != nil {
			t.Error(err2)
		}

		// Test if formatted string is equal to the Gold standard
		goldString, err := ioutil.ReadFile(strings.Split(filename, ".")[0] + "_Gold." + strings.Split(filename, ".")[1])
		if err != nil {
			t.Error(err)
		}

		if parser.Strcmp(formattedFile, strings.TrimSpace(string(goldString))) != 0 {
			t.Error("Failed the gold standard with: " + fmt.Sprintf("%v", parser.Strcmp(formattedFile, strings.TrimSpace(string(goldString)))))
		}

		return
	}
}
func main() {
	data, err := ioutil.ReadAll(os.Stdin)

	// Declare the request and response structures
	Request := new(plugin.CodeGeneratorRequest)   // The input.
	Response := new(plugin.CodeGeneratorResponse) // The output.

	if err != nil {
		Response.Error = proto.String("reading input")
	} else {
		if err = proto.Unmarshal(data, Request); err != nil {
			Response.Error = proto.String("parsing input proto")
		}
		if len(Request.GetFileToGenerate()) == 0 {
			Response.Error = proto.String("No files to generate")
		}

		formattedFiles := make(map[string]string)

		for _, fileToGen := range Request.GetFileToGenerate() {
			for _, protoFile := range Request.GetProtoFile() {
				if protoFile.GetName() == fileToGen {
					fileSet := descriptor.FileDescriptorSet{Request.GetProtoFile(), nil}
					formattedFiles[fileToGen] = fileSet.Fmt(fileToGen)

					if parser.CheckFloatingComments(fileToGen) {
						os.Stderr.WriteString("You had unattached comments that got lost.\n")
					}

					header := parser.ReadFileHeader(fileToGen)
					if len(header) != 0 {
						formattedFiles[fileToGen] = header + formattedFiles[fileToGen]
					}
					//os.Stderr.WriteString(fmt.Sprintf("%v", formattedFiles[fileToGen]))
				}
			}
		}

		// Create the slice of response files
		Response.File = make([]*plugin.CodeGeneratorResponse_File, len(formattedFiles))

		i := 0
		for fileName, formatFile := range formattedFiles {

			fo, err := os.Create("tempOutput.proto")
			if err != nil {
				panic(err)
			}
			defer os.Remove("tempOutput.proto")
			fo.WriteString(formatFile)
			fo.Close()

			_, err2 := parser.ParseFile("tempOutput.proto", "./", "../../../")
			if err2 != nil {
				Response.Error = proto.String(err2.Error())
			} else {
				Response.File[i] = new(plugin.CodeGeneratorResponse_File)

				Response.File[i].Name = proto.String(fileName)
				Response.File[i].Content = proto.String(formatFile)

				i += 1

			}
		}

		// Send back the results.
		data, err = proto.Marshal(Response)
		if err != nil {
			os.Stderr.Write([]byte("failed to marshal output proto"))
		}
		_, err = os.Stdout.Write(data)
		if err != nil {
			os.Stderr.Write([]byte("failed to write output proto"))
		}

	}
}