Made quick chars use an index
This commit is contained in:
parent
d01bb415a4
commit
1161888660
50
main.go
50
main.go
@ -85,12 +85,12 @@ func main() {
|
|||||||
|
|
||||||
menuBar = ui.NewMenuBar(&theme)
|
menuBar = ui.NewMenuBar(&theme)
|
||||||
|
|
||||||
fileMenu := ui.NewMenu("_File", &theme)
|
fileMenu := ui.NewMenu("File", 0, &theme)
|
||||||
|
|
||||||
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_New File", Shortcut: "Ctrl+N", Callback: func() {
|
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New File", Shortcut: "Ctrl+N", Callback: func() {
|
||||||
textEdit := ui.NewTextEdit(&s, "", []byte{}, &theme) // No file path, no contents
|
textEdit := ui.NewTextEdit(&s, "", []byte{}, &theme) // No file path, no contents
|
||||||
tabContainer.AddTab("noname", textEdit)
|
tabContainer.AddTab("noname", textEdit)
|
||||||
}}, &ui.ItemEntry{Name: "_Open...", Shortcut: "Ctrl+O", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Open...", Shortcut: "Ctrl+O", Callback: func() {
|
||||||
callback := func(filePaths []string) {
|
callback := func(filePaths []string) {
|
||||||
for _, path := range filePaths {
|
for _, path := range filePaths {
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
@ -124,7 +124,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
changeFocus(dialog)
|
changeFocus(dialog)
|
||||||
}}, &ui.ItemEntry{Name: "_Save", Shortcut: "Ctrl+S", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Save", Shortcut: "Ctrl+S", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -144,7 +144,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
}}, &ui.ItemEntry{Name: "Save _As...", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Save As...", QuickChar: 5, Callback: func() {
|
||||||
// TODO: implement a "Save as" dialog system, and show that when trying to save noname files
|
// TODO: implement a "Save as" dialog system, and show that when trying to save noname files
|
||||||
callback := func(filePaths []string) {
|
callback := func(filePaths []string) {
|
||||||
dialog = nil // Hide the file selector
|
dialog = nil // Hide the file selector
|
||||||
@ -163,7 +163,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
changeFocus(dialog)
|
changeFocus(dialog)
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "_Close", Shortcut: "Ctrl+Q", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Close", Shortcut: "Ctrl+Q", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tabContainer.RemoveTab(tabContainer.GetSelectedTabIdx())
|
tabContainer.RemoveTab(tabContainer.GetSelectedTabIdx())
|
||||||
} else { // No tabs open; close the editor
|
} else { // No tabs open; close the editor
|
||||||
@ -172,35 +172,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
}}})
|
}}})
|
||||||
|
|
||||||
panelMenu := ui.NewMenu("_Panel", &theme)
|
panelMenu := ui.NewMenu("Panel", 0, &theme)
|
||||||
|
|
||||||
panelMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Focus Up", Shortcut: "Alt+Up", Callback: func() {
|
panelMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Focus Up", QuickChar: -1, Shortcut: "Alt+Up", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Focus Down", Shortcut: "Alt+Down", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Focus Down", QuickChar: -1, Shortcut: "Alt+Down", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Focus Left", Shortcut: "Alt+Left", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Focus Left", QuickChar: -1, Shortcut: "Alt+Left", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Focus Right", Shortcut: "Alt+Right", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Focus Right", QuickChar: -1, Shortcut: "Alt+Right", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Split _Top", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Split Top", QuickChar: 6, Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Split _Bottom", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Split Bottom", QuickChar: 6, Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Split _Left", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Split Left", QuickChar: 6, Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Split _Right", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Split Right", QuickChar: 6, Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "_Move", Shortcut: "Ctrl+M", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Move", Shortcut: "Ctrl+M", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "_Resize", Shortcut: "Ctrl+R", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Resize", Shortcut: "Ctrl+R", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "_Float", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Float", Callback: func() {
|
||||||
|
|
||||||
}}})
|
}}})
|
||||||
|
|
||||||
editMenu := ui.NewMenu("_Edit", &theme)
|
editMenu := ui.NewMenu("Edit", 0, &theme)
|
||||||
|
|
||||||
editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "_Cut", Shortcut: "Ctrl+X", Callback: func() {
|
editMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Cut", Shortcut: "Ctrl+X", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -212,7 +212,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
}}, &ui.ItemEntry{Name: "_Copy", Shortcut: "Ctrl+C", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Copy", Shortcut: "Ctrl+C", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -222,7 +222,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
}}, &ui.ItemEntry{Name: "_Paste", Shortcut: "Ctrl+V", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Paste", Shortcut: "Ctrl+V", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
@ -235,13 +235,13 @@ func main() {
|
|||||||
|
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Select _All", Shortcut: "Ctrl+A", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Select All", QuickChar: 7, Shortcut: "Ctrl+A", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Select _Line", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Select Line", QuickChar: 7, Callback: func() {
|
||||||
|
|
||||||
}}})
|
}}})
|
||||||
|
|
||||||
searchMenu := ui.NewMenu("_Search", &theme)
|
searchMenu := ui.NewMenu("Search", 0, &theme)
|
||||||
|
|
||||||
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||||
s.Beep()
|
s.Beep()
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import "github.com/gdamore/tcell/v2"
|
import (
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
)
|
||||||
|
|
||||||
// DrawRect renders a filled box at `x` and `y`, of size `width` and `height`.
|
// DrawRect renders a filled box at `x` and `y`, of size `width` and `height`.
|
||||||
// Will not call `Show()`.
|
// Will not call `Show()`.
|
||||||
@ -21,25 +25,26 @@ func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
|
// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
|
||||||
// quick char (any rune after an underscore) with an underline. Returned is the number of
|
// quick char (the rune at `quickCharIdx`) with an underline. Returned is the number of
|
||||||
// columns that were drawn to the screen. This is useful to know the length of the string
|
// columns that were drawn to the screen.
|
||||||
// drawn, minus the underscore.
|
func DrawQuickCharStr(s tcell.Screen, x, y int, str string, quickCharIdx int, style tcell.Style) int {
|
||||||
func DrawQuickCharStr(s tcell.Screen, x, y int, str string, style tcell.Style) int {
|
var col int
|
||||||
runes := []rune(str)
|
var runeIdx int
|
||||||
col := 0
|
|
||||||
for i := 0; i < len(runes); i++ {
|
bytes := []byte(str)
|
||||||
r := runes[i]
|
for i := 0; i < len(bytes); runeIdx++ { // i is a byte index
|
||||||
if r == '_' && i+1 < len(runes) {
|
r, size := utf8.DecodeRune(bytes[i:])
|
||||||
i++
|
|
||||||
sty := style.Underline(true)
|
sty := style
|
||||||
|
if runeIdx == quickCharIdx {
|
||||||
s.SetContent(x+col, y, runes[i], nil, sty)
|
sty = style.Underline(true)
|
||||||
} else {
|
|
||||||
s.SetContent(x+col, y, r, nil, style)
|
|
||||||
}
|
}
|
||||||
|
s.SetContent(x+col, y, r, nil, sty)
|
||||||
|
|
||||||
|
i += size
|
||||||
col++
|
col++
|
||||||
}
|
}
|
||||||
return col
|
return col // TODO: use mattn/runewidth
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectOutline draws only the outline of a rectangle, using `ul`, `ur`, `bl`, and `br`
|
// DrawRectOutline draws only the outline of a rectangle, using `ul`, `ur`, `bl`, and `br`
|
||||||
|
50
ui/menu.go
50
ui/menu.go
@ -11,6 +11,8 @@ import (
|
|||||||
// Item is an interface implemented by ItemEntry and ItemMenu to be listed in Menus.
|
// Item is an interface implemented by ItemEntry and ItemMenu to be listed in Menus.
|
||||||
type Item interface {
|
type Item interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
|
// Returns a character/rune index of the name of the item.
|
||||||
|
GetQuickCharIdx() int
|
||||||
// A Shortcut is a string of the modifiers+key name of the action that must be pressed
|
// A Shortcut is a string of the modifiers+key name of the action that must be pressed
|
||||||
// to trigger the shortcut. For example: "Ctrl+Alt+X". The order of the modifiers is
|
// to trigger the shortcut. For example: "Ctrl+Alt+X". The order of the modifiers is
|
||||||
// very important. Letters are case-sensitive. See the KeyEvent.Name() function of tcell
|
// very important. Letters are case-sensitive. See the KeyEvent.Name() function of tcell
|
||||||
@ -27,15 +29,20 @@ func (i *ItemSeparator) GetName() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *ItemSeparator) GetQuickCharIdx() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (i *ItemSeparator) GetShortcut() string {
|
func (i *ItemSeparator) GetShortcut() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// ItemEntry is a listing in a Menu with a name and callback.
|
// ItemEntry is a listing in a Menu with a name and callback.
|
||||||
type ItemEntry struct {
|
type ItemEntry struct {
|
||||||
Name string
|
Name string
|
||||||
Shortcut string
|
QuickChar int // Character/rune index of Name
|
||||||
Callback func()
|
Shortcut string
|
||||||
|
Callback func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetName returns the name of the ItemEntry.
|
// GetName returns the name of the ItemEntry.
|
||||||
@ -43,6 +50,10 @@ func (i *ItemEntry) GetName() string {
|
|||||||
return i.Name
|
return i.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *ItemEntry) GetQuickCharIdx() int {
|
||||||
|
return i.QuickChar
|
||||||
|
}
|
||||||
|
|
||||||
func (i *ItemEntry) GetShortcut() string {
|
func (i *ItemEntry) GetShortcut() string {
|
||||||
return i.Shortcut
|
return i.Shortcut
|
||||||
}
|
}
|
||||||
@ -52,6 +63,10 @@ func (m *Menu) GetName() string {
|
|||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Menu) GetQuickCharIdx() int {
|
||||||
|
return m.QuickChar
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Menu) GetShortcut() string {
|
func (m *Menu) GetShortcut() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -143,16 +158,15 @@ func (b *MenuBar) Draw(s tcell.Screen) {
|
|||||||
DrawRect(s, b.x, b.y, b.width, 1, ' ', normalStyle)
|
DrawRect(s, b.x, b.y, b.width, 1, ' ', normalStyle)
|
||||||
col := b.x + 1
|
col := b.x + 1
|
||||||
for i, item := range b.menus {
|
for i, item := range b.menus {
|
||||||
str := fmt.Sprintf(" %s ", item.Name) // Surround the name in spaces
|
|
||||||
|
|
||||||
sty := normalStyle
|
sty := normalStyle
|
||||||
if b.focused && b.selected == i {
|
if b.focused && b.selected == i {
|
||||||
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use special style for selected item
|
sty = b.Theme.GetOrDefault("MenuBarSelected") // Use special style for selected item
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawQuickCharStr(s, col, b.y, str, sty)
|
str := fmt.Sprintf(" %s ", item.Name)
|
||||||
|
cols := DrawQuickCharStr(s, col, b.y, str, item.QuickChar+1, sty)
|
||||||
|
|
||||||
col += len(str)
|
col += cols
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.menusVisible {
|
if b.menusVisible {
|
||||||
@ -245,8 +259,8 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
|||||||
case tcell.KeyRune: // Search for the matching quick char in menu names
|
case tcell.KeyRune: // Search for the matching quick char in menu names
|
||||||
if !b.menusVisible { // If the selected Menu is not open/visible
|
if !b.menusVisible { // If the selected Menu is not open/visible
|
||||||
for i, m := range b.menus {
|
for i, m := range b.menus {
|
||||||
found, r := QuickCharInString(m.Name)
|
r := QuickCharInString(m.Name, m.QuickChar)
|
||||||
if found && r == ev.Rune() {
|
if r != 0 && r == ev.Rune() {
|
||||||
b.selected = i // Select menu at i
|
b.selected = i // Select menu at i
|
||||||
b.ActivateMenuUnderCursor() // Show menu
|
b.ActivateMenuUnderCursor() // Show menu
|
||||||
break
|
break
|
||||||
@ -270,8 +284,9 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
|||||||
|
|
||||||
// A Menu contains one or more ItemEntry or ItemMenus.
|
// A Menu contains one or more ItemEntry or ItemMenus.
|
||||||
type Menu struct {
|
type Menu struct {
|
||||||
Name string
|
Name string
|
||||||
Items []Item
|
QuickChar int // Character/rune index of Name
|
||||||
|
Items []Item
|
||||||
|
|
||||||
x, y int
|
x, y int
|
||||||
width, height int // Size may not be settable
|
width, height int // Size may not be settable
|
||||||
@ -282,9 +297,10 @@ type Menu struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Menu. `items` can be `nil`.
|
// New creates a new Menu. `items` can be `nil`.
|
||||||
func NewMenu(name string, theme *Theme) *Menu {
|
func NewMenu(name string, quickChar int, theme *Theme) *Menu {
|
||||||
return &Menu{
|
return &Menu{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
QuickChar: quickChar,
|
||||||
Items: make([]Item, 0, 6),
|
Items: make([]Item, 0, 6),
|
||||||
Theme: theme,
|
Theme: theme,
|
||||||
}
|
}
|
||||||
@ -364,10 +380,10 @@ func (m *Menu) Draw(s tcell.Screen) {
|
|||||||
sty = defaultStyle
|
sty = defaultStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
nameLen := DrawQuickCharStr(s, m.x+1, m.y+1+i, item.GetName(), sty)
|
nameCols := DrawQuickCharStr(s, m.x+1, m.y+1+i, item.GetName(), item.GetQuickCharIdx(), sty)
|
||||||
|
|
||||||
str := strings.Repeat(" ", m.width-2-nameLen) // Fill space after menu names to border
|
str := strings.Repeat(" ", m.width-2-nameCols) // Fill space after menu names to border
|
||||||
DrawStr(s, m.x+1+nameLen, m.y+1+i, str, sty)
|
DrawStr(s, m.x+1+nameCols, m.y+1+i, str, sty)
|
||||||
|
|
||||||
if shortcut := item.GetShortcut(); len(shortcut) > 0 { // If the item has a shortcut...
|
if shortcut := item.GetShortcut(); len(shortcut) > 0 { // If the item has a shortcut...
|
||||||
str := " " + shortcut + " "
|
str := " " + shortcut + " "
|
||||||
@ -470,8 +486,8 @@ func (m *Menu) HandleEvent(event tcell.Event) bool {
|
|||||||
if m.selected == i {
|
if m.selected == i {
|
||||||
continue // Skip the item we're on
|
continue // Skip the item we're on
|
||||||
}
|
}
|
||||||
found, r := QuickCharInString(item.GetName())
|
r := QuickCharInString(item.GetName(), item.GetQuickCharIdx())
|
||||||
if found && r == ev.Rune() {
|
if r != 0 && r == ev.Rune() {
|
||||||
m.selected = i
|
m.selected = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
38
ui/util.go
38
ui/util.go
@ -1,23 +1,29 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import "unicode"
|
import (
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
// QuickCharInString is used for finding the "quick char" in a string. A quick char
|
// QuickCharInString is used for finding the "quick char" in a string. The rune
|
||||||
// suffixes a '_' (underscore). So basically, this function returns any rune after
|
// is always made lowercase. A rune of value zero is returned if the index was
|
||||||
// an underscore. The rune is always made lowercase. The bool returned is whether
|
// less than zero, or greater or equal to, the number of runes in s.
|
||||||
// the rune was found.
|
func QuickCharInString(s string, idx int) rune {
|
||||||
func QuickCharInString(s string) (bool, rune) {
|
if idx < 0 {
|
||||||
runes := []rune(s)
|
return 0
|
||||||
for i, r := range runes {
|
|
||||||
if r == '_' {
|
|
||||||
if i+1 < len(runes) {
|
|
||||||
return true, unicode.ToLower(runes[i+1])
|
|
||||||
} else {
|
|
||||||
return false, ' '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false, ' '
|
|
||||||
|
var runeIdx int
|
||||||
|
|
||||||
|
bytes := []byte(s)
|
||||||
|
for i := 0; i < len(bytes); runeIdx++ { // i is a byte index
|
||||||
|
r, size := utf8.DecodeRune(bytes[i:])
|
||||||
|
if runeIdx == idx {
|
||||||
|
return unicode.ToLower(r)
|
||||||
|
}
|
||||||
|
i += size
|
||||||
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max returns the larger integer.
|
// Max returns the larger integer.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user