hs.eventtap.keyStroke with modifier works only after double press - hammerspoon

I want change copy command from Cmd+c to Ctrl+c.
I have this code:
hs.hotkey.bind({"ctrl"}, "c", function()
hs.eventtap.keyStroke({"cmd"}, "c")
end)
But it works only after two 'c' fast presses with Ctrl button pressed.
It's not a Cmd button problem because Shift+c doesn't work as well.
Haw can I remap Cmd+c combination by Hammerspoon?
My system:
Mac OSX 10.14 Mojave

I know this is an old post but I stumbled across it with the same issue. I think what's happening is that the super key is still in action when the event triggers.
I got around it with a delay to allow the user time to have stopped pressing super:
hs.timer.doAfter(0.3, function()
hs.eventtap.keyStroke({"cmd"}, "`")
end)

I am using hammerspoon to map ctrl-c and ctrl-v to their respective cmd-c and cmd-v equivalents via:
hs.hotkey.bind({"ctrl"}, "c", nil, function()
hs.eventtap.keyStroke({"cmd"}, "c")
end)
hs.hotkey.bind({"ctrl"}, "v", nil, function()
hs.eventtap.keyStroke({"cmd"}, "v")
end)
I can still use the cmd-c and cmd-v keystrokes, but now ctrl-c and ctrl-v also work.

Related

How to distinguish between iTerm2 windows to move / resize only one of them with Hammerspoon?

I have two iTerm2 windows open, and I want to place and resize one via Hammerspoon while leaving the other one as is.
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "Right", function()
local layout = {
{"iTerm2", "/in/my/work/dir", nil, hs.geometry.rect(0.0, 0.40, 0.6, 0.6), nil, nil},
}
hs.layout.apply(layout)
end)
When I run the code as above, nothing happens; Hammerspoon does not find my iTerm2 windows, even though it looks like my window has "/in/my/work/dir" in the title.
When I replace "/in/my/work/dir" with nil, Hammerspoon moves and resizes all my iTerm2 windows. This makes sense, since I just ask for all iTerm2 windows without specifying a title.
When I add debug code to print the list of my iTerm2 windows to the console, I see only one iTerm2 window:
hs.fnutils.each(hs.application.runningApplications(), function(app)
if string.find(app:name(), "iTerm2") then
print("Found " .. app:name() .. " -- " .. app:title())
end
end)
This prints:
Found iTerm2 -- iTerm2
How can I use Hammerspoon to tell my iTerm2 windows apart and move / resize only one of them?
This actually works when you pass the complete title, not only a part of the title. I guess I got misled when the documentation said "string containing a window title". It has to be an exact match.

Position two Terminal windows

I'd like to start two Terminals and put them at specific positions on my screen. I know how to do this with one Terminal but what do I have to do to open a second Terminal and position it next to the first one?
Here is the code for one Terminal:
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "2", function()
hs.application.launchOrFocus("Terminal")
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
f.x = max.x
f.y = max.y
f.w = 960
f.h = 540
win:setFrame(f)
end)
So this potentially gets quite complex, but what I would do is have the hotkey check to see if Terminal is already running. If not, launch it and put it in position 1. If it is already running, focus it, activate the menu item to open a new window, and put it in position 2.

How to write the content of a Flink var to screen in Zeppelin?

I try to run the followin simple commands in Apache Zeppelin.
%flink
var rabbit = env.fromElements(
"ARTHUR: What, behind the rabbit?",
"TIM: It is the rabbit!",
"ARTHUR: You silly sod! You got us all worked up!",
"TIM: Well, that's no ordinary rabbit. That's the most foul, cruel, and bad-tempered rodent you ever set eyes on.",
"ROBIN: You tit! I soiled my armor I was so scared!",
"TIM: Look, that rabbit's got a vicious streak a mile wide, it's a killer!")
var counts = rabbit.flatMap { _.toLowerCase.split("\\W+")}.map{ (_,1)}.groupBy(0).sum(1)
counts.print()
I try to print out the results in the notebook. But unfortunately, I only get the following output.
rabbit: org.apache.flink.api.scala.DataSet[String] = org.apache.flink.api.scala.DataSet#37fdb65c
counts: org.apache.flink.api.scala.AggregateDataSet[(String, Int)] = org.apache.flink.api.scala.AggregateDataSet#1efc7158
res103: org.apache.flink.api.java.operators.DataSink[(String, Int)] = DataSink '<unnamed>' (Print to System.out)
How can I spill the content of counts to the notebook in Zeppelin?
The way to print the result of such computation in Zeppelin is:
%flink
counts.collect().foreach(println(_))
//or one might prefer
//counts.collect foreach println
Output:
(a,3)
(all,1)
(and,1)
(armor,1)
...
The reason for the observed behaviour lies in the interplay between Apache Zeppelin and Apache Flink. Zeppelin captures all standard output of Console. However, Flink also prints output to System.out and that's exactly what's happening when you call counts.print(). The reason why bzz's solution works is that it prints the result using Console.
I opened a JIRA issue [1] and opened a pull request [2] to correct this behaviour so that you can also use counts.print().
[1] https://issues.apache.org/jira/browse/ZEPPELIN-287
[2] https://github.com/apache/incubator-zeppelin/pull/288

