Giter Site home page Giter Site logo

mjolnir's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mjolnir's Issues

Fall back to default config in case of any error

Right now it only falls back to default config when there's no config. It should also fall back in case of any error, via the default error handler. (Our custom error handler function should also have its own secondary fallback in case the default error handler has its own user-error.) This depends on #13.

Improve windows-in-direction algorithm

It's not great right now.

First of all, to make things simpler, it should always calculate the "closest window" in a single direction. To focus windows in other directions, their coordinates should just be rotated around the focused window, to align them to the canonical direction (for some reason, I've been assuming this is "east"). This is the easy part, but it should make the code a lot cleaner and easier to work with.

The harder part is finding which window is actually closer. Right now, we just compare midpoints, completely abandoning a window's width and height, which are actually pretty important. Imagine two windows with nearly the same midpoint, but one is much wider and it should be focused, but in fact the other one is focused instead because its midpoint is a pixel closer. I'm not sure how to solve this. Geometry and math aren't my strong-point.

Add REPL

A simple version has been written. It should be rewritten in terms of api.textgrid and thus depends on #16.

Make api.reload() clear old state (hotkeys, etc)?

  • disable all hotkeys in api.hotkeys.keys and remove them from that table
  • hide the menu
  • stop all pathwatchers (need to record them somewhere first)
  • destroy all textgrids
  • stop all timers (need to record them somewhere first)

Change API hierarchical structure

There should be a global hydra already pre-loaded, with fields window for the window submodule, app for app submodule, etc. So you could do hydra.window.focusedwindow() to get the focused window, without even touching a single require.

Add mouse events to textgrids

It would be really cool to have a "documentation"-specific textgrid at some point, which you could scroll and click around with the mouse, and drag-to-highlight some text so you could copy/paste it. Probably too big of a feature for 1.0 though.

Tap into stdout and log it internally

Probably use the NSFileHandle class methods to replace stdout. Then log it to an array at api.stdout maybe? There's no need for stdin in this app, but stdout is useful for using print and maybe showing errors in the future in a new textgrid that just prints stdout. We should probably also add an event-handler for "received stdout".

Document api.ext and explain it

Make sure the full explanation is accessible from within the doc system! Also explain that third party libs can use the doc system just like the built-in lib does.

api.ext = {}

Add api.ext = {} to the beginning of rawinit.lua. This allows third-party authors to put their extensions into api.ext.whatever without worrying whether it already exists. Document it too.

Status

Making this issue as a placeholder where people can see the status of this project.

Open new webview windows at will

I think it'd be nice to have an API function that lets the user create a new borderless window containing only a webview containing only the raw HTML they pass into it via the API. Then the user could position/hide/show this window at will. This would not be a directly useful feature, but it would enable users to make new features such as window hints.

The way I'm envisioning it, the user would do something like this:

var text = api.readfile("~/.hydra/windowhint.html").format("this will replace the first %s", "this will replace the second %s, etc")
var opts = {x: 0, y: 0, w: 100, h: 100, text: text, ...}
var window = api.openwindow(opts)
// move the window around, etc

We can use -[NSWindow setIgnoresMouseEvents:], and you can pass us the value as part of the options. Maybe it should be called "ignoresMouse". And if you choose to have it not ignore the mouse, there are /some/ tricky things we can do to allow clicks within the window to trigger some function you give it. But that will be trickier.

We can also have options (I think) to disallow the window from becoming the key window, even if it does allow mouse clicks, which will allow it to be more transient.

Probably the simplest way to allow interaction in the web view would be to pass an object whose keys are names (i.e. "action1") that point to function, and you'd pass this in as the "actions" key on opts, and then you can have your JS code be like: onclick="action1()".

As for actually passing data to Hydra from that web view, that sounds probably doable also, but probably annoying with all the conversions and stuff.

Listen to and override {mouse, keyboard, trackpad} events

I just found some code the other day that lets us capture every single key-event and override it.. not just handle it but literally switch it out. The sample code I found makes it so when you press "a" you really press "z", and vice versa. This would be an incredibly cool API to use. It could potentially also obsolete the existing hotkey API, but there may be side-effects or caveats I'm not aware of, so this should probably just be a new separate API for now.

I can't find the original site that I found it on, and the one original source that looks legit seems to be down now, but here's the code (I think):

// alterkeys.c
// http://osxbook.com
//
// Complile using the following command line:
//     gcc -Wall -o alterkeys alterkeys.c -framework ApplicationServices
//
// You need superuser privileges to create the event tap, unless accessibility
// is enabled. To do so, select the "Enable access for assistive devices"
// checkbox in the Universal Access system preference pane.

#include <ApplicationServices/ApplicationServices.h>

// This callback will be invoked every time there is a keystroke.
//
CGEventRef
myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
                  CGEventRef event, void *refcon)
{
    // Paranoid sanity check.
    if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
        return event;

    // The incoming keycode.
    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(
                                                               event, kCGKeyboardEventKeycode);

    // Swap 'a' (keycode=0) and 'z' (keycode=6).
    if (keycode == (CGKeyCode)0)
        keycode = (CGKeyCode)6;
    else if (keycode == (CGKeyCode)6)
        keycode = (CGKeyCode)0;

    // Set the modified keycode field in the event.
    CGEventSetIntegerValueField(
                                event, kCGKeyboardEventKeycode, (int64_t)keycode);

    // We must return the event for it to be useful.
    return event;
}

