All Projects → shiro → map2

shiro / map2

Licence: MIT license
A scripting language that allows complex key remapping on Linux.

Programming Languages

rust
11053 projects
python
139335 projects - #7 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to map2

Keypress Osd
This program is an On-Screen Display or a Heads-Up Display for keys. It displays every key press at a clearly visible text size. It is developed for people with poor eye sight. It is meant to aid desktop computer usage. It is especially useful while chatting or for occasional typing. The user no longer has to squint or zoom in the entire screen to see what s/he writes in small text fields.
Stars: ✭ 131 (+32.32%)
Mutual labels:  keyboard-layout
kbct
Keyboard keycode mapping utility for Linux supporting layered configuration
Stars: ✭ 209 (+111.11%)
Mutual labels:  keyboard-layout
react-material-ui-keyboard
Virtual keyboard for TextField when needed
Stars: ✭ 54 (-45.45%)
Mutual labels:  keyboard-layout
Extra Keyboards For Chrome Os
Extra keyboard layouts and input methods for Chrome OS
Stars: ✭ 140 (+41.41%)
Mutual labels:  keyboard-layout
Links-QA
Сборная солянка полезных ссылок для QA/тестировщика. Ссылки будут постоянно пополняться.
Stars: ✭ 42 (-57.58%)
Mutual labels:  usability
qmk-keymaps
Personal keyboard keymap files for QMK firmware
Stars: ✭ 46 (-53.54%)
Mutual labels:  keyboard-layout
Gnome Cedilla Fix
A fix to make the Gnome "US-International" layouts generate a cedilla c (ç) when the user types '+c.
Stars: ✭ 106 (+7.07%)
Mutual labels:  keyboard-layout
godlike.css
CSS for layout standardization and usability of web applications
Stars: ✭ 12 (-87.88%)
Mutual labels:  usability
Strata
Раскладка клавиатуры для тех, кто любит Markdown и пишет по-русски
Stars: ✭ 70 (-29.29%)
Mutual labels:  keyboard-layout
List-of-Academic-Research-on-Usability-in-FOSS
No description or website provided.
Stars: ✭ 29 (-70.71%)
Mutual labels:  usability
Xkbswitch Macosx
Console keyboard layout switcher for MacOS
Stars: ✭ 144 (+45.45%)
Mutual labels:  keyboard-layout
Keyboard Layout Editor For Blender
Allows you to import keyboard layouts into blender and render them in 3d
Stars: ✭ 224 (+126.26%)
Mutual labels:  keyboard-layout
incubator-flagon-useralejs
Apache Flagon UserALE.js is a comprehensive, thin-client behavioral logging tool
Stars: ✭ 21 (-78.79%)
Mutual labels:  usability
Ergodox Layout
algernon's ErgoDox EZ layout
Stars: ✭ 135 (+36.36%)
Mutual labels:  keyboard-layout
btnx-config
btnx-config is a configuration tool for btnx (Button Extension). It allows the user to send keyboard combinations or execute commands with mouse buttons. btnx-config provides mouse and button detection, and an easy way to configure btnx's behavior. See https://github.com/cdobrich/btnx/ for btnx.
Stars: ✭ 47 (-52.53%)
Mutual labels:  remapping
Norman
Norman keyboard layout - alternative to QWERTY for touch typing in English
Stars: ✭ 112 (+13.13%)
Mutual labels:  keyboard-layout
birman-typography-layouts-for-ubuntu
Типографские раскладки Ильи Бирмана для Ubuntu
Stars: ✭ 73 (-26.26%)
Mutual labels:  keyboard-layout
us-with-german-umlauts
Mac U.S. keyboard layout with German Umlauts
Stars: ✭ 91 (-8.08%)
Mutual labels:  keyboard-layout
windows-programmer-dvorak
A native and customizable approach for installing Programmer Dvorak for Windows.
Stars: ✭ 38 (-61.62%)
Mutual labels:  keyboard-layout
vim-plugin-ruscmd
Vim plugin: support command mode in Russian keyboard layout
Stars: ✭ 60 (-39.39%)
Mutual labels:  keyboard-layout

Map2

License: MIT

A scripting language that allows complex key remapping on Linux, written in Rust.

