package patch import ( "regexp" "strings" "github.com/jesseduffield/lazygit/pkg/utils" ) var hunkHeaderRegexp = regexp.MustCompile(`(?m)^@@ -(\d+)[^\+]+\+(\d+)[^@]+@@(.*)$`) func Parse(patchStr string) *Patch { // ignore trailing newline. lines := strings.Split(strings.TrimSuffix(patchStr, "\n"), "\n") hunks := []*Hunk{} patchHeader := []string{} var currentHunk *Hunk for _, line := range lines { if strings.HasPrefix(line, "@@") { oldStart, newStart, headerContext := headerInfo(line) currentHunk = &Hunk{ oldStart: oldStart, newStart: newStart, headerContext: headerContext, bodyLines: []*PatchLine{}, } hunks = append(hunks, currentHunk) } else if currentHunk != nil { currentHunk.bodyLines = append(currentHunk.bodyLines, newHunkLine(line)) } else { patchHeader = append(patchHeader, line) } } return &Patch{ hunks: hunks, header: patchHeader, } } func headerInfo(header string) (int, int, string) { match := hunkHeaderRegexp.FindStringSubmatch(header) oldStart := utils.MustConvertToInt(match[1]) newStart := utils.MustConvertToInt(match[2]) headerContext := match[3] return oldStart, newStart, headerContext } func newHunkLine(line string) *PatchLine { if line == "" { return &PatchLine{ Kind: CONTEXT, Content: "", } } firstChar := line[:1] kind := parseFirstChar(firstChar) return &PatchLine{ Kind: kind, Content: line, } } func parseFirstChar(firstChar string) PatchLineKind { switch firstChar { case " ": return CONTEXT case "+": return ADDITION case "-": return DELETION case "\\": return NEWLINE_MESSAGE } return CONTEXT }