├── bin
└── xkbswitch
├── xkbswitch.xcodeproj
├── xcuserdata
│ └── alecm.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ ├── xkbswitch.xcscheme
│ │ └── xkbswitch_release.xcscheme
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── README.md
└── xkbswitch
└── main.m
/bin/xkbswitch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myshov/xkbswitch-macosx/HEAD/bin/xkbswitch
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/xcuserdata/alecm.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/xcuserdata/alecm.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | xkbswitch.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | xkbswitch_release.xcscheme
13 |
14 | orderHint
15 | 1
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | B0053B9F1A56B1AE00B2EB8F
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xkbswitch-macosx
2 |
3 | Console keyboard layout switcher for Mac OS X.
4 |
5 | The utility for switching current layout in terminal. You can use it whenever you need
6 | that functionality (for example, for tmux statusline when one is running in fullscreen
7 | terminal). Also you can use it as auxilary utility for [vim-xkbswitch](https://github.com/lyokha/vim-xkbswitch) plugin for
8 | changing the keyboard layout in Mac OS X. The utility should work on all versions
9 | of Mac OS X since 10.6.
10 |
11 | ## Vim integration
12 | For integration with vim-xkbswitch you need to install this [library](https://github.com/myshov/libxkbswitch-macosx) and follow instructions from there.
13 |
14 | ## Installation
15 | For installation put executable file from bin directory in any directory in your $PATH
16 | variable. For example you can put it into `/usr/local/bin` with this command (if source
17 | files of utility in your `Download` directory):
18 | ```shell
19 | $ cp ~/Download/xkbswitch-macosx/bin/xkbswitch /usr/local/bin
20 | ```
21 | ## Usage:
22 | ```
23 | xkbswitch -g|s [-n|e] [value]
24 | where:
25 | -g - get number of layout
26 | -s - set layout by number of list of layouts
27 | -n - code mode (default mode)
28 | -e - string mode (combine it with -g|s to get current layout name or set layouts by its name)
29 | -l - list all available keyboard layouts (their names)
30 | ```
31 |
32 | ## Examples:
33 | #### set layout:
34 | ```shell
35 | $ ./xkbswitch -se RussianWin
36 | $ ./xkbswitch -se US
37 | $ ./xkbswitch -s 2
38 | $ ./xkbswitch -s 1
39 | ```
40 |
41 | #### get current layout:
42 | ```shell
43 | $ ./xkbswitch -ge
44 | $ ./xkbswitch -g
45 | ```
46 |
47 | ## License
48 | The MIT License (MIT)
49 |
50 | Copyright (c) 2015 Alexander Myshov
51 |
52 | Permission is hereby granted, free of charge, to any person obtaining a copy
53 | of this software and associated documentation files (the "Software"), to deal
54 | in the Software without restriction, including without limitation the rights
55 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56 | copies of the Software, and to permit persons to whom the Software is
57 | furnished to do so, subject to the following conditions:
58 |
59 | The above copyright notice and this permission notice shall be included in all
60 | copies or substantial portions of the Software.
61 |
62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
68 | SOFTWARE.
69 |
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/xcuserdata/alecm.xcuserdatad/xcschemes/xkbswitch.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
51 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/xcuserdata/alecm.xcuserdatad/xcschemes/xkbswitch_release.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
51 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/xkbswitch.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B0053BA41A56B1AE00B2EB8F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B0053BA31A56B1AE00B2EB8F /* main.m */; };
11 | B0053BAB1A56B41800B2EB8F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0053BAA1A56B41800B2EB8F /* Carbon.framework */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | B0053B9E1A56B1AE00B2EB8F /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = /usr/share/man/man1/;
19 | dstSubfolderSpec = 0;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 1;
23 | };
24 | /* End PBXCopyFilesBuildPhase section */
25 |
26 | /* Begin PBXFileReference section */
27 | B0053BA01A56B1AE00B2EB8F /* xkbswitch */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xkbswitch; sourceTree = BUILT_PRODUCTS_DIR; };
28 | B0053BA31A56B1AE00B2EB8F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
29 | B0053BAA1A56B41800B2EB8F /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
30 | /* End PBXFileReference section */
31 |
32 | /* Begin PBXFrameworksBuildPhase section */
33 | B0053B9D1A56B1AE00B2EB8F /* Frameworks */ = {
34 | isa = PBXFrameworksBuildPhase;
35 | buildActionMask = 2147483647;
36 | files = (
37 | B0053BAB1A56B41800B2EB8F /* Carbon.framework in Frameworks */,
38 | );
39 | runOnlyForDeploymentPostprocessing = 0;
40 | };
41 | /* End PBXFrameworksBuildPhase section */
42 |
43 | /* Begin PBXGroup section */
44 | B0053B971A56B1AE00B2EB8F = {
45 | isa = PBXGroup;
46 | children = (
47 | B0053BAA1A56B41800B2EB8F /* Carbon.framework */,
48 | B0053BA21A56B1AE00B2EB8F /* xkbswitch */,
49 | B0053BA11A56B1AE00B2EB8F /* Products */,
50 | );
51 | sourceTree = "";
52 | };
53 | B0053BA11A56B1AE00B2EB8F /* Products */ = {
54 | isa = PBXGroup;
55 | children = (
56 | B0053BA01A56B1AE00B2EB8F /* xkbswitch */,
57 | );
58 | name = Products;
59 | sourceTree = "";
60 | };
61 | B0053BA21A56B1AE00B2EB8F /* xkbswitch */ = {
62 | isa = PBXGroup;
63 | children = (
64 | B0053BA31A56B1AE00B2EB8F /* main.m */,
65 | );
66 | path = xkbswitch;
67 | sourceTree = "";
68 | };
69 | /* End PBXGroup section */
70 |
71 | /* Begin PBXNativeTarget section */
72 | B0053B9F1A56B1AE00B2EB8F /* xkbswitch */ = {
73 | isa = PBXNativeTarget;
74 | buildConfigurationList = B0053BA71A56B1AE00B2EB8F /* Build configuration list for PBXNativeTarget "xkbswitch" */;
75 | buildPhases = (
76 | B0053B9C1A56B1AE00B2EB8F /* Sources */,
77 | B0053B9D1A56B1AE00B2EB8F /* Frameworks */,
78 | B0053B9E1A56B1AE00B2EB8F /* CopyFiles */,
79 | );
80 | buildRules = (
81 | );
82 | dependencies = (
83 | );
84 | name = xkbswitch;
85 | productName = xkbswitch;
86 | productReference = B0053BA01A56B1AE00B2EB8F /* xkbswitch */;
87 | productType = "com.apple.product-type.tool";
88 | };
89 | /* End PBXNativeTarget section */
90 |
91 | /* Begin PBXProject section */
92 | B0053B981A56B1AE00B2EB8F /* Project object */ = {
93 | isa = PBXProject;
94 | attributes = {
95 | LastUpgradeCheck = 0610;
96 | ORGANIZATIONNAME = "Alexander Myshov";
97 | TargetAttributes = {
98 | B0053B9F1A56B1AE00B2EB8F = {
99 | CreatedOnToolsVersion = 6.1.1;
100 | };
101 | };
102 | };
103 | buildConfigurationList = B0053B9B1A56B1AE00B2EB8F /* Build configuration list for PBXProject "xkbswitch" */;
104 | compatibilityVersion = "Xcode 3.2";
105 | developmentRegion = English;
106 | hasScannedForEncodings = 0;
107 | knownRegions = (
108 | en,
109 | );
110 | mainGroup = B0053B971A56B1AE00B2EB8F;
111 | productRefGroup = B0053BA11A56B1AE00B2EB8F /* Products */;
112 | projectDirPath = "";
113 | projectRoot = "";
114 | targets = (
115 | B0053B9F1A56B1AE00B2EB8F /* xkbswitch */,
116 | );
117 | };
118 | /* End PBXProject section */
119 |
120 | /* Begin PBXSourcesBuildPhase section */
121 | B0053B9C1A56B1AE00B2EB8F /* Sources */ = {
122 | isa = PBXSourcesBuildPhase;
123 | buildActionMask = 2147483647;
124 | files = (
125 | B0053BA41A56B1AE00B2EB8F /* main.m in Sources */,
126 | );
127 | runOnlyForDeploymentPostprocessing = 0;
128 | };
129 | /* End PBXSourcesBuildPhase section */
130 |
131 | /* Begin XCBuildConfiguration section */
132 | B0053BA51A56B1AE00B2EB8F /* Debug */ = {
133 | isa = XCBuildConfiguration;
134 | buildSettings = {
135 | ALWAYS_SEARCH_USER_PATHS = NO;
136 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
137 | CLANG_CXX_LIBRARY = "libc++";
138 | CLANG_ENABLE_MODULES = YES;
139 | CLANG_ENABLE_OBJC_ARC = YES;
140 | CLANG_WARN_BOOL_CONVERSION = YES;
141 | CLANG_WARN_CONSTANT_CONVERSION = YES;
142 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
143 | CLANG_WARN_EMPTY_BODY = YES;
144 | CLANG_WARN_ENUM_CONVERSION = YES;
145 | CLANG_WARN_INT_CONVERSION = YES;
146 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
147 | CLANG_WARN_UNREACHABLE_CODE = YES;
148 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
149 | COPY_PHASE_STRIP = NO;
150 | ENABLE_STRICT_OBJC_MSGSEND = YES;
151 | GCC_C_LANGUAGE_STANDARD = gnu99;
152 | GCC_DYNAMIC_NO_PIC = NO;
153 | GCC_OPTIMIZATION_LEVEL = 0;
154 | GCC_PREPROCESSOR_DEFINITIONS = (
155 | "DEBUG=1",
156 | "$(inherited)",
157 | );
158 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
159 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
160 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
161 | GCC_WARN_UNDECLARED_SELECTOR = YES;
162 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
163 | GCC_WARN_UNUSED_FUNCTION = YES;
164 | GCC_WARN_UNUSED_VARIABLE = YES;
165 | MACOSX_DEPLOYMENT_TARGET = 10.6;
166 | MTL_ENABLE_DEBUG_INFO = YES;
167 | ONLY_ACTIVE_ARCH = YES;
168 | SDKROOT = macosx;
169 | };
170 | name = Debug;
171 | };
172 | B0053BA61A56B1AE00B2EB8F /* Release */ = {
173 | isa = XCBuildConfiguration;
174 | buildSettings = {
175 | ALWAYS_SEARCH_USER_PATHS = NO;
176 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
177 | CLANG_CXX_LIBRARY = "libc++";
178 | CLANG_ENABLE_MODULES = YES;
179 | CLANG_ENABLE_OBJC_ARC = YES;
180 | CLANG_WARN_BOOL_CONVERSION = YES;
181 | CLANG_WARN_CONSTANT_CONVERSION = YES;
182 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
183 | CLANG_WARN_EMPTY_BODY = YES;
184 | CLANG_WARN_ENUM_CONVERSION = YES;
185 | CLANG_WARN_INT_CONVERSION = YES;
186 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
187 | CLANG_WARN_UNREACHABLE_CODE = YES;
188 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
189 | COPY_PHASE_STRIP = YES;
190 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
191 | ENABLE_NS_ASSERTIONS = NO;
192 | ENABLE_STRICT_OBJC_MSGSEND = YES;
193 | GCC_C_LANGUAGE_STANDARD = gnu99;
194 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
195 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
196 | GCC_WARN_UNDECLARED_SELECTOR = YES;
197 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
198 | GCC_WARN_UNUSED_FUNCTION = YES;
199 | GCC_WARN_UNUSED_VARIABLE = YES;
200 | MACOSX_DEPLOYMENT_TARGET = 10.6;
201 | MTL_ENABLE_DEBUG_INFO = NO;
202 | ONLY_ACTIVE_ARCH = YES;
203 | SDKROOT = macosx;
204 | };
205 | name = Release;
206 | };
207 | B0053BA81A56B1AE00B2EB8F /* Debug */ = {
208 | isa = XCBuildConfiguration;
209 | buildSettings = {
210 | ONLY_ACTIVE_ARCH = YES;
211 | PRODUCT_NAME = "$(TARGET_NAME)";
212 | };
213 | name = Debug;
214 | };
215 | B0053BA91A56B1AE00B2EB8F /* Release */ = {
216 | isa = XCBuildConfiguration;
217 | buildSettings = {
218 | ONLY_ACTIVE_ARCH = YES;
219 | PRODUCT_NAME = "$(TARGET_NAME)";
220 | };
221 | name = Release;
222 | };
223 | /* End XCBuildConfiguration section */
224 |
225 | /* Begin XCConfigurationList section */
226 | B0053B9B1A56B1AE00B2EB8F /* Build configuration list for PBXProject "xkbswitch" */ = {
227 | isa = XCConfigurationList;
228 | buildConfigurations = (
229 | B0053BA51A56B1AE00B2EB8F /* Debug */,
230 | B0053BA61A56B1AE00B2EB8F /* Release */,
231 | );
232 | defaultConfigurationIsVisible = 0;
233 | defaultConfigurationName = Release;
234 | };
235 | B0053BA71A56B1AE00B2EB8F /* Build configuration list for PBXNativeTarget "xkbswitch" */ = {
236 | isa = XCConfigurationList;
237 | buildConfigurations = (
238 | B0053BA81A56B1AE00B2EB8F /* Debug */,
239 | B0053BA91A56B1AE00B2EB8F /* Release */,
240 | );
241 | defaultConfigurationIsVisible = 0;
242 | defaultConfigurationName = Release;
243 | };
244 | /* End XCConfigurationList section */
245 | };
246 | rootObject = B0053B981A56B1AE00B2EB8F /* Project object */;
247 | }
248 |
--------------------------------------------------------------------------------
/xkbswitch/main.m:
--------------------------------------------------------------------------------
1 | // Xkbswitch - console keyboard layout switcher for Mac OS X
2 | //
3 | // The MIT License (MIT)
4 | //
5 | // Copyright (c) 2015 Alexander Myshov
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 |
25 |
26 | #import
27 | #import
28 |
29 |
30 | OSStatus set_by_name(const char** argv, const NSString* prefix) {
31 | NSString *macosx_layout_name;
32 | macosx_layout_name = [prefix stringByAppendingString:[NSString stringWithUTF8String:*argv]];
33 | NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : macosx_layout_name}, FALSE));
34 | TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
35 | OSStatus status = TISSelectInputSource(source);
36 | return status;
37 | }
38 |
39 | int main(int argc, const char * argv[]) {
40 | @autoreleasepool {
41 | NSArray *layouts = [[NSArray alloc] initWithObjects:
42 | @"2SetHangul",
43 | @"390Hangul",
44 | @"3SetHangul",
45 | @"AfghanDari",
46 | @"AfghanPashto",
47 | @"AfghanUzbek",
48 | @"Anjal",
49 | @"Arabic",
50 | @"Arabic-QWERTY",
51 | @"ArabicPC",
52 | @"Armenian-HMQWERTY",
53 | @"Armenian-WesternQWERTY",
54 | @"Australian",
55 | @"Austrian",
56 | @"Azeri",
57 | @"Bangla",
58 | @"Bangla-QWERTY",
59 | @"Belgian",
60 | @"Brazilian",
61 | @"British",
62 | @"British-PC",
63 | @"Bulgarian",
64 | @"Bulgarian-Phonetic",
65 | @"Byelorussian",
66 | @"Canadian",
67 | @"Canadian-CSA",
68 | @"CangjieKeyboard",
69 | @"Cherokee-Nation",
70 | @"Cherokee-QWERTY",
71 | @"Colemak",
72 | @"Croatian",
73 | @"Croatian-PC",
74 | @"Czech",
75 | @"Czech-QWERTY",
76 | @"DVORAK-QWERTYCMD",
77 | @"Danish",
78 | @"Devanagari",
79 | @"Devanagari-QWERTY",
80 | @"Dutch",
81 | @"Dvorak",
82 | @"Dvorak-Left",
83 | @"Dvorak-Right",
84 | @"Estonian",
85 | @"Faroese",
86 | @"Finnish",
87 | @"FinnishExtended",
88 | @"FinnishSami-PC",
89 | @"French",
90 | @"French-numerical",
91 | @"GJCRomaja",
92 | @"Georgian-QWERTY",
93 | @"German",
94 | @"Greek",
95 | @"GreekPolytonic",
96 | @"Gujarati",
97 | @"Gujarati-QWERTY",
98 | @"Gurmukhi",
99 | @"Gurmukhi-QWERTY",
100 | @"HNCRomaja",
101 | @"Hawaiian",
102 | @"Hebrew",
103 | @"Hebrew-PC",
104 | @"Hebrew-QWERTY",
105 | @"Hungarian",
106 | @"Icelandic",
107 | @"Inuktitut-Nunavut",
108 | @"Inuktitut-Nutaaq",
109 | @"Inuktitut-QWERTY",
110 | @"InuttitutNunavik",
111 | @"Irish",
112 | @"IrishExtended",
113 | @"Italian",
114 | @"Italian-Pro",
115 | @"Jawi-QWERTY",
116 | @"KANA",
117 | @"Kannada",
118 | @"Kannada-QWERTY",
119 | @"Kazakh",
120 | @"Khmer",
121 | @"Kurdish-Sorani",
122 | @"Latvian",
123 | @"Lithuanian",
124 | @"Macedonian",
125 | @"Malayalam",
126 | @"Malayalam-QWERTY",
127 | @"Maltese",
128 | @"Maori",
129 | @"Myanmar-QWERTY",
130 | @"Nepali",
131 | @"NorthernSami",
132 | @"Norwegian",
133 | @"NorwegianExtended",
134 | @"NorwegianSami-PC",
135 | @"Oriya",
136 | @"Oriya-QWERTY",
137 | @"Persian",
138 | @"Persian-ISIRI2901",
139 | @"Persian-QWERTY",
140 | @"Polish",
141 | @"PolishPro",
142 | @"Portuguese",
143 | @"Romanian",
144 | @"Romanian-Standard",
145 | @"Russian",
146 | @"Russian-Phonetic",
147 | @"RussianWin",
148 | @"Sami-PC",
149 | @"Serbian",
150 | @"Serbian-Latin",
151 | @"Sinhala",
152 | @"Sinhala-QWERTY",
153 | @"Slovak",
154 | @"Slovak-QWERTY",
155 | @"Slovenian",
156 | @"Spanish",
157 | @"Spanish-ISO",
158 | @"Swedish",
159 | @"Swedish-Pro",
160 | @"SwedishSami-PC",
161 | @"SwissFrench",
162 | @"SwissGerman",
163 | @"Tamil99",
164 | @"Telugu",
165 | @"Telugu-QWERTY",
166 | @"Thai",
167 | @"Thai-PattaChote",
168 | @"Tibetan-QWERTY",
169 | @"Tibetan-Wylie",
170 | @"TibetanOtaniUS",
171 | @"Turkish",
172 | @"Turkish-QWERTY",
173 | @"Turkish-QWERTY-PC",
174 | @"US",
175 | @"USExtended",
176 | @"USInternational-PC",
177 | @"Ukrainian",
178 | @"UnicodeHexInput",
179 | @"Urdu",
180 | @"Uyghur",
181 | @"Vietnamese",
182 | @"Welsh",
183 | @"WubihuaKeyboard",
184 | @"WubixingKeyboard",
185 | @"ZhuyinBopomofo",
186 | @"ZhuyinEten",
187 | nil];
188 |
189 | int c;
190 | int argc_init = argc;
191 | int layout_by_name = 0;
192 | int layout_by_num = 1;
193 | int set_mode = 0;
194 | int get_mode = 0;
195 | // Get enabled keyboard layouts list
196 | CFArrayRef sourceList = (CFArrayRef) TISCreateInputSourceList (NULL, false);
197 |
198 | while (--argc > 0 && (*++argv)[0] == '-') {
199 | while ((c = *++argv[0])) {
200 | switch (c) {
201 | case 's':
202 | set_mode = 1;
203 | break;
204 | case 'g':
205 | get_mode = 1;
206 | break;
207 | case 'n':
208 | layout_by_num = 1;
209 | break;
210 | case 'e':
211 | layout_by_name = 1;
212 | break;
213 | case 'l':
214 | for (int i = 0; i < [layouts count]; i++) {
215 | printf("%s\n", [layouts[i] UTF8String]);
216 | }
217 | break;
218 | default:
219 | printf("xkbswitch: illegal option %c\n", c);
220 | argc = 0;
221 | break;
222 | }
223 | }
224 | }
225 |
226 | // if there was no options show help
227 | if (argc_init == 1) {
228 | printf("Usage: xkbswitch -g|s [-n|e] [value]\n"
229 | "-g get mode\n"
230 | "-s set mode\n"
231 | "-n setting and getting by numeric mode (default)\n"
232 | "-e setting and getting by string mode\n"
233 | "-l list all available layouts (their names)\n");
234 | exit(0);
235 | }
236 |
237 | if (get_mode) {
238 | if (layout_by_name) {
239 | // get current keyboard layout by name
240 | TISInputSourceRef current_source = TISCopyCurrentKeyboardInputSource();
241 | NSString *s = (__bridge NSString *)(TISGetInputSourceProperty(current_source, kTISPropertyInputSourceID));
242 | // get last part of string (without com.apple.keylayout.)
243 | NSUInteger last_dot_num = [s rangeOfString:@"." options:NSBackwardsSearch].location;
244 | NSString *substring = [s substringFromIndex:last_dot_num + 1];
245 | printf("%s", [substring UTF8String]);
246 | } else if (layout_by_num) {
247 | // Get current keyborad layout
248 | TISInputSourceRef currentSource = TISCopyCurrentKeyboardInputSource();
249 | long sourceCount = CFArrayGetCount(sourceList);
250 |
251 | // Search an index of the keyboard layout
252 | for (int i = 0; i < sourceCount; i++)
253 | // If the index is found
254 | if (TISGetInputSourceProperty((TISInputSourceRef) CFArrayGetValueAtIndex(sourceList, i), kTISPropertyLocalizedName) == TISGetInputSourceProperty(currentSource, kTISPropertyLocalizedName)) {
255 | // Print the index
256 | printf("%d", i);
257 |
258 | return 0;
259 | }
260 | }
261 | exit(0);
262 | } else if (set_mode) {
263 | if (layout_by_name) {
264 | OSStatus status = set_by_name(argv, @"com.apple.keylayout.");
265 | if (status != noErr) {
266 | printf("There is no active layout with name in the default prefix \"%s\"\n", *argv);
267 | printf("Trying with the org.unknown.keylayout prefix...\n");
268 | status = set_by_name(argv, @"org.unknown.keylayout.");
269 | if (status != noErr) {
270 | printf("Unable to find an active layout with this name.\n");
271 | }
272 | }
273 | } else if (layout_by_num) {
274 | // Get the first argument. It is index of wanted keyboard layout
275 | int wantedSourceIndex = atoi(*argv);
276 | // Get wanted keyboard layout by index
277 | TISInputSourceRef wantedSource = (TISInputSourceRef) CFArrayGetValueAtIndex(sourceList, wantedSourceIndex);
278 |
279 | // If a keyboard layout with the index does not exist
280 | if (!wantedSource) {
281 | printf("%d", -1);
282 | return 1;
283 | }
284 |
285 | // Switch to wanted keyboard layout
286 | TISSelectInputSource(wantedSource);
287 | }
288 | exit(0);
289 | }
290 |
291 |
292 | }
293 | return 0;
294 | }
295 |
--------------------------------------------------------------------------------