Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding unicode modifications #697

Closed
erickrf opened this issue May 24, 2020 · 12 comments
Closed

Adding unicode modifications #697

erickrf opened this issue May 24, 2020 · 12 comments
Labels

Comments

@erickrf
Copy link

erickrf commented May 24, 2020

Is it possible to modify a key's input to Unicode characters not in the default keyboard? For example, if I want to map left_option + a to 💎

@stale
Copy link

stale bot commented Jul 25, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jul 25, 2020
@erickrf
Copy link
Author

erickrf commented Jul 25, 2020

Anything on this? I haven't figured out if there is an answer.

@stale stale bot removed the stale label Jul 25, 2020
@harmtemolder
Copy link
Collaborator

harmtemolder commented Aug 8, 2020

I don't know of any native way Karabiner could do this, but you could take a look at setting your Input Source to Unicode Hex Input in your Keyboard Preferences. That allows you to type unicode characters by their number while holding option. And then map option+A to that series of numbers.

edit: that works, although you'll have to look up the code for that diamond:

{
  "title": "Print Unicode Characters",
  "maintainers": [
    "harmtemolder"
  ],
  "rules": [{
    "description": "Print Unicode Characters",
    "manipulators": [{
      "type": "basic",
      "from": {
        "key_code": "a"

      },
      "to": [{
          "key_code": "2",
          "modifiers": [
            "option"
          ]
        },
        {
          "key_code": "6",
          "modifiers": [
            "option"
          ]
        },
        {
          "key_code": "2",
          "modifiers": [
            "option"
          ]
        },
        {
          "key_code": "0",
          "modifiers": [
            "option"
          ]
        }
      ]
    }]
  }]
}

Maybe start and end with control+space to switch input methods so you're not in Unicode Hex Input at all times?

@MuhammedZakir
Copy link
Collaborator

MuhammedZakir commented Aug 15, 2020

Alternatively, use a shell script.

Karabiner config:

#!/usr/bin/env ruby

#######################################################################
# You can generate json by executing the following command on Terminal.
#     ruby ./insert_unicode.json.rb
#######################################################################

require 'json'

MODIFIER = 'fn'
KEY_CODES = ('a' .. 'z').to_a.freeze

def rules
  KEY_CODES.map do |key_code|
    {
      desscription: "Insert Character with Key '#{key_code}'",
      manipulators: [{
        type: "basic",
        from: {
          key_code: key_code,
          modifiers: {
            mandatory: [MODIFIER]
          }
        },
        to: [{
          'shell_command': "~/.config/karabiner/assets/complex_modifications/helpers/unicode " + key_code
        }],
        to_delayed_action: {
          to_if_invoked: [
            {
              key_code: "v",
              modifiers: "command"
            },
            {
              "shell_command": "pbpaste -pboard ruler | pbcopy" 
            }
          ]
        },
        parameters: {
          'basic.to_delayed_action_delay_milliseconds': 100
        }
      }]
    }
  end
end

def main
  {
    title: 'Insert Unicode Characters',
    rules: rules
  }
end

puts JSON.pretty_generate(main)

You can restrict this to only execute when caps_lock is enabled by adding 'caps_lock' to 'from.modifiers.mandatory' . Also, if you want to use more than 26 Unicode characters, use conditions - https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/.

Shell script (~/.config/karabiner/assets/complex_modifications/helpers/unicode):

#!/bin/zsh

typeset -A unicode_characters=( a '💎'    b '1F4A0' c '1F4A1'
                                d '1F4A2' e '1F4A3' f '1F4A4'
                                g '1F4A5' h '1F4A6' i '1F4A7'
                                j '....'  k '....'  l '....'
                                m '....'  n '....'  o '....'
                                p '....'  q '....'  r '....'
                                s '....'  t '....'  u '....'
                                v '....'  w '....'  x '....'
                                y '....'  z '....'
                              )


key="$1"

# Copy current clipboard content to 'ruler' pboard
pbpaste | pbcopy -pboard ruler

printf "\\U${unicode_characters[$key]}" | pbcopy

For Bash, see https://stackoverflow.com/questions/602912/how-do-you-echo-a-4-digit-unicode-character-in-bash

@realliyifei
Copy link

@MuhammedZakir Hi, I have a similar problem here, which involves inputting the punctuations that are not on the keyboard.

I modify your script a bit but it doesn't work? Would you mind to help me check the reason? Thanks.

I have two files:

  1. ~/.config/karabiner/assets/complex_modifications/fn_halfwidth.json
{
  "title": "fn半角符号切换  |  Map fn + chinese punctuations to their corresponding halfwidth forms",
  "rules": [
    {
      "description": "Map fn + punctuations to their corresponding halfwidth forms",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "a",
            "modifiers": {
              "mandatory": ["fn"]
            }
          },
          "to": [
            {
              "shell_command": "~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert a"
            }
          ]
        }          
      ]
    }
  ]
}
  1. ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert
