]> git.gir.st - VimFx.git/blob - extension/lib/parse-prefs.coffee
Implement filtering hints by text and related changes
[VimFx.git] / extension / lib / parse-prefs.coffee
1 ###
2 # Copyright Simon Lydell 2015, 2016.
3 #
4 # This file is part of VimFx.
5 #
6 # VimFx is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # VimFx is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
18 ###
19
20 # This file parses string prefs into more easily used data structures.
21
22 defaults = require('./defaults')
23 prefs = require('./prefs')
24 utils = require('./utils')
25
26 MIN_NUM_HINT_CHARS = 2
27
28 parsePref = (pref) ->
29 # Parsed options are not stored in Firefox’s prefs system, and are therefore
30 # always read from the defaults. The only way to override them is via the
31 # config file API.
32 if pref of defaults.parsed_options
33 return defaults.parsed_options[pref]
34
35 value = prefs.get(pref)
36
37 if pref of parsers
38 {parsed, normalized} = parsers[pref](value, defaults.all_options[pref])
39 if normalized? and normalized != value and prefs.has(pref)
40 prefs.set(pref, normalized)
41 return parsed
42
43 return value
44
45 # Splits a whitespace delimited string into an array, with empty elements and
46 # duplicates filtered.
47 parseSpaceDelimitedString = (value) ->
48 parsed = utils.removeDuplicates(value.split(/\s+/)).filter(Boolean)
49 return {parsed, normalized: parsed.join(' ')}
50
51 parseHintChars = (value, defaultValue) ->
52 [leading..., end] = value.trim().split(/\s+/)
53 parsed = if leading.length > 0 then "#{leading.join('')} #{end}" else end
54 parsed = utils.removeDuplicateChars(parsed)
55
56 # Make sure that hint chars contain at least the required amount of chars.
57 diff = MIN_NUM_HINT_CHARS - parsed.length
58 if diff > 0
59 parsed = parsed + defaultValue[...diff]
60
61 unless parsed.includes(' ')
62 numDefaultSecondaryHintChars =
63 defaultValue.length - 1 - defaultValue.indexOf(' ')
64 index = Math.min(parsed.length // 2, numDefaultSecondaryHintChars)
65 parsed = "#{parsed[...-index]} #{parsed[-index..]}"
66
67 return {parsed, normalized: parsed}
68
69 parsePatterns = (value) ->
70 result = parseSpaceDelimitedString(value)
71 # The patterns are case insensitive regexes and must match either in the
72 # beginning or at the end of a string. They do not match in the middle of
73 # words, so "previous" does not match "previously" (`previous\S*` can be used
74 # for that case). Note: `\s` is used instead of `\b` since it works better
75 # with non-English characters.
76 result.parsed = result.parsed.map((pattern) ->
77 patternRegex =
78 try
79 RegExp(pattern).source
80 catch
81 utils.regexEscape(pattern)
82 return ///
83 ^\s* (?:#{patternRegex}) (?:\s|$)
84 |
85 (?:\s|^) (?:#{patternRegex}) \s*$
86 ///i
87 )
88 return result
89
90 parseBlacklist = (value) ->
91 result = parseSpaceDelimitedString(value)
92 result.parsed = result.parsed.map((pattern) ->
93 return ///^#{utils.regexEscape(pattern).replace(/\\\*/g, '.*')}$///i
94 )
95 return result
96
97 parsers = {
98 'hints.chars': parseHintChars
99
100 prev_patterns: parsePatterns
101 next_patterns: parsePatterns
102
103 blacklist: parseBlacklist
104
105 prevent_autofocus_modes: parseSpaceDelimitedString
106
107 adjustable_element_keys: parseSpaceDelimitedString
108 activatable_element_keys: parseSpaceDelimitedString
109
110 pattern_attrs: parseSpaceDelimitedString
111 }
112
113 module.exports = {
114 parsePref
115 parseSpaceDelimitedString
116 }
Imprint / Impressum