UITextField autocapitalizationType UITextAutocapitalizationTypeAllCharacters not working on device

You can set the autocapitalizationType property of a UITextField so all input is in upper case. I find that does work fine on the simulator (when actually tapping the simulator's keypad, not the Mac's keyboard), but not on the device? Everything stays lowercase.
In the UICatalog demo I added to the textFieldNormal method:
textFieldNormal.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
Added a delegate too, to display the actual autocapitalizationType for the UITextField:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog( #"textField.autocapitalizationType=%d", textField.autocapitalizationType );
}
It will properly display 3 (=UITextAutocapitalizationTypeAllCharacters), but anything you tap remains lowercase. What am I missing?
Apparently this is a device general settings issue: Settings -> General -> Keyboard -> Auto-Capitalization must be ON to honour the setting of textField.autocapitalizationType to all upper case, else setting the property is ignored, apparently. If I switch it on everything works as expected.
You could try something like this the the textfield delegate:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (range.length == 0) { // not deleting , but adding a char
textField.text = [textField.text stringByAppendingString:[string uppercaseString]];
return NO;
}
return YES;
}
This works only if you try to insert a symbol at the end of the text.
Should you want to play with the text in the middle you could play with
range.location
and also you will need to play with the cursor positioning as it will go at the end every time...
I hope this helps someone.

WPF - Build a string of pressed keys using KeyDown in ListView

I have a listview with a dozen of rows binded to xml. I'd like to have a possibility to locate and position the cursor to a certain record. For example:
I have a with these ID, Name, Value:
1, Johny, Cash, USA
2, Jean-Michel, Jarre, France
3, Jeanette, , USA
When I would type "Je", the SelectedRow would be positioned to ID 2. When I would type "Jeane", the SelectedRow would be positioned to ID 3. Simply I'd like to have a possibility to search and go to the proper record in the listview. I started building the SearchString and at this point I got stuck:
The one and only possibility in WPF is to use the KeyDown event. Unfortunately, this event return a kind of Key, which I was not able to convert to a string. E.g. when I press "A", SearchString would be "A". When I continue typing "B", SearchString would be "AB" etc. When SelectedItem changes, SearchString will be set to String.Empty. No KeyCode or other useful property/method is available.
And here comes the head rubbing. How can I build the SearchString I need?
When I tried e.Key.ToString(), I got really funny strings - e.g. for 0 on Numpad I get a Key "Numpad0", for "," I get "OemComma" etc. I was trying also the TryParse method to char, for key "3" I get a value of "#" etc, it only works flawlessly just for letter A through Z, for other keys TryParse returns false.
The one and only way how to solve this is to build a translation table with a very long kind of "case e.Key.ToString() of":
"A": SearchString = SearchString + "A";
"System", SearchString = SearchString + " ";
"Numpad0", SearchString = SearchString + "0";
"ArrowUp", do nothing
etc etc etc.
Isn't there a more clever and simple way to do this?? Or I just don't see the trees because of the forest?
Handle PreviewTextInput instead. Reference: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3fcfbe53-2c72-4fec-a997-dc881d1de72a.
EDIT:
Note: The ListView (and ListBox also) internally handles the KeyDown event for some keys to perform selection and navigation. Below are the keys that are internally handled by the ListView:
Key.Space:
Key.Return:
Key.Prior:
Key.Next:
Key.End:
Key.Home:
Key.Left:
Key.Up:
Key.Right:
Key.Down:
Key.Space is of particular interest because when space is pressed on a ListView, the PreviewTextInput event will not get fired. So to complete your solution, you would have to also add a handler for the ListView.PreviewKeyDown event and check if the space key was pressed in order for you to append the correct whitespace text.

Resources