github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/misc/logos/misc.go (about)

     1  package logos
     2  
     3  import (
     4  	"strings"
     5  	"unicode"
     6  
     7  	"github.com/gdamore/tcell/v2"
     8  	runewidth "github.com/mattn/go-runewidth"
     9  )
    10  
    11  // splits a string into lines by newline.
    12  func splitLines(s string) (ss []string) {
    13  	return strings.Split(s, "\n")
    14  }
    15  
    16  // splits a string according to unicode spaces.
    17  func splitSpaces(s string) (ss []string) {
    18  	buf := []rune{}
    19  	for _, r := range s {
    20  		if unicode.IsSpace(r) {
    21  			// continue
    22  			if len(buf) > 0 {
    23  				ss = append(ss, string(buf))
    24  				buf = nil
    25  			}
    26  		} else {
    27  			buf = append(buf, r)
    28  		}
    29  	}
    30  	if len(buf) > 0 {
    31  		ss = append(ss, string(buf))
    32  		// buf = nil
    33  	}
    34  	return ss
    35  }
    36  
    37  func toRunes(s string) []rune {
    38  	runes := make([]rune, 0, len(s))
    39  	for _, r := range s {
    40  		runes = append(runes, r)
    41  	}
    42  	return runes
    43  }
    44  
    45  // gets the terminal display width of a string.
    46  // must be compatible with nextCharacter().
    47  // NOTE: must be kept in sync with nextCharacter(); see tests.
    48  func widthOf(s string) (l int) {
    49  	zwj := false // zero width joiner '\u200d'.
    50  	for _, r := range s {
    51  		if r == '\u200d' {
    52  			zwj = true
    53  			continue
    54  		}
    55  		if zwj {
    56  			zwj = false
    57  			continue
    58  		}
    59  		switch runewidth.RuneWidth(r) {
    60  		case 0:
    61  			if isCombining(r) {
    62  				// combining characters have no length.
    63  			} else {
    64  				l++ // show a blank instead, weird.
    65  			}
    66  		case 1:
    67  			l++
    68  		case 2:
    69  			l += 2
    70  		default:
    71  			panic("should not happen")
    72  		}
    73  	}
    74  	return l
    75  }
    76  
    77  // given runes of a valid utf8 string,
    78  // return a string that represents
    79  // the next single character (with any modifiers).
    80  // w: width of character. n: number of runes read
    81  func nextCharacter(rz []rune) (s string, w int, n int) {
    82  	for n = 0; n < len(rz); n++ {
    83  		r := rz[n]
    84  		if r == '\u200d' {
    85  			// special case: zero width joins.
    86  			s = s + string(r)
    87  			if n+1 < len(rz) {
    88  				s = s + string(rz[n+1])
    89  				n++
    90  				continue
    91  			} else {
    92  				// just continue, return invalid string s.
    93  				n++
    94  				return
    95  			}
    96  		} else if 0 < len(s) {
    97  			return
    98  		} else {
    99  			// append r to s and inc w.
   100  			rw := runewidth.RuneWidth(r)
   101  			s = s + string(r)
   102  			if rw == 0 {
   103  				if isCombining(r) {
   104  					// no width
   105  				} else {
   106  					w += 1
   107  				}
   108  			} else {
   109  				w += rw
   110  			}
   111  		}
   112  	}
   113  	return
   114  }
   115  
   116  //----------------------------------------
   117  
   118  func AbsCoord(elem Elem) (crd Coord) {
   119  	for elem != nil {
   120  		crd = crd.Add(elem.GetCoord())
   121  		elem = elem.GetParent()
   122  	}
   123  	return
   124  }
   125  
   126  var randColors []Color = []Color{
   127  	tcell.ColorAliceBlue,
   128  	tcell.ColorAntiqueWhite,
   129  	tcell.ColorAquaMarine,
   130  	tcell.ColorAzure,
   131  	tcell.ColorBeige,
   132  	tcell.ColorBisque,
   133  	tcell.ColorBlanchedAlmond,
   134  	tcell.ColorBlueViolet,
   135  	tcell.ColorBrown,
   136  	tcell.ColorBurlyWood,
   137  }
   138  
   139  var rctr = 0
   140  
   141  func RandColor() Color {
   142  	rctr++
   143  	return randColors[rctr%len(randColors)]
   144  }
   145  
   146  func IsInBounds(x, y int, origin Coord, size Size) bool {
   147  	if x < origin.X || y < origin.Y {
   148  		return false
   149  	}
   150  	if origin.X+size.Width <= x ||
   151  		origin.Y+size.Height <= y {
   152  		return false
   153  	}
   154  	return true
   155  }