All of the functionality related to interacting with graphical elements such as getting the active window information is currently only supported on X11. Wayland support is planned but probably won't be added for some time.

For details check the documentation.

The next major release of map2 is currently in preview on the python branch.
There's almost no documentation yet, the API will likely change and things might break, but if you want to test out the future release and provide feedback you can check it out. The current version of map2 will continue to exist in another repo but won't receive any new features.

Examples

Map2 is a very flexible scripting language that can utilize logic control statements, arithmetic and provides lots of useful built-in functions.

// change the 'a' key to 'b'
a::b;

// map the 'c' key to a code block
c::{
  // output text to standard output
  print("hello world");
  
  // type the text using the virtual keyboard
  send("some text{enter}");
};

// define variables and lambda functions
let sum = |argument1, argument2|{
  return argument1 + argument2;
};

let my_sum = sum(1, 2);
print("the sum of 1 and 2 is: " + my_sum);

// do something when the active window changes
on_window_change(||{
  if(active_window_class() == "firefox"){
    print("firefox is now the active window");
    
    // map 'F1' to ctrl+'t' (open new browser tab)
    f1::^t;
  }else{
    print("firefox is not the active window");
    
    // map 'F1' back
    f1::f1;
  }
});

For more examples check the examples directory.

Getting started

tldr:

  • find the input device file descriptors you want to grab
  • write them into a file (i.e. devices.list)
  • write a script file for remapping the keys
  • run $ map2 -d devices.list script_name.m2

In order to execute a script simply pass it as an argument to the map2 command provided by this package.

$ map2 script-name.m2

By default a script is able to output events though a virtual output device, but in order for a script to intercept input events from physical devices it is necessary to define which devices should be grabbed (all events will pass through the script).

To describe which devices should be grabbed it is necessary to provide a list of file descriptor paths, regular expressions are also supported.

For example, in order to grab a keyboard and Logitech mouse, one might specify the device list as such:

devices.list:

/dev/input/by-id/usb-Logitech_G700s.*-event-kbd
/dev/input/by-path/pci-0000:03:00.0-usb-0:9:1.0-event-kbd

In order to find out which file descriptor corresponds to which physical device one should examine /dev/input/by-id/ and /dev/input/by-path/. After defining the device list we can test it using a short script.

example.m2:

// maps 'a' to 'b'
a::b;

And finally execute the script which should successfully remap the keys.

$ map2 -d devices.list example.m2

Each device can only be grabbed once. Attempting to run several scripts that attempt to grab the same device simultaneously will produce warnings and the device will not be grabbed.

Install

Arch Linux

Install stable version:

$ yay -S map2

Install latest version:

$ yay -S map2-git

Build local package from cloned source:

$ makepkg -si

Other distributions

Install precompiled binary:

  • download the latest release from the releases page
  • unpack the archive
  • copy the files to the respective folders

if there's an error with system libraries being too old, try building from source instead.

Build local package from cloned source:

  • $ cargo build --release
  • copy the compiled binary somewhere in your PATH (i.e. $ cp target/release/map2 /usr/bin)

Documentation

Mappings

Basic mappings simply map one key to a different one.

a::b; // when 'a' is pressed, 'b' will be pressed instead

Under the hood the above expression is a shorthand for the following code:

{a down}::{b down};
{a repeat}::{b repeat};
{a up}::{b up};

Keys can also be remapped to key sequences, meaning that pressing the key will result in the key sequence being typed.

a::"hello world"; // maps a to "hello world"

Also see Key sequences.

Complex mappings can be used by putting a code block on the right side of the mapping expression.

a::{
  sleep(200);
  print("hi");
  send("b");
};

Modifier flags

Modifier flags can be added to key mappings in order to press down the key with the given modifier. Multiple flags can be used at once.
The following modifier flags can be used:

  • ^ - control
  • + - shift
  • ! - alt
  • # - meta

Flags can be used on both sides of a mapping expression:

!a::b; // maps 'alt+a' to 'b'
a::+b; // maps 'a' to 'shift+b'
#!^a::+b; // maps 'meta+alt+ctrl+a' to 'shift+b'

Key symbols

