github.com/mithrandie/csvq@v1.18.1/lib/syntax/element.go (about) 1 package syntax 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/mithrandie/csvq/lib/option" 8 9 "github.com/mithrandie/go-text/color" 10 ) 11 12 const ( 13 NameEffect = "syntax_name" 14 KeywordEffect = "syntax_keyword" 15 LinkEffect = "syntax_link" 16 VariableEffect = "syntax_variable" 17 FlagEffect = "syntax_flag" 18 ItalicEffect = "syntax_italic" 19 TypeEffect = "syntax_type" 20 ) 21 22 type Definition struct { 23 Name Name 24 Group []Grammar 25 Description Description 26 } 27 28 type Element interface { 29 Format(p *color.Palette) string 30 } 31 32 type Name string 33 34 func (e Name) String() string { 35 return string(e) 36 } 37 38 func (e Name) Format(p *color.Palette) string { 39 s := string(e) 40 if p != nil { 41 s = p.Render(NameEffect, s) 42 } 43 return s 44 } 45 46 type Grammar []Element 47 48 func (e Grammar) Format(p *color.Palette) string { 49 l := make([]string, 0, len(e)) 50 for _, en := range e { 51 l = append(l, en.Format(p)) 52 } 53 return strings.Join(l, " ") 54 } 55 56 type Description struct { 57 Template string 58 Values []Element 59 } 60 61 func (e Description) Format(p *color.Palette) string { 62 var decorateRequired = func(e Element) bool { 63 switch e.(type) { 64 case String, Integer, Float, Boolean, Datetime, Identifier: 65 return true 66 case Ternary: 67 s := string(e.(Ternary)) 68 if s == "TRUE" || s == "FALSE" || s == "UNKNOWN" { 69 return false 70 } 71 return true 72 case Null: 73 s := string(e.(Null)) 74 if s == "NULL" { 75 return false 76 } 77 return true 78 } 79 return false 80 } 81 82 replaces := make([]interface{}, 0, len(e.Values)) 83 for _, v := range e.Values { 84 if p == nil && decorateRequired(v) { 85 replaces = append(replaces, "_"+v.Format(p)+"_") 86 } else { 87 replaces = append(replaces, v.Format(p)) 88 } 89 } 90 return fmt.Sprintf(e.Template, replaces...) 91 } 92 93 type Keyword string 94 95 func (e Keyword) Format(p *color.Palette) string { 96 s := string(e) 97 if p != nil { 98 s = p.Render(KeywordEffect, s) 99 } 100 return s 101 } 102 103 type Link string 104 105 func (e Link) Format(p *color.Palette) string { 106 s := "<" + string(e) + ">" 107 if p != nil { 108 s = p.Render(LinkEffect, s) 109 } 110 return s 111 } 112 113 type Option []Element 114 115 func (e Option) Format(p *color.Palette) string { 116 l := make([]string, 0, len(e)) 117 for _, v := range e { 118 l = append(l, v.Format(p)) 119 } 120 return "[" + strings.Join(l, " ") + "]" 121 } 122 123 type FollowingContinuousOption []Element 124 125 func (e FollowingContinuousOption) Format(p *color.Palette) string { 126 l := make([]string, 0, len(e)) 127 for _, v := range e { 128 l = append(l, v.Format(p)) 129 } 130 return " [, " + strings.Join(l, " ") + " ...]" 131 } 132 133 type ContinuousOption []Element 134 135 func (e ContinuousOption) Format(p *color.Palette) string { 136 l := make([]string, 0, len(e)) 137 for _, v := range e { 138 l = append(l, v.Format(p)) 139 } 140 return strings.Join(l, " ") + " [, " + strings.Join(l, " ") + " ...]" 141 } 142 143 type AnyOne []Element 144 145 func (e AnyOne) Format(p *color.Palette) string { 146 l := make([]string, 0, len(e)) 147 for _, v := range e { 148 l = append(l, v.Format(p)) 149 } 150 return "{" + strings.Join(l, "|") + "}" 151 } 152 153 type Parentheses []Element 154 155 func (e Parentheses) Format(p *color.Palette) string { 156 l := make([]string, 0, len(e)) 157 for _, v := range e { 158 l = append(l, v.Format(p)) 159 } 160 return "(" + strings.Join(l, " ") + ")" 161 } 162 163 type PlainGroup []Element 164 165 func (e PlainGroup) Format(p *color.Palette) string { 166 l := make([]string, 0, len(e)) 167 for _, v := range e { 168 l = append(l, v.Format(p)) 169 } 170 return strings.Join(l, " ") 171 } 172 173 type ConnectedGroup []Element 174 175 func (e ConnectedGroup) Format(p *color.Palette) string { 176 l := make([]string, 0, len(e)) 177 for _, v := range e { 178 l = append(l, v.Format(p)) 179 } 180 return strings.Join(l, "") 181 } 182 183 type Function struct { 184 Name string 185 Args []Element 186 AfterArgs []Element 187 CustomArgs []Element 188 Return Element 189 } 190 191 func (e Function) Format(p *color.Palette) string { 192 name := e.Name 193 if p != nil { 194 name = p.Render(KeywordEffect, name) 195 } 196 197 var fnargs string 198 if 0 < len(e.CustomArgs) { 199 args := make([]string, 0, len(e.CustomArgs)) 200 for _, v := range e.CustomArgs { 201 args = append(args, formatArg(v, p)) 202 } 203 fnargs = strings.Join(args, " ") 204 } else { 205 args := make([]string, 0, len(e.Args)) 206 var opstr string 207 var prevOpt string 208 for i, v := range e.Args { 209 if op, ok := v.(Option); ok { 210 if i == 0 { 211 prevOpt = formatArg(v, p) + " " 212 } else { 213 for i := len(op) - 1; i >= 0; i-- { 214 opstr = " [, " + formatArg(op[i], p) + opstr + "]" 215 } 216 } 217 } else { 218 args = append(args, formatArg(v, p)) 219 } 220 } 221 fnargs = prevOpt + strings.Join(args, ", ") + opstr 222 } 223 s := name + "(" + fnargs + ")" 224 225 if e.AfterArgs != nil { 226 afterArgs := make([]string, 0, len(e.AfterArgs)) 227 for _, arg := range e.AfterArgs { 228 afterArgs = append(afterArgs, arg.Format(p)) 229 } 230 s = s + " " + strings.Join(afterArgs, " ") 231 } 232 233 if e.Return != nil { 234 s = s + e.Return.Format(p) 235 } 236 return s 237 } 238 239 func formatArg(arg Element, p *color.Palette) string { 240 s := arg.Format(p) 241 242 t := "" 243 switch arg.(type) { 244 case String: 245 t = "string" 246 case Integer: 247 t = "integer" 248 case Float: 249 t = "float" 250 case Boolean: 251 t = "boolean" 252 case Ternary: 253 t = "ternary" 254 case Datetime: 255 t = "datetime" 256 default: 257 return s 258 } 259 t = "::" + t 260 if p != nil { 261 t = p.Render(TypeEffect, t) 262 } 263 return s + t 264 } 265 266 type ArgWithDefValue struct { 267 Arg Element 268 Default Element 269 } 270 271 func (e ArgWithDefValue) Format(p *color.Palette) string { 272 return formatArg(e.Arg, p) + " " + Keyword("DEFAULT").Format(p) + " " + e.Default.Format(p) 273 } 274 275 type String string 276 277 func (e String) Format(p *color.Palette) string { 278 s := string(e) 279 if p != nil { 280 s = p.Render(ItalicEffect, p.Render(option.StringEffect, s)) 281 } 282 return s 283 } 284 285 type Integer string 286 287 func (e Integer) Format(p *color.Palette) string { 288 s := string(e) 289 if p != nil { 290 s = p.Render(ItalicEffect, p.Render(option.NumberEffect, s)) 291 } 292 return s 293 } 294 295 type Float string 296 297 func (e Float) Format(p *color.Palette) string { 298 s := string(e) 299 if p != nil { 300 s = p.Render(ItalicEffect, p.Render(option.NumberEffect, s)) 301 } 302 return s 303 } 304 305 type Identifier string 306 307 func (e Identifier) Format(p *color.Palette) string { 308 s := string(e) 309 if p != nil { 310 s = p.Render(option.IdentifierEffect, s) 311 } 312 return s 313 } 314 315 type Datetime string 316 317 func (e Datetime) Format(p *color.Palette) string { 318 s := string(e) 319 if p != nil { 320 s = p.Render(ItalicEffect, p.Render(option.DatetimeEffect, s)) 321 } 322 return s 323 } 324 325 type Boolean string 326 327 func (e Boolean) Format(p *color.Palette) string { 328 s := string(e) 329 if p != nil { 330 s = p.Render(ItalicEffect, p.Render(option.BooleanEffect, s)) 331 } 332 return s 333 } 334 335 type Ternary string 336 337 func (e Ternary) Format(p *color.Palette) string { 338 s := string(e) 339 if p != nil { 340 s = p.Render(ItalicEffect, p.Render(option.TernaryEffect, s)) 341 } 342 return s 343 } 344 345 type Null string 346 347 func (e Null) Format(p *color.Palette) string { 348 s := string(e) 349 if p != nil { 350 s = p.Render(ItalicEffect, p.Render(option.NullEffect, s)) 351 } 352 return s 353 } 354 355 type Variable string 356 357 func (e Variable) Format(p *color.Palette) string { 358 s := string(e) 359 if p != nil { 360 s = p.Render(VariableEffect, s) 361 } 362 return s 363 } 364 365 type Flag string 366 367 func (e Flag) Format(p *color.Palette) string { 368 s := string(e) 369 if p != nil { 370 s = p.Render(FlagEffect, s) 371 } 372 return s 373 } 374 375 type Token string 376 377 func (e Token) Format(_ *color.Palette) string { 378 return string(e) 379 } 380 381 type Italic string 382 383 func (e Italic) Format(p *color.Palette) string { 384 s := string(e) 385 if p != nil { 386 s = p.Render(ItalicEffect, s) 387 } 388 return s 389 } 390 391 type Return string 392 393 func (e Return) Format(p *color.Palette) string { 394 s := "return::" + string(e) 395 if p != nil { 396 s = p.Render(TypeEffect, s) 397 } 398 return " " + s 399 }