Using shifted function keys in XKB keyboard layout - layout

I'm working on a Khmer keyboard layout and I've run into a problem at the last step of the project.
Khmer has 33 consonant characters, 24 vowel diacritic characters, and another 14 independent vowels characters. On top of this, I have included each character's corresponding International Phonetic Alphabet symbol(s) in my layout at the ALT and SHIFT-ALT levels, so very quickly I'm running out of space.
To alleviate this I was planning to map the 24 vowel diacritics to F1 - F12 and SHIFT F1 - F12 (with the corresponding IPA characters at the ALT and SHIFT/ALT levels) but the SHIFT + FN, ALT + FN and SHIFT/ALT + FN combinations don't register. I've tried the combinations in different text editors, browsers, and the terminal but none work. It seems to be a system wide problem.
I am running Ubuntu 10.04.
Here's the section in my layout that pertains to the FN keys:
key <FK01> { [ 0x10017b6, 0x10017c2, voidsymbol, voidsymbol ] };
key <FK02> { [ 0x10017b7, 0x10017c3, voidsymbol, voidsymbol ] };
key <FK03> { [ 0x10017b8, 0x10017c4, voidsymbol, voidsymbol ] };
key <FK04> { [ 0x10017b9, 0x10017c5, voidsymbol, voidsymbol ] };
key <FK05> { [ 0x10017ba, voidsymbol, voidsymbol, voidsymbol ] };
key <FK06> { [ 0x10017bb, voidsymbol, voidsymbol, voidsymbol ] };
key <FK07> { [ 0x10017bc, voidsymbol, voidsymbol, voidsymbol ] };
key <FK08> { [ 0x10017bd, voidsymbol, voidsymbol, voidsymbol ] };
key <FK09> { [ 0x10017be, voidsymbol, voidsymbol, voidsymbol ] };
key <FK10> { [ 0x10017bf, voidsymbol, voidsymbol, voidsymbol ] };
key <FK11> { [ 0x10017c0, voidsymbol, voidsymbol, voidsymbol ] };
key <FK12> { [ 0x10017c1, voidsymbol, voidsymbol, voidsymbol ] };
As you can see I've only filled out SHIFT F1 - F4 so far, I'll do the rest when or if I get those keys working.
Hopefully some of you can point me in the right direction.

I don't know why the combinations don't register, but as an alternative solution think perhaps of utilising more levels per key, for example using level5 (by including one of the symbol definitions to map some key to the level5 modifier) and defining the key mapping using an eight-level type, such as EIGHT_LEVEL or EIGHT_LEVEL_ALPHABETIC.

