github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/git.go (about) 1 package main 2 3 import ( 4 "strings" 5 6 "github.com/xyproto/vt100" 7 ) 8 9 var gitRebasePrefixes = []string{"p", "pick", "f", "fixup", "r", "reword", "d", "drop", "e", "edit", "s", "squash", "x", "exec", "b", "break", "l", "label", "t", "reset", "m", "merge"} 10 11 // getNextInCycle returns the next element in the cycle, given the current element and the cycle 12 func getNextInCycle(current string, cycle []string) string { 13 for i, w := range cycle { 14 if current == w { 15 if i+1 < len(cycle) { 16 return cycle[i+1] 17 } 18 return cycle[0] 19 } 20 } 21 return "" 22 } 23 24 // nextGitRebaseKeyword will use the first word in the given line, 25 // and replace it with the next git rebase keyword (as ordered in gitRebasePrefixes) 26 func nextGitRebaseKeyword(line string) string { 27 cycle1 := filterS(gitRebasePrefixes, func(s string) bool { return len(s) > 1 }) 28 cycle2 := filterS(gitRebasePrefixes, func(s string) bool { return len(s) == 1 }) 29 30 firstWord := strings.Fields(line)[0] 31 next := getNextInCycle(firstWord, cycle1) 32 33 if next == "" { 34 next = getNextInCycle(firstWord, cycle2) 35 } 36 37 if next == "" { 38 // Return the line as it is, no git rebase keyword found 39 return line 40 } 41 42 // Return the line with the keyword replaced with the next one in cycle1 or cycle2 43 return strings.Replace(line, firstWord, next, 1) 44 } 45 46 func (e *Editor) gitHighlight(line string) string { 47 var coloredString string 48 if strings.HasPrefix(line, "#") { 49 filenameColor := vt100.Red 50 renameColor := vt100.Magenta 51 if strings.HasPrefix(line, "# On branch ") { 52 coloredString = vt100.DarkGray.Get(line[:12]) + vt100.LightCyan.Get(line[12:]) 53 } else if strings.HasPrefix(line, "# Your branch is up to date with '") && strings.Count(line, "'") == 2 { 54 parts := strings.SplitN(line, "'", 3) 55 coloredString = vt100.DarkGray.Get(parts[0]+"'") + vt100.LightGreen.Get(parts[1]) + vt100.DarkGray.Get("'"+parts[2]) 56 } else if line == "# Changes to be committed:" { 57 coloredString = vt100.DarkGray.Get("# ") + vt100.LightBlue.Get("Changes to be committed:") 58 } else if line == "# Changes not staged for commit:" { 59 coloredString = vt100.DarkGray.Get("# ") + vt100.LightBlue.Get("Changes not staged for commit:") 60 } else if line == "# Untracked files:" { 61 coloredString = vt100.DarkGray.Get("# ") + vt100.LightBlue.Get("Untracked files:") 62 } else if strings.Contains(line, "new file:") { 63 parts := strings.SplitN(line[1:], ":", 2) 64 coloredString = vt100.DarkGray.Get("#") + vt100.LightYellow.Get(parts[0]) + vt100.DarkGray.Get(":") + filenameColor.Get(parts[1]) 65 } else if strings.Contains(line, "modified:") { 66 parts := strings.SplitN(line[1:], ":", 2) 67 coloredString = vt100.DarkGray.Get("#") + vt100.LightYellow.Get(parts[0]) + vt100.DarkGray.Get(":") + filenameColor.Get(parts[1]) 68 } else if strings.Contains(line, "deleted:") { 69 parts := strings.SplitN(line[1:], ":", 2) 70 coloredString = vt100.DarkGray.Get("#") + vt100.LightYellow.Get(parts[0]) + vt100.DarkGray.Get(":") + filenameColor.Get(parts[1]) 71 } else if strings.Contains(line, "renamed:") { 72 parts := strings.SplitN(line[1:], ":", 2) 73 coloredString = vt100.DarkGray.Get("#") + vt100.LightYellow.Get(parts[0]) + vt100.DarkGray.Get(":") 74 if strings.Contains(parts[1], "->") { 75 filenames := strings.SplitN(parts[1], "->", 2) 76 coloredString += renameColor.Get(filenames[0]) + vt100.White.Get("->") + renameColor.Get(filenames[1]) 77 } else { 78 coloredString += filenameColor.Get(parts[1]) 79 } 80 } else if fields := strings.Fields(line); strings.HasPrefix(line, "# Rebase ") && len(fields) >= 5 && strings.Contains(fields[2], "..") { 81 textColor := vt100.LightGray 82 commitRange := strings.SplitN(fields[2], "..", 2) 83 coloredString = vt100.DarkGray.Get("# ") + textColor.Get(fields[1]) + " " + vt100.LightBlue.Get(commitRange[0]) + textColor.Get("..") + vt100.LightBlue.Get(commitRange[1]) + " " + textColor.Get(fields[3]) + " " + vt100.LightBlue.Get(fields[4]) + " " + textColor.Get(strings.Join(fields[5:], " ")) 84 } else { 85 coloredString = vt100.DarkGray.Get(line) 86 } 87 } else if strings.HasPrefix(line, "GIT:") { 88 coloredString = vt100.DarkGray.Get(line) 89 } else if strings.HasPrefix(line, "From ") && strings.Contains(line, "#") { 90 parts := strings.SplitN(line, "#", 2) 91 // Also syntax highlight the e-mail address 92 if strings.Contains(parts[0], "<") && strings.Contains(parts[0], ">") { 93 parts1 := strings.SplitN(parts[0], "<", 2) 94 parts2 := strings.SplitN(parts1[1], ">", 2) 95 coloredString = vt100.LightBlue.Get(parts1[0][:5]) + vt100.White.Get(parts1[0][5:]) + vt100.Red.Get("<") + vt100.LightYellow.Get(parts2[0]) + vt100.Red.Get(">") + vt100.White.Get(parts2[1]) + vt100.DarkGray.Get("#"+parts[1]) 96 } else { 97 coloredString = vt100.LightCyan.Get(parts[0]) + vt100.DarkGray.Get("#"+parts[1]) 98 } 99 } else if hasAnyPrefix(line, []string{"From:", "To:", "Cc:", "Bcc:", "Subject:", "Date:", "Message-Id:", "X-Mailer:", "MIME-Version:", "Content-Type:", "Content-Transfer-Encoding:", "Reply-To:", "In-Reply-To:"}) { 100 parts := strings.SplitN(line, ":", 2) 101 if strings.Contains(parts[1], "<") && strings.Contains(parts[1], ">") { 102 parts1 := strings.SplitN(parts[1], "<", 2) 103 parts2 := strings.SplitN(parts1[1], ">", 2) 104 coloredString = vt100.LightBlue.Get(parts[0]+":") + parts1[0] + vt100.Red.Get("<") + vt100.LightYellow.Get(parts2[0]) + vt100.Red.Get(">") + vt100.White.Get(parts2[1]) 105 } else { 106 coloredString = vt100.LightBlue.Get(parts[0]+":") + vt100.LightYellow.Get(parts[1]) 107 } 108 } else if fields := strings.Fields(line); len(fields) >= 3 && hasAnyPrefixWord(line, []string{"p", "pick", "r", "reword", "e", "edit", "s", "squash", "f", "fixup", "x", "exec", "b", "break", "d", "drop", "l", "label", "t", "reset", "m", "merge"}) { 109 coloredString = vt100.Red.Get(fields[0]) + " " + vt100.LightBlue.Get(fields[1]) + " " + vt100.LightGray.Get(strings.Join(fields[2:], " ")) 110 } else { 111 coloredString = e.Git.Get(line) 112 } 113 return coloredString 114 }