To descript keys in key mappings and sequences it is possible to either use literal key symbols (such as 'a') or any valid input event as defined in input-event-codes.h (such as 'KEY_A'). In the case of special keys such as 'left mouse button', input events need to be used (i.e. BTN_MOUSE).

Non-US keyboard layouts: Alternative keys that require modifiers (such as '@', '%', etc.) probably won't work and get mapped to different keys. To fix this use the modifier flags and the original key instead. (i.e. on the US layout the '@' symbol requires pressing shift+'2', meaning that +2 should be used in simple mappings and {shift down}2{shift up} should be used in key sequences.)

Variables

Variables can be initialized using the let keyword. Assigning a value to a non-existent variable produces an error.

let foo = 33;

Variables are dynamically typed, meaning the their type can change at runtime.

let foo = 33;
foo = "hello";

Control statements

The flow of execution can be controlled using control statements.

If statement

If statements can check whether a certain condition is satisfied and execute code conditionally.

let a = 3;

if (a == 1){
  print("a is 1");
}else if (a == 3){
  print("a is 3");
}else{
  print("a is not 1 or 3");
}

For loop

For loops are useful when a code block should be run several times.

for(let i=0; i<10; i = i+1){
  print(i);
}

Key sequences

Key sequences represent multiple keys with a specific ordering. They can be used on the right side of a mapping expression in order to type the sequence when a key is pressed.

a::"hello world";

Complex keys are also permitted.

a::"hello{enter}world{shift down}1{shift up}";

Functions

All functions are either built-in functions provided by the runtime itself or user defined functions.

List of built-in functions

print(value)

Print the value to the standard output.

print(33);

print("hello");

print(||{});

send(key_sequence)

Outputs the key sequence to the virtual keyboard. This is especially useful for sending dynamic values that are computed at runtime.

let name = "bob";
send("hello " + name);

send_modifier(key_sequence)

Outputs a single modifier to the virtual keyboard and treats the key as being pysically pressed down. This allows binding modifiers to other keys and use them to trigger other mappings in the same way as with the original modifier key. Using send instead will result in the key not triggering other mappings that use the modifier.

// map 'a' to 'shift' and add custom behaviour
{a down}::{
  send_modifier("{shift down}");
  // some custom logic
};
{a up}::{ send_modifier("{shift up}"); };

// pressing 'a' (now became 'shift') and 'b' will trigger this
+b::c;

map_key(trigger, callback)

Maps a key to a callback at runtime, meaning expressions can be used as parameters. This is useful when the trigger key or callback need to be dynamically evaluated.

map_key("a", ||{
  send("b");
});

sleep(duration)

Pauses the execution for a certain duration. This does not block other mappings and tasks.

sleep(1000); // sleep for 1 second

on_window_change(callback)

Registers a callback that is called whenever the active window changes.

on_window_change(||{
  print("hello");
});

active_window_class()

Gets the class name of the currently active window or Void.

if(active_window_class() == "firefox"){
  print("firefox!");
}

number_to_char(number: Number)

Converts a number to the corresponding character.

let char = num_to_char(97);
print(char); // output: 'a'

char_to_number(char: String)

Converts a character to the corresponding number.

let number = char_to_number("a");
print(number); // output: '97'

exit(exit_code?: Number)

Terminates the application with the specified exit code. If no exit code is provided it defaults to '0'.

exit(); // exits the application and indicates success
exit(1); // exits the application and indicates an error

execute(command: String, ...arguments: String[]): String | Void

Executes the given command with the provided arguments.
The standard output of the command is returned as a string if the command succeeds. If the command fails, Void is returned.

let message = execute("echo", "hello", "world");
let now = execute("date");

Comments

Code inside of comments is not evaluated and will be ignored. There exist two types of comments: line comments and in-line comments.

// this is a line comment
print(/* this is an in-line comment */ "hello");

Feature roadmap

  • more built-ins
  • escaped characters in strings and key sequences
  • update documentation and refactor code
  • better tests to avoid regressions
  • pre-packaged binaries for various distros
  • mouse events
  • Wayland support (someday)

Contributing

If you want to report bugs, add suggestions or help out with development please check the issues page and open an issue if it doesn't exist yet.

License

MIT

Authors

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].