My guess is that the default fallback "type" of your FN keys are not including enough keys. E.g, if you have
key <FK01> { type = "TWO_LEVEL", [FirstKey,SecondKey,ThirdKey,...]}
then only FirstKey and SecondKey can be generated. If you have
key <FK01> { type = "CTRL+ALT", [FirstKey,SecondKey,ThirdKey,...]}
then the alt and ctrl and ctrl+alt levels should be recognized, giving you 5 levels, 4 of which you might want to change (you probably don't want to change the ctrl level). Do keep in mind that you probably want to be able to use CTRL+ALT+FN to switch out of X to a terminal in case of emergency, or to at least have some key bound to XF86Switch_VT_1 somewhere in your layout.
You might also want to differentiate between Alt and AltGr, the latter named ISO_Level3_Shift in xkb.
If you want to create and use a ISO_Level5_Switch button somewhere on your keyboard you can use the type "EIGHT_LEVEL" or similar to recognize all combinations of (no modifier),level3 and level5 for a total of 8 levels.
(I have Alt_L bound to my left Alt button, ISO_Level3_Shift bound to my right Alt button, and ISO_Level5_Shift bound to my right "windows" button)
Your keymap will probably need to import some of the key types from elsewhere. In the xkb_types section of your .xkb file, add the line
augment "level5"
to include "LEVEL_EIGHT" and other similar types into your layout.
The files in /usr/share/X11/xkb/types/ should show you which types are available on your system, and which file you need to add to your .xkb file with an augment line to use the type. (They might be in a different directory on your system, since I use Gentoo; type locate level5 in a terminal to find where the directory is for you.) If you feel the need, you can also construct your own type directly into the xkb_types section of your .xkb file, after the augment lines. Look in the files in /usr/share/X11/xkb/types/ to see the syntax of a type definition.
You'll also want to add the line to your xkb_compatibility section, not just the xkb_types section; xkb_types provides the types, xkb_compatibility defines modifier key behavior, so while an augment "level5" in xkb_types will give you access to types like "EIGHT_LEVEL", an augment "level5" in xkb_compatibility will make a key bound to ISO_Level5_Shift actually act as a modifier.
Just to give you an idea, my own xkb_compatibility section looks like this:
xkb_compatibility "complete" {
// "pc" would only set Alt, need "pc98" for NumLock
include "pc98" // Numlock
augment "misc" // Alt,Meta,Super,Hyper ...
augment "ledscroll(group_lock)" // Set scroll lock on group switch
augment "xfree86" // Switch out to terminal
augment "caps" // Simple caps thing
augment "iso9995" // level3,groups
augment "level5" // level5
};
I'm not sure if all .xkb files include these sections or if it's just mine.
IIRC, there's often some GUI way to include level3, level5 and the likes when you set your layout rather than in the layout file itself, if that's more to your liking.
If you want to go deeper, I can recommend something like https://www.charvolant.org/doug/xkb/

Related

Order of keys in package.json exports

I believe I understand the basic functioning of the exports key in package.json files:
// package.json
{
"exports": {
".": {
// used by typescript
"types": "./file_with_type_defs.d.ts",
// used by ESM resolution
"import": "./file_to_import.mjs",
// used by CJS resolution
"require": "./file_to_require.cjs",
// used by ...others?
"default": "./file_one_more.js"
}
}
}
Question: Does the order of the "types", "import", "require", and "default" keys matter? Normally I would think no way, since JSON object keys are unordered. From json.org:
An object is an unordered set of name/value pairs. An object begins with { ...
But Typescript documentation says that "types" must come first:
Entry-point for TypeScript resolution - must occur first!
"types": "./types/index.d.ts"
and the NodeJS documentation says "default" should come last
"default" - the generic fallback that always matches. Can be a CommonJS or ES module file. This condition should always come last.
So... Does the order of the export keys matter? If not, what do the NodeJS and Typescript documentation mean when they talk about "first" and "last"?
Having swapped the order of "types" with other keys, its order seems not to matter.
Webpack, which also uses the export key explains this field as follows:
Notes about ordering
In an object where each key is a condition, order of properties is significant. Conditions are handled in the order they are specified.
Rather than see this as a plain object, consider it being like this if-else case:
let file;
if (platform_supports('types')) {
file = "./file_with_type_defs.d.ts";
} else if (platform_supports('import')) {
file = "./file_to_import.mjs";
} else if (platform_supports('require')) {
file = "./file_to_require.cjs";
} else if (true) { // default
file = "./file_one_more.js";
}
If you were to swap the order, it might be like this:
let file;
if (true) { // default
file = "./file_one_more.js";
} else if (platform_supports('types')) {
file = "./file_with_type_defs.d.ts";
} else if (platform_supports('import')) {
file = "./file_to_import.mjs";
} else if (platform_supports('require')) {
file = "./file_to_require.cjs";
}
Even though Typescript understands .d.ts files it would use file_one_more.js since it matches first.
I have tried swapping the order of "types" with other keys. It seems not to matter.
It might be that Typescript prioritizes the types condition over others. However, I'd stick with what they advise—"must occur first" is not "ought to occur first", after all.
As a side-note, historically JavaScript object keys are unordered / the order is not guaranteed. In practice, browsers did preserve the key order and this behavior was standardized in ES2015: non-integer keys are preserved in insertion order.
The JSON standard doesn't make the same promise, as there are many implementations of JSON decoders in different languages and it the predates ES2015 standard.
JSON objects are "unordered set" as "key do not have a particular order(i.e. never have to be sorted)", not as "do not have an order"
Parsed JS object DOES have an order of keys matching the orger in JSON
Depending on if the code uses for (let k in json) or if (json.types) the behaviour may be different
So by whatever reason it's recommended to order keys in the way some parsers may expect
In your case I'd recommend you to try swapping them, seeing that nothing happens, and swapping them back

Azure maps - change the color of a pin based on data driven styling

I am trying to create a data driven layer style that uses a boolean expression, but I am not sure how to make it work.
I have a Feature shape defined. Notice the property bag has an assigned property.
new atlas.data.Feature(new atlas.data.Point([-122.3802, 47.54384]), {
leaseNo: '928928A',
assigned: true
}),
Then for the SymbolLayer the Feature is assigned to uses a style definition as...
iconOptions: {
image: [
'match',
['get', 'assigned'],
['==', 'true'], 'marker-red',
'marker-darkblue'
]
}
It retrieves the value of the assigned property and returns a marker based on whether the value is true or false.
However, it's not working, so my syntax isn't correct. Can someone help me with the syntax to make this work?
I found a solution using case.
iconOptions: {
image: [
'case',
['get', 'assigned'], 'marker-red',
'marker-darkblue'
]
}

How to read keys into array?

I am trying to read keys from a hiera json file into an array.
The json is as follows:
{
"network::interfaces": {
"eth0": {
"ip": "10.111.22.10"
},
"eth1": {
"ip": "10.111.22.11"
},
"eth2": {
"ip": "10.111.22.12"
}
}
}
In my Puppet code, I am doing this:
$network_interfaces = hiera_array('network::interfaces')
notice($network_interfaces)
Which results in the following:
Notice: Scope(Class[Role::Vagrant]): {eth0 => {ip => 10.111.22.10}, eth2 => {ip => 10.111.22.11}, eth3 => {ip => 10.111.22.12}}
But what I want are just the interfaces: [eth0, eth1, eth2]
Can someone let me know how to do this?
The difference between hiera_array() and plain hiera() has to do with what happens when the requested key (network::interfaces in your case) is present at multiple hierarchy levels. It has very little to do with what form you want the data in, and nothing to do with selecting bits and pieces of data structures. hiera_array() requests an "array-merge" lookup. The more modern lookup() function refers to this as the "unique" merge strategy.
It seems unlikely that an array-merge lookup is in fact what you want. In that case, the easiest thing to do is read the whole hash and extract the keys:
$network_interfaces = keys(hiera('network::interfaces'))
In Puppet 4 you'll need to use the keys() function provided by the puppetlabs/stdlib module. From Puppet 5 on, that function appears in core Puppet.

How to show the find and replace panel with a pre-populated search string?

I know that it is possible to show the Sublime Text "Find and Replace" panel using the show_panel command (either via a keybinding or a plugin), and control which arguments are enabled/disabled.
Example run from Sublime Console panel:
window.run_command('show_panel', { 'panel': 'replace', 'regex': True, 'case_sensitive': False, 'whole_word': False, 'in_selection': False, 'wrap': True, 'highlight': True, 'preserve_case': True })
What I would like to know, is: is there a way to pre-populate the Find What: and Replace With: values?
I found this forum post but it has no reply, and the unofficial documentation is of no help in this case.
I have tried:
'find_what': 'string'
'replace_with': 'string'
'find_history': 'string'
'replace_history': 'string'
'find_history': ['string']
'replace_history': ['string']
'find': 'string'
'replace': 'string'
EDIT: I have also tried:
characters
find_characters
look_for
search_for
find_regex
find_string
search_string
replacement
search_characters
and none of the above makes any difference - the panel is always pre-populated with the previous search and replace values, not what I pass in.
I am aware of the commands slurp_find_string and slurp_replace_string, which will take the current selection and update the Find What / Replace With values respectively, but I would like a way to do it without having to mess around with selections first - I just want to pass the values as arguments directly to the show_panel command.
Does anyone know what parameters/arguments can be used to control this?
You can run an insert command on the window just after you've run the show_panel command.
import sublime_plugin
class ShowPanelPrefilledCommand(sublime_plugin.WindowCommand):
def run(self, interactive=True):
self.window.run_command('show_panel', {
'panel': 'find_in_files',
'where': '<open folders>',
'whole_word': False,
'case_sensitive': False,
'preserve_case': False,
'regex': False,
'use_buffer': False,
'show_context': False,
})
self.window.run_command('insert', {'characters': 'hello'})
if not interactive:
self.window.run_command('find_all', {'close_panel': True})
I wanted to do the same thing for a key binding command that opens a Package Tool and uses the Find Search window. I ended up with something easy to customize and use for any command that just uses another key binding.
After I run my Package Tool, I just use this key binding to insert the text (which is a complicated regex in my case). For me on OSX, it's intuitively remembered as (insert 1) CMD+i, CMD+1
Open Sublime Text / Preferences / Key Bindings
Add this to the User - Default (OS).sublime-keymap
{ "keys": ["super+i", "super+1"], "command": "insert", "args": { "characters": "my-custom-insert-text1" } },
{ "keys": ["super+i", "super+2"], "command": "insert", "args": { "characters": "my-custom-insert-text2" } },
// etc..
This feature was added in Sublime Text build 4123 on 6 December 2021.
The show_panel command for the find and find in files panels can now take "pattern" and "replace_pattern" arguments.

i18next: fallback to [same language + different namespace] instead of [different language + same namespace]

This is about using i18next in a node.js backend.
This is the initialization:
i18next.init({
lng: 'de',
fallbackLng: ['de'],
ns: {
namespaces: ['formal', 'informal'],
defaultNs: 'formal'
},
fallbackToDefaultNS: true,
resStore: {
de: resourcesDE,
en: resourcesEN
}
});
where resourcesDE is an object with structure { formal: { }, informal: { }} and resourcesEN has the same structure but only 'formal', no 'informal' (but I have this problem even if there is 'informal' in resourcesEN).
Now, what I want to have is:
If I request the translation of 'informal:myKey' for English that the search route (== fallback) is:
(en)'informal:myKey' > (en)'myKey' > (de)'informal:myKey' > (de)'myKey'
or
(en)'informal:myKey' > (en)'myKey' > (de)'myKey'
but what actually happens is:
(en)'informal:myKey' > (de)'informal:myKey' > (de)'myKey'
meaning that the language changes before even trying to get a text of the same language from a different (the default) namespace.
How can I achieve this or something along those lines. I've also tried using a context instead of namespaces for these alternatives, but that seemed to behave the same. I'm glad to be proven wrong though.
The solution that worked out for me, in the end:
Instead of namespaces, I use special language flavors: 'de-INFORMAL' and 'en-INFORMAL'. If no label is found under 'en-INFORMAL', the lookup falls back to 'en', first and out of the box. If fallbackLng is set to 'de' it will fallback to that if the label in not found in 'en', either.

Resources