Breadcrumbs
Home / Programming / Objective-C / Changing Keyboard Input - Command Line UtilityChanging Keyboard Input - Command Line Utility
If you have the need to programmatically change between languages on the Macintosh, this may be what you are looking for. This code kindly provided by Stefan Klieme
There are two examples. One is an AppleScript example and the other is a command line tool. The command line tool is very useful and easy to use. Example Tool Usage
changeInput //prints current input language
changeInput name //changes input language to name
changeInput toggle name1 name2 //toggles input language between name1 and name2
AppleScript Example
changeInputLanguage("Hebrew")
changeInputLanguage("U.S.")
on changeInputLanguage(L)
tell application "System Events" to tell process "SystemUIServer"
tell (1st menu bar item of menu bar 1 whose value of attribute "AXDescription" is "text input")
return {its value, click, click menu 1's menu item L}
end tell
end tell
end changeInputLanguage
Download a Pre-compiled Version
ChangeInput (3.86 kB)
Instructions for Compiling Yourself Make a folder on your desktop and name it 'input' Create a text file with with the code below and save it in this folder. Name it 'changeInput.m' Be sure to make this file "plain text." Do not use Word or the Rich Text format in TextEdit. It might be wise to download the free TextWranger for this purpose.
Open up the Terminal from /Applications/Utilities/Terminal.app and type the following ALL ON ONE LINE.
name=~/desktop/input/changeInput; gcc "$name".m -o "$name" -l objc
-framework foundation -framework carbon</pre>
What the above code does:
This sets a variable named "name" to a full path -> "/Users/USER_NAME/Desktop/input/changeInput"
This keeps us from typing the path twice in the code.
It ends in a semi-colon to inform the terminal that this is the end of one statement and it can move on to the next statement.
name=~/desktop/input/changeInput;
gcc is the GNU Objective-C compiler we are using to compile this code.
"$name".m is the variable name, which contains the path as shown above with the ".m" appending to the end. This gives us a full path to the "inputChange.m" file in the input folder.
-o is the output option and it specifies the full path to where you want this executable to be created. Here we are using the variable "$name" which is the same name as the ".m" file without the extension.
gcc "$name".m -o "$name"
-l objc is telling the compiler to link this code with the Objective-C runtime library called objc.
-l objc
This is linking each framework included in this code. If we had other frameworks, we would add then in the same way.
-framework foundation -framework carbon
#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>
/*###############################################################################
# #
# changeInput #
# #
# author: Stefan Klieme (based on an idea by Craig Williams) #
# created: 2009-11-05 #
# Changes input language #
# Usage: changeInput prints current input language #
# changeInput name changes input language to name #
# changeInput toggle name1 name2 toggles input language between #
# name1 and name2 #
# #
#################################################################################
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
################################################################################*/
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
TISInputSourceRef current = TISCopyCurrentKeyboardLayoutInputSource();
NSString *currentName = (NSString *)TISGetInputSourceProperty(current, kTISPropertyLocalizedName);
if (argc == 1) {
printf("%s\n", [currentName UTF8String]);
}
else {
NSString *chosenInput, *language1, *language2;
NSArray *inputArray = (NSArray *)TISCreateInputSourceList ( NULL, false);
NSMutableDictionary *availableLanguages = [NSMutableDictionary dictionaryWithCapacity:[inputArray count]];
NSUInteger i;
TISInputSourceRef chosen, languageRef1, languageRef2;
for (i = 0; i < [inputArray count]; ++i) {
[availableLanguages setObject:[inputArray objectAtIndex:i] forKey:TISGetInputSourceProperty((TISInputSourceRef)[inputArray objectAtIndex:i], kTISPropertyLocalizedName)];
}
[inputArray release];
if (argc == 4 && [[args objectAtIndex:1] isEqualTo:@"toggle"]) {
language1 = [args objectAtIndex:2];
language2 = [args objectAtIndex:3];
languageRef1 = (TISInputSourceRef)[availableLanguages objectForKey:language1];
languageRef2 = (TISInputSourceRef)[availableLanguages objectForKey:language2];
if (languageRef1 != nil && languageRef2 != nil) {
chosenInput = ([language1 isEqualTo:currentName]) ? language2 : language1;
chosen = (TISInputSourceRef)[availableLanguages objectForKey:chosenInput];
}
else {
chosenInput = (languageRef1 == nil) ? language1 : language2;
chosen = nil;
}
}
else {
chosenInput = [args objectAtIndex:1];
chosen = (TISInputSourceRef)[availableLanguages objectForKey:chosenInput];
}
if (chosen) {
OSStatus err = TISSelectInputSource (chosen);
if (err)
printf("Could not change input language (error %i)\n", (int)err);
else
printf("Changed input language to %s\n", [chosenInput UTF8String]);
}
else {
printf("%s not available\n", [chosenInput UTF8String]);
}
}
CFRelease(current);
[pool release];
return 0;
}

Comments
Note that for my environment I had to use
TISCopyCurrentK eyboardInputSou rce
instead of
TISCopyCurrentK eyboardLayoutIn putSource
Thanks again!
RSS feed for comments to this post.