Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
137a799399 |
@@ -588,6 +588,14 @@ selected row on a `darker` surface with a `violet` pointer, the filter's hits in
|
||||
`pink`, counts in `green`, questions in `yellow`, errors in `red`, headers and
|
||||
the help line in `dark`.
|
||||
|
||||
Every line at the foot of the screen that wants an answer is that one `yellow`,
|
||||
whatever kind of question it is: the sort legend, both its lines; a yes/no
|
||||
question and its hint; the label in front of a snapshot name or the `YES` of a
|
||||
confirmation. They are different kinds of question and one state — gvm is
|
||||
waiting for a key — and that state is worth learning once, in one place and one
|
||||
tone, rather than being worked out per screen. What is typed in answer stays
|
||||
`white`: it is the operator's, not part of the question.
|
||||
|
||||
Inside the table and the sheet every colour is a role, not a decoration:
|
||||
|
||||
| | |
|
||||
|
||||
@@ -39,20 +39,29 @@ const (
|
||||
// The screen's colours. The comment on each is the name mwxcol's fzf theme gives
|
||||
// the same job, so the two stay in step.
|
||||
var (
|
||||
colRow = cGrey.fg() // fg
|
||||
colRowSel = cWhite.fg() // fg+
|
||||
colSurface = cDarker.bg() // bg+
|
||||
colMatch = cPink.fg() // hl, hl+
|
||||
colPointer = cViolet.fg() // pointer
|
||||
colHeader = cDark.fg() // header, label
|
||||
colInfo = cGreen.fg() // info
|
||||
colQuery = cWhite.fg() // query
|
||||
colErr = cRed.fg() // prompt
|
||||
colWarn = cYellow.fg() // not in the theme: a question, a wait
|
||||
colTitle = attrBold + cWhite.fg() //
|
||||
colLabel = cDark.fg() // the sheet's field names
|
||||
colValue = cWhite.fg() // its values, where nothing better applies
|
||||
colDim = cDark.fg() // disabled
|
||||
colRow = cGrey.fg() // fg
|
||||
colRowSel = cWhite.fg() // fg+
|
||||
colSurface = cDarker.bg() // bg+
|
||||
colMatch = cPink.fg() // hl, hl+
|
||||
colPointer = cViolet.fg() // pointer
|
||||
colHeader = cDark.fg() // header, label
|
||||
colInfo = cGreen.fg() // info
|
||||
colQuery = cWhite.fg() // query
|
||||
colErr = cRed.fg() // prompt
|
||||
colWarn = cYellow.fg() // not in the theme: a question, a wait
|
||||
// colPrompt is every line at the foot of the screen that wants an answer:
|
||||
// the sort legend, a yes/no question, the label in front of something being
|
||||
// typed. One colour for all of them, whatever kind of question it is —
|
||||
// yellow, which is the job mwxcol's own theme gives it — so that "gvm is
|
||||
// waiting for me" is learned once, in one place and one tone, rather than
|
||||
// being a thing to work out per screen. It is the same value as colWarn and
|
||||
// a name of its own, because the two mean different things and only one of
|
||||
// them may ever change.
|
||||
colPrompt = cYellow.fg()
|
||||
colTitle = attrBold + cWhite.fg() //
|
||||
colLabel = cDark.fg() // the sheet's field names
|
||||
colValue = cWhite.fg() // its values, where nothing better applies
|
||||
colDim = cDark.fg() // disabled
|
||||
)
|
||||
|
||||
// What the columns and the sheet's values are coloured by. Every one of these is
|
||||
@@ -1223,7 +1232,7 @@ type prompt struct {
|
||||
// ask puts one question on the status line and waits for a single key. Only "y"
|
||||
// means yes — every other key, Esc and Ctrl-C included, means no.
|
||||
func (b *browser) ask(question string) bool {
|
||||
b.prompt = &prompt{text: question, hint: " y = yes, anything else = no", col: colWarn}
|
||||
b.prompt = &prompt{text: question, hint: " y = yes, anything else = no", col: colPrompt}
|
||||
b.render()
|
||||
k := b.keys.next()
|
||||
b.prompt = nil
|
||||
@@ -1353,12 +1362,13 @@ func (b *browser) renderList() {
|
||||
b.write(sb.String())
|
||||
}
|
||||
|
||||
// editLine draws the input in the status area: the label stays put, the typed
|
||||
// text is the query colour, and a hint says what Enter alone would do.
|
||||
// editLine draws the input in the status area: the label stays put in the colour
|
||||
// every question at the foot of the screen has, and the typed text is the query
|
||||
// colour, because it is the answer and not part of the question.
|
||||
func (b *browser) editLine(sb *strings.Builder, cols int) {
|
||||
segLine(sb, cols,
|
||||
seg{colWarn, b.edit.label},
|
||||
seg{colQuery, string(b.edit.runes)})
|
||||
seg{colPrompt, b.edit.label},
|
||||
seg{colQuery, string(b.edit.runes)}) // the answer is the operator's, and white
|
||||
}
|
||||
|
||||
// parkCursor puts the terminal's own cursor where the typing happens and shows
|
||||
|
||||
@@ -1401,3 +1401,58 @@ func TestEveryScreenDrawsWhatItHasToSay(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Every line at the foot of the screen that wants an answer wears one colour.
|
||||
// The sort legend is a menu, a confirmation is a yes/no question and a snapshot
|
||||
// name is something typed, and they are three different kinds of question — but
|
||||
// "gvm is waiting for me" is one thing, and it is learned once rather than
|
||||
// worked out per screen.
|
||||
func TestEveryQuestionWearsOneColour(t *testing.T) {
|
||||
t.Setenv("COLUMNS", "100")
|
||||
t.Setenv("LINES", "12")
|
||||
|
||||
b := testBrowser("web01", "db01")
|
||||
b.applySort()
|
||||
|
||||
for _, c := range []struct {
|
||||
what string
|
||||
set func()
|
||||
text string
|
||||
lines int // how many of the bottom rows the question occupies
|
||||
}{
|
||||
{"the sort legend", func() {
|
||||
lines := sortLegend()
|
||||
b.prompt = &prompt{text: lines[0], col: colPrompt, more: lines[1]}
|
||||
b.edit = nil
|
||||
}, "sort:", 2},
|
||||
{"a yes/no question", func() {
|
||||
b.prompt = &prompt{text: "power on web01 on v308?", col: colPrompt}
|
||||
b.edit = nil
|
||||
}, "power on web01", 1},
|
||||
{"a name being typed", func() {
|
||||
b.prompt = nil
|
||||
b.edit = &editor{label: "name the snapshot of web01: "}
|
||||
}, "name the snapshot", 1},
|
||||
} {
|
||||
c.set()
|
||||
frame := renderToPipe(t, b, b.renderList)
|
||||
|
||||
if !strings.Contains(frame, colPrompt+c.text) {
|
||||
t.Errorf("%s is not in the colour every question has:\n%s",
|
||||
c.what, frame[max(len(frame)-400, 0):])
|
||||
}
|
||||
// And the second line of a two-line question is in it as well, or the
|
||||
// menu would fade out halfway down.
|
||||
if c.lines == 2 {
|
||||
second := stripEscapes(frame)
|
||||
if !strings.Contains(second, "r·reverse") {
|
||||
t.Errorf("%s lost its second line:\n%s", c.what, second)
|
||||
}
|
||||
if strings.Count(frame, colPrompt) < 2 {
|
||||
t.Errorf("%s does not carry the colour onto its second line", c.what)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.prompt, b.edit = nil, nil
|
||||
}
|
||||
|
||||
@@ -293,11 +293,13 @@ func shortName(name string) string {
|
||||
// choice leaves the order alone: this is the one prompt in the list that is
|
||||
// reached by accident, and doing nothing is the right answer to a stray key.
|
||||
func (b *browser) sortPrompt() {
|
||||
// A menu, not a warning: the colour is the ordinary value colour and there
|
||||
// is no yes/no hint. Where it takes two lines the second one goes in place
|
||||
// of the help line, which says nothing that applies while a menu is up.
|
||||
// The colour every question at the foot of the screen has (colPrompt), and
|
||||
// no yes/no hint: this is a menu and not a question answerable with y, but
|
||||
// it is still gvm waiting for a key, and that is one thing wearing one
|
||||
// colour. Where it takes two lines the second goes in place of the help
|
||||
// line, which says nothing that applies while a menu is up.
|
||||
lines := sortLegend()
|
||||
b.prompt = &prompt{text: lines[0], col: colValue}
|
||||
b.prompt = &prompt{text: lines[0], col: colPrompt}
|
||||
if len(lines) > 1 {
|
||||
b.prompt.more = strings.Join(lines[1:], " ")
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.1.1
|
||||
1.1.2
|
||||
|
||||
Reference in New Issue
Block a user