octalmage / robotjs

Node.js Desktop Automation.

Home Page:http://robotjs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Finalize function naming scheme.

octalmage opened this issue · comments

Need to decide function names.

I'm thinking I'd like to separate each set of functions, so the code would be:

robot.mouse.click();

instead of:

robot.mouseClick();

that would be greate idea...we need to implement the native object factory..

In e55e2d2 I did this in the index.js, are you suggesting we do it natively? I'd be ok with that!

i would suggest javascript functions are better than native.

I agree, seems like it would be easier to maintain.

yup. it would be much easier . I have seen many native node.js libraries the author will write a primitive functional modules in c++/c and he implements his idea in native node.js

I'm thinking for keyboard events I'd like to use, keyboard instead of key.

Like:

robot.keyboard.type("Hello World");
robot.keyboard.press("enter");

instead of:

robot.key.type("Hello World");
robot.key.press("enter");

I think it looks better, and it makes more sense.

👍 for this. Then you can also just include the scope you need, so if you only need to control the mouse, simply just only have that.

Just chiming in as I see would be great to chain, have the commands return the robot object so you can do:

robot
    .keyboard.type('Hello world')
    .mouse.click()
    .window.close()
...
    .<context>.<command>()

Chaining would be pretty nice, actually.

Chaining would be nice, but how would you do error handling?

This might be controversial, but what about a promise-based API?

(First of all, I'm new here. Sorry if I shouldn't just be jumping in. I really like the idea of this project, and have been looking for something to contribute to. I don't know C/C++, but I'm goodish with node).

@RangerMauve Promises would work, but they're hard to chain. The trouble with them is that they return a promise, not robot.

IMHO, the way to do it would be to throw an error. It seems like (especially if this is supposed to replace AutoHotKey), that most of the time there will be a human using in, to deal with an error. If not, try/catch. What jQuery does is they emit error events, which would work. Have a global error handler that prints and quits.

@ariporad In terms of promises, it doesn't necessarily have to be a promise that gets returned outright. It just matters that it's a "thenable". So it could be an object that has all the same methods as robot but also has a .then() method. And whenever one of the methods get called, they get chained with something like return robot.wrapPromise(robot.then(dothething)) internally.

Oh, really? (Promises are weird). That could work then. Although I feel like it'd be rather confusing. (but it's probably the best way to do it).

Well, it's not so much promises as it'd be a fluent interface that relies on promises. One could probably do it without promises, too.

I did some testing and for this code to work:

var robot = require("robotjs");

robot.moveMouse(5, 5);
var old = robot.getMousePos();
robot.moveMouse(50, 50);
var current = robot.getMousePos();
if (current.x !== old.x)
{
    console.log("Success!");
}

There needs to be a 50-100ms delay after the move. After I added the delay to the C++ code this code works without issue.

With the delay in the C code, is there anything wrong with the syntax above? I still want to separate the modules like in my second comment.

#14 and #27 are related.

I don't like to block my app. I'd much rather have something like:

robot.moveMouse({ x: 50, y : 50}, function(err, success) {
  if (err) {
    return;
  }
  var current = robot.getMousePos();
});

@Multiply +1 for callbacks.

Callbacks are nice for activities which take considerable amount of time to complete.
Keyboard and mouse activities should have OPTIONAL callbacks.

Callbacks would be really helpful in scenarios such as taking screenshots and saving them to a file. Those kind of activities will require large amount of time and hence callbacks.

-1 for callbacks. What @RangerMauve suggested is part of the future of callback replacement.

My suggestion is go all in on ES7 async/await so you can instead do the following

var robot = require("robotjs");

await robot.moveMouse(5, 5);
var old = robot.getMousePos();
await robot.moveMouse(50, 50);
var current = robot.getMousePos();
if (current.x !== old.x)
{
    console.log("Success!");
}

Now some real API suggestions is that move could return an object containing the old and/or current position rather than nothing.

var robot = require("robotjs");

await robot.moveMouse(5, 5);
var { old, current } = await robot.moveMouse(50, 50);
if (current.x !== old.x)
{
    console.log("Success!");
}

Additionally, I think going with robot.mouse.x makes a lot of sense. I'd personally would opt for robot.kb.x as I like terseness.

If you don't want to go with es7, then async/await is really just nice sugar on top of waiting for promises to resolve and returning promises from async functions, so if you wrote it in es5 with Promises being returned from the various functions, it'd be forward-compatible for when async/await becomes a thing.

+1 for promises. They naturally suit the "async sequence of actions" paradigm.

+1 for promises.

What about actions where you need to wait some time before doing the next action? Or until some condition is true, like successfully finding an image on the screen.

robot.mouse.move(5, 5);
robot.mouse.click();
// Wait 2 seconds for some animation to complete
robot.mouse.move(50, 50);
robot.mouse.click();
// Wait until image of some button exists on screen
robot.mouse.move(200, 100);
robot.mouse.click();

Is there thoughts on syntax for multiple key presses (e.g. if I needed to do CTRL SHIFT L)?
Or,
If I needed to do a combo between a keypress and a mouse clicks (e.g. CTRL, LEFT-CLICK, (move mouse to x,y) LEFT-CLICK) to simulate multiple selections while holding down a key.

@danprime multiple keypresses are implemented with keyTap. Something like

robot.keyTap("c", "command"); 

Should work. I'll get the documentation updated soon.

Also keyToggle can hold keys down. So you can hold down control while clicking.

I guess we could just have sync and async versions of the functions. I'll at least start working on non-blocking functions using libuv in a branch.

Here are some alternate apis that could address both.

robot.kb.key('c').key('ctrl').hold()
robot.kb.key('c').key('ctrl').press()
robot.kb.keys('c', 'ctrl').hold()
robot.kb.keys(['c', 'ctrl']).hold()
robot.kb.async.key('c').key('ctrl').press()
robot.kb.async().key('c').key('ctrl').press()

I was thinking about creating a typo-corrector in nodejs that observes text typed in every window a few days ago, Your project could serve as a base. It already provides a way to do keypresses, but does it provide a way to listen them?

@steelbrain as of now it doesn't support that feature. Since its a desktop automation tool there wouldn't be much of a use for event listening (that's my honest opinion). But if the feature is requested maybe it can be done. It all depends on @octalmage

The README of the project states that the project started because there was no AutoHotKey for mac, and that's actually the basic usage of AutoHotKey that it transforms brb in to be right back. Really looking forward to have this implemented in here.

@steelbrain Sorry I am yet to try out AHK. Till yesterday was thinking it was only for Mac (or something similar)

@steelbrain this wasn't something I ever planned to implement because I use aText for this on Mac and I don't have a need, but I started work on a separate module. See #55.

I run X11 in Docker containers on my Mac, I'd love to be able to do this:

var Robot = require("robot");

var robotOne = new Robot({xDisplay:"/tmp/x11-1"});
robotOne.keys("a");

var robotTwo = new Robot({xDisplay:"/tmp/x11-1"});
robotTwo.keys("a");

Also, imo, all commands should be promise-based. That's the direction JS is taking going forward (promises are the basis of async/await)

async function myFunc(){
   await robot.keys("a");
}

add detect click of mouse or keyboard function, part of an event listener maybe?

if someone click x button, then move mouse by 300 px