#!/bin/zsh

typeset -A halfwidth_chars= (   a '💎'    b '1F4A0' c '1F4A1'
                                d '1F4A2' e '1F4A3' f '1F4A4'
                                g '1F4A5' h '1F4A6' i '1F4A7'
                                j '....'  k '....'  l '....'
                                m '....'  n '....'  o '....'
                                p '....'  q '....'  r '....'
                                s '....'  t '....'  u '....'
                                v '....'  w '....'  x '....'
                                y '....'  z '....'
                            )


key="$1"

printf "\\U${halfwidth_chars[$key]}" | pbcopy

Based on my understanding, when I press fn and a, it should input 💎. But it shows nothing.

@MuhammedZakir
Copy link
Collaborator

MuhammedZakir commented Aug 20, 2020

Based on my understanding, when I press fn and a, it should input 💎. But it shows nothing.

At the end of shell script, printf creates Unicode character and pbcopy copies it to clipboard. It does not paste it at the current cursor location. To do that, I added a delayed action command+v after a short delay (for executing shell script). I guess you forgot to include that part!

to_delayed_action: {
  to_if_invoked: [{
    key_code: "v",
    modifiers: "command"
  }]
},
parameters: {
  'basic.to_delayed_action_delay_milliseconds': 100
}

P.S. Recently, I came across espanso - https://espanso.org/. It maybe more suited to your and OP's needs.

@realliyifei
Copy link

realliyifei commented Aug 20, 2020

I guess you forgot to include that part!

Actually I have tried it but failed. My scripts with this part are shown as below:

  1. ~/.config/karabiner/assets/complex_modifications/fn_halfwidth.json
{
  "title": "fn半角符号切换  |  Map fn + chinese punctuations to their corresponding halfwidth forms",
  "rules": [
    {
      "description": "Map fn + punctuations to their corresponding halfwidth forms",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "a",
            "modifiers": {
              "mandatory": ["fn"]
            }
          },
          "to": [
            {
              "shell_command": "~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert a"
            }
          ],
          "to_delayed_action": {
            "to_if_invoked": [{
              "key_code": "v",
              "modifiers": "command"
            }]
          },
          "parameters": {
            "basic.to_delayed_action_delay_milliseconds": 100
          }
        }          
      ]
    }
  ]
}
  1. ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert
#!/bin/zsh

typeset -A halfwidth_chars= (   a '💎'    b '1F4A0' c '1F4A1'
                                d '1F4A2' e '1F4A3' f '1F4A4'
                                g '1F4A5' h '1F4A6' i '1F4A7'
                                j '....'  k '....'  l '....'
                                m '....'  n '....'  o '....'
                                p '....'  q '....'  r '....'
                                s '....'  t '....'  u '....'
                                v '....'  w '....'  x '....'
                                y '....'  z '....'
                            )


key="$1"

printf "\\U${halfwidth_chars[$key]}" | pbcopy

btw I have tried the shell script itself but fails, too. I'm not familiar with sh so am not sure whether the shell script has a problem.

I tried sh halfwidth_convert a or sh halfwidth_convert 'a' in terminal, and it turns out:

