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  }