summaryrefslogtreecommitdiffstats
path: root/js/misc/history.js
blob: 268f13bb87b64e61ff4e95c075e7b29455620e45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported HistoryManager */

const Signals = imports.misc.signals;
const Clutter = imports.gi.Clutter;
const Params = imports.misc.params;

var DEFAULT_LIMIT = 512;

var HistoryManager = class extends Signals.EventEmitter {
    constructor(params) {
        super();

        params = Params.parse(params, {
            gsettingsKey: null,
            limit: DEFAULT_LIMIT,
            entry: null,
        });

        this._key = params.gsettingsKey;
        this._limit = params.limit;

        this._historyIndex = 0;
        if (this._key) {
            this._history = global.settings.get_strv(this._key);
            global.settings.connect(`changed::${this._key}`,
                                    this._historyChanged.bind(this));
        } else {
            this._history = [];
        }

        this._entry = params.entry;

        if (this._entry) {
            this._entry.connect('key-press-event',
                                this._onEntryKeyPress.bind(this));
        }
    }

    _historyChanged() {
        this._history = global.settings.get_strv(this._key);
        this._historyIndex = this._history.length;
    }

    _setPrevItem(text) {
        if (this._historyIndex <= 0)
            return false;

        if (text)
            this._history[this._historyIndex] = text;
        this._historyIndex--;
        this._indexChanged();
        return true;
    }

    _setNextItem(text) {
        if (this._historyIndex >= this._history.length)
            return false;

        if (text)
            this._history[this._historyIndex] = text;
        this._historyIndex++;
        this._indexChanged();
        return true;
    }

    lastItem() {
        if (this._historyIndex !== this._history.length) {
            this._historyIndex = this._history.length;
            this._indexChanged();
        }

        return this._historyIndex ? this._history[this._historyIndex - 1] : null;
    }

    addItem(input) {
        input = input.trim();
        if (input &&
            (this._history.length === 0 ||
             this._history[this._history.length - 1] !== input)) {
            this._history = this._history.filter(entry => entry !== input);
            this._history.push(input);
            this._save();
        }
        this._historyIndex = this._history.length;
        return input; // trimmed
    }

    _onEntryKeyPress(entry, event) {
        let symbol = event.get_key_symbol();
        if (symbol === Clutter.KEY_Up)
            return this._setPrevItem(entry.get_text().trim());
        else if (symbol === Clutter.KEY_Down)
            return this._setNextItem(entry.get_text().trim());

        return Clutter.EVENT_PROPAGATE;
    }

    _indexChanged() {
        let current = this._history[this._historyIndex] || '';
        this.emit('changed', current);

        if (this._entry)
            this._entry.set_text(current);
    }

    _save() {
        if (this._history.length > this._limit)
            this._history.splice(0, this._history.length - this._limit);

        if (this._key)
            global.settings.set_strv(this._key, this._history);
    }
};