halfwidth_convert: line 3: syntax error near unexpected token `('
halfwidth_convert: line 3: `typeset -A halfwidth_chars= (   a '💎'    b '1F4A0' c '1F4A1''

P.S. Recently, I came across espanso - https://espanso.org/. It maybe more suited to your and OP's needs.

Thanks for your recommendation. I have similar text-replacement stuff such as Mac built-in text replacement and Alfred 4 script. The reason I use karabiner here is that I prefer inputting the punctuations more quickly, and then they can be switched back automatically and immediately. Text replacement is not that efficient in this case.

@MuhammedZakir
Copy link
Collaborator

1. ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert> 
#!/bin/zsh

typeset -A halfwidth_chars= (   a '💎'    b '1F4A0' c '1F4A1'
*--snip--*
  1. No space between = and ( -> typeset -A halfwidth_chars=( a '💎'
  2. Make the script executable -> chmod ug+x ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert. I forgot to mention this! 😬

Thanks for your recommendation. I have similar text-replacement stuff such as Mac built-in text replacement and Alfred 4 script. The reason I use karabiner here is that I prefer inputting the punctuations more quickly, and then they can be switched back automatically and immediately. Text replacement is not that efficient in this case.

I see!

@realliyifei
Copy link

realliyifei commented Aug 22, 2020

I ultimately finish my side-project based on your suggestions. Thanks a lot for your help!

Here is probably the last question:

  1. Make the script executable -> chmod ug+x ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert. I forgot to mention this! 😬

If others download my scripts, do they need to chmod ug+x .../halfwidth_convert in their terminal to activate the shell script file first, too?

Edit: ok, just figure out that it doesn't work as well as I thought 😂. This mechanism copy the character to the clipboard so it's a bit inconvenient when you want to copy something but at the same time use this script. I'm trying to remove the first item in clipboard history (i.e. the copied character) each time or use another method. But anyway, thanks for your inspiration.

@MuhammedZakir
Copy link
Collaborator

MuhammedZakir commented Aug 22, 2020

I ultimately finish my side-project based on your suggestions. Thanks a lot for your help!

Congrats! 😄

Here is probably the last question:

  1. Make the script executable -> chmod ug+x ~/.config/karabiner/assets/complex_modifications/helpers/halfwidth_convert. I forgot to mention this! 😬

If others download my scripts, do they need to chmod ug+x .../halfwidth_convert in their terminal to activate the shell script file first, too?

Permissions can be preserved by downloading zip [1] file.

[1] https://github.com/yif-li/Mac-Karabiner-Chinese-Punctuations-to-Halfwidth-Forms/archive/master.zip

Edit: ok, just figure out that it doesn't work as well as I thought 😂. This mechanism copy the character to the clipboard so it's a bit inconvenient when you want to copy something but at the same time use this script. I'm trying to remove the first item in clipboard history (i.e. the copied character) each time or use another method. But anyway, thanks for your inspiration.

You are welcome! And... this isn't the end! 😉

Put this before printf function in shell script

# Copy current clipboard content to 'ruler' pboard
pbpaste | pbcopy -pboard ruler

and add one more command to delayed action.

to_delayed_action: {
  to_if_invoked: [
    {
      key_code: "v",
      modifiers: "command"
    },
    {
      "shell_command": "pbpaste -pboard ruler | pbcopy" 
    }
  ]
 }

This shell command will copy content inside ruler pboard to general pboard.

Note: There are four pboards -

  1. general - what we normally use
  2. ruler - I don't know what this is used for
  3. find - stores text entered in find(?) fields - command+f.
  4. font - don't know

See pbcopy or pbpaste manpage for more information.

@stale
Copy link

stale bot commented Nov 15, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@edmundseto
Copy link

Thanks to harmtemolder's response above, I was able to get Karabiner-Elements to convert keystrokes to both 4-digit (e.g., math symbols) and 5-digit (e.g., emoji) unicode. I didn't have to resort to running a shell script or copy/paste. It's just a complex modification in karabiner.json.

Here's my code. The json file generally is structured this way...

{
   "global": {
            ... various stuff here...
    },
    "profiles": [
         {
         "complex_modifications": {
              "parameters": {
                      ... various stuff here...
              },
             "rules": [
             {
                    **...stick a complex modifications here...**
             },
             {
                   **...stick another complex modifications here...**
             }
             ],
           "type": "basic"
        }
     ]
     ... remaining stuff here....

And here is an example complex modification that is inserted into the section above for a 4-digit hex unicode (U+03BC for the mu symbol)...

"description": "Math symbol mu.",
"manipulators": [
{
"conditions": [
{
"identifiers": [
{
"description": "2.4G Keyboard Mouse (MOSART Semi.)",
"product_id": 16641,
"vendor_id": 1578
}
],
"type": "device_if"
}
],
"from": {
"key_code": "keypad_1"
},
"to": [
{
"key_code": "spacebar",
"modifiers": [
"left_control"
]
},
{
"key_code": "0",
"modifiers": [
"left_option"
]
},
{
"key_code": "3",
"modifiers": [
"left_option"
]
},
{
"key_code": "b",
"modifiers": [
"left_option"
]
},
{
"key_code": "c",
"modifiers": [
"left_option"
]
},
{
"key_code": "spacebar",
"modifiers": [
"left_control"
]
}
],
“type”: “basic”
}
]

For this to work, it requires that you first go into your Mac System Preferences - Keyboard settings, and add the Unicode Hex input mode.

You'll see that in the code above when keypad_1 is pressed, it converts it first to a Ctrl+Spacebar that will switch to the Unicode Hex input mode, and then it "types" Option(held down)+0 3 b c. Then finishes by typing Ctrl+Spacebar to return to your original Mac keyboard input mode.

Also note, that I've specified "product_id" and "vendor_id" in the code above to limit the modification to a specific device, a numeric keypad that I'm using. You'll want to either remove this part, or change it to refer the the IDs of the device you're using.

I've converted two numeric keypads to a math and an emoji keypads. There's a bit more detail on my website: https://www.edmundseto.com/edmundseto/creating-a-scientific-keypad-for-mac/

Again, thanks to harmtemolder for leading the way for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants