Detecting the Terminal.app locale (LC_TYPE) from KM

Problem:

What is the best way to detect, from a KM macro, the locale ($LC_CTYPE) setting in a users's Terminal.app /bin/bash settings ?

(not the same as the LC_TYPE value in KM's Execute shell script /bin/sh

Context:

The character count given by the bash wc -m filename in a Keyboard Maestro Execute a shell script action can differ significantly from that given by wc -m in Terminal.app, and this means that scripts which work well in Terminal.app may behave incorrectly in Keyboard Maestro.

This is because the user's default /bin/bash locale (like the path settings in their .bash_profile) are not exported to KM's slightly different /bin/sh shell.

In particular, $LC_CTYPE might have the value "UTF-8" in Terminal.app, but have the value "C" in the KM '/bin/sh', and this will mean that wc -m in Keyboard Maestro simply falls back to the same return value as wc -c – making no allowance for multi-byte characters.


I would like to detect the Terminal.app setting, and export it into the KM /bin/sh context.

Any thoughts on a clean solution ?

PS a simple solution would be to export “UTF-8” in all cases, but I would prefer to reproduce more specific local settings in order to be sure that script behaviour won’t diverge between Terminal.app and KeyBoard Maestro.

The simple fix might look like:

# Ensure that the locale is a UTF-8 setting
if [[ "$LC_CTYPE" != *"UTF-8"* ]]; then
	export LC_CTYPE="UTF-8" 
fi

but this would drop distinctions between cultivars like:

  • en_US.UTF-8
  • gb_US.UTF-8
  • en_FR.UTF-8

etc

UPDATE:

This seems to do it from within an Execute Shell Script action:

#!/bin/bash

LANGSTATE="$(defaults read -g AppleLocale).UTF-8"

if [[ "$LC_CTYPE" != *"UTF-8"* ]]; then
	export LC_ALL="$LANGSTATE" 
fi

The differences in the environment between Execute Shell Script and Terminal are many and varied. Most stem from one of three things:

  • Keyboard Maestro uses /bin/sh, where Terminal uses your shell selection.
  • Keyboard Maestro runs the shell in non-interactive mode, where Terminal runs it in Interactive mode.
  • Keyboard Maestro runs it in the background, whereas Terminal may allow User Interaction.

Running the shell in non-Interactive mode in particular means that usually none of your configuration scripts (.profile, .login, .cshrc etc) will be executed and this can make a very large difference in the resulting environment variables. You can run this scripts manually yourself at the start of your Execute Shell Script action though (with appropriate care in the scripts). And you can start your script with #!/bin/bash to select a shell.

1 Like

Thanks, Peter. That’s very helpful.

Is there a way of getting Execute Shell Script to read and digest the contents of /etc/paths ?

Not by default, but you could write a script that added /etc/paths to the PATH environment variable and then execute that script at the start of any Execute Shell Script action that required it.

Note that new in 7.0, you can set the variable “ENV_PATH” to “/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin” (or whatever) and Keyboard Maestro will set the PATH environment variable to that value when it runs any script. Same for “ENV_Anything”.

1 Like