int
main(void)
{
    CFMachPortRef      eventTap;
    CGEventMask        eventMask;
    CFRunLoopSourceRef runLoopSource;

    // Create an event tap. We are interested in key presses.
    eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
    eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
                                eventMask, myCGEventCallback, NULL);
    if (!eventTap) {
        fprintf(stderr, "failed to create event tap\n");
        exit(1);
    }

    // Create a run loop source.
    runLoopSource = CFMachPortCreateRunLoopSource(
                                                  kCFAllocatorDefault, eventTap, 0);

    // Add to the current run loop.
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                       kCFRunLoopCommonModes);

    // Enable the event tap.
    CGEventTapEnable(eventTap, true);

    // Set it all running.
    CFRunLoopRun();

    // In a real program, one would have arranged for cleaning up.

    exit(0);
}

Make the API consistent

There are a few oddities. The only one I can remember right now is that there are (at least) 2 different ways of registering callbacks. This should probably be standardized.

  • change textgrid callbacks to be regular keys on the textgrid instance rather than functions that take functions
  • figure out the other ones

Add ~/.hydra/ to require path

This way, people can load third party libraries which are essentially immutable, taking advantage of the normal caching behavior of require.

File path

Is there a reason for the config file path to be ~/.hydra/init.lua instead of just ~/.hydra.lua?

Log window should make use of api.log.gotline handler.

If it's hard as it is, then api.log.gotline should be made easier to use. I can't remember what's hard about it, something about object lifespan or something. But I remember thinking earlier "hmm this is gonna be tricky, something about object lifespan or something" and I trust that memory, so I believe it.

Add textgrid API

Basically just import github.com/sdegutis/chaos as an API. Let's call it api.textgrid.

Add timer.once

Used like this:

timer.once(function()
  print("hello world")
end)

It will shell out to dispatch_once. The purpose is to make it easy to have something in your config only run once at the beginning, never after you reload. For example, I just made a pathwatcher that reloads my script, and it grows exponentially at each reload.

There's a name for this thing, but I can't remember it. It's like a nonce or something?

Come up with a better documentation format (and use it)

  • show return values
  • document arg types and return types
  • make the easy stuff easy to read and the hard stuff possible to read without being ugly
  • maybe find a way to make it prettier?
  • use the wiki, don't use github-pages or anything like that

Build documentation into the API itself

api.doc(api.hotkey) should print a documentation string. It would be most helpful in the REPL. (Depends in #12). With no args, it should print the full list of API functions. With a submodule, it should print the sublist of API functions, and perhaps a help string for that specific submodule.

Is any of the API confusing?

Now's the time to make breaking changes. The goal of this first release is to have a stable API so we don't break backwards compatibility (except in trivial ways) in future releases.

  • find new name for api.require to make its intention more self-evident
  • get rid of api.alert.show(), keep api.alert()

Add default "log" textgrid that shows stdout as lines

Should probably be api.openlog.

Also, should we namespace all the stdout stuff? Right now we would have this:

api.stdout = {}
api.maxstdoutlen = 500
api.receivedstdout(str)
api.openlog()

Maybe it should be this instead:

api.log.lines = {}
api.log.maxlines = 500
api.log.gotline(str)
api.log.show()

Make REPL way awesome

  • scroll buffer (M-n and M-p)
  • resizing should correctly adjust the scroll position
  • typing should bring the prompt into view unless it already is
  • pressing up and down should cycle through previous commands to edit and enter them
  • show all returned results, not just first
  • try adding return before statement; fallback to without it if that fails
  • fix tabs (so they're just 2 spaces)
  • basic readline keys should just work
    • transpose-char (C-t)
    • go-back-char (C-b, left)
    • go-forward-char (C-f, right)
    • go-back-word (M-b)
    • go-forward-word (M-f)
    • delete-backward-char (C-h, delete)
    • delete-forward-char (C-d)
    • delete-backward-word (M-delete)
    • delete-forward-word (M-d)
    • kill-forward (C-k)
    • go-beginning-line (C-a)
    • go-end-line (C-e)

Question: What constitutes word-boundaries? We can't just delegate to Lua's regex word-boundary option, since it has none. Answer: for now let's just say "alphanumeric and underscore characters".

Create new API to show self-documentation

It should either be named api.doc(...) or just doc(...). Preferences? I've tried to stay away from globals (besides "api"), but this one might be worth the convenience.

Fix state issues

Fix clear_old_state and the registration functions themselves. Pathwatchers, timers, and textgrids are almost definitely broken, since the length operator is undefined for nonsequential tables, and the unregisterers for these things just pokes holes right in the middle of their respective tables. Terrible! So let's just do the "n" trick that api.notify.registry uses.

Make REPL show stdout inline

It's weird that print(3) doesn't show anything in the REPL itself, only in the log window. Make it show directly in the REPL window too.

Known caveats:

  1. There may be a short delay in capturing stdout which causes it to show up a line too low
  2. There's currently no separation of stdout by source, so ALL stdout will show in REPL
  3. The same line will appear in every log window and every open currently REPL

Add notifications API

It should tap into the same thing that App Store does to show you there's an update. I forget what it's called but I've used it before and it's dead-simple. We could probably get really fancy with making this API really flexible, but I just want a bare-basics one for now that helps us to close #2 (which would be obnoxious if it used an alert to let you know about available updates).

Change api.doc.foo to doc.api.foo

It just feels so backwards right now.

And maybe instead of doc(doc.api.alert) it should just be doc('api.alert'). I dismissed this idea when I first had it because the table idea seemed so cool, but the extra "doc" is redundant, and I refuse to do any more Lua magic. (I've used Ruby for far too long.)

Add timer API

Basically setInterval and setTimeout:

  • doafter(sec, fn)
  • new(fn)
    • start(interval)
    • stop()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.