Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "native/inotify_simple"]
path = native/inotify_simple
url = https://github.com/chrisjbillington/inotify_simple
[submodule "native/watchgod"]
path = native/watchgod
url = https://github.com/samuelcolvin/watchgod
18 changes: 14 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
UNAME_S := $(shell uname -s)

ifneq ($(USER),1)
PREFIX ?= /usr/local
MOZILLA_PREFIX ?= /usr
MOZILLA_NATIVE ?= $(MOZILLA_PREFIX)/lib64/mozilla/native-messaging-hosts
ifeq ($(UNAME_S),Darwin)
MOZILLA_NATIVE ?= /Library/Application\ Support/Mozilla/NativeMessagingHosts
else
MOZILLA_PREFIX ?= /usr
MOZILLA_NATIVE ?= $(MOZILLA_PREFIX)/lib64/mozilla/native-messaging-hosts
endif
else
PREFIX ?= $(HOME)/.local
MOZILLA_NATIVE ?= $(HOME)/.mozilla/native-messaging-hosts
ifeq ($(UNAME_S),Darwin)
MOZILLA_NATIVE ?= $(HOME)/Library/Application\ Support/Mozilla/NativeMessagingHosts
else
MOZILLA_NATIVE ?= $(HOME)/.mozilla/native-messaging-hosts
endif
endif

LIBEXEC ?= $(PREFIX)/libexec
Expand All @@ -28,7 +38,7 @@ native-install: native/textern.json
mkdir -p $(DESTDIR)$(MOZILLA_NATIVE)
cp -f native/textern.json $(DESTDIR)$(MOZILLA_NATIVE)
mkdir -p $(DESTDIR)$(LIBEXEC)/textern
cp -rf native/textern.py native/inotify_simple $(DESTDIR)$(LIBEXEC)/textern
cp -rf native/textern.py native/watchgod $(DESTDIR)$(LIBEXEC)/textern

.PHONY: native-uninstall
native-uninstall:
Expand Down
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The add-on is divided into two parts:
- the native application, which handles text editor
launching and monitoring.

The native application currently only supports Linux with
The native application currently supports Linux or macOS with
Python 3.5. Patches to add support for other platforms are
welcome!

Expand Down Expand Up @@ -53,6 +53,18 @@ the native app for the current user, run:
$ make native-install USER=1
```


### Note for macOS

If you installed Python via [homebrew](https://brew.sh/), note
that `/usr/local/bin` is *not* on the PATH by default, so
`textern.py` cannot find it. You either need to adjust your
PATH globally, the exact procedure for which seems to [change with
each macOS version](https://stackoverflow.com/a/32902449/1885340),
or edit the first line of `native/textern.py` to read
`#!/usr/local/bin/python3` and repeating the `make native-install` call.


## Usage

Once both the WebExtension and the native application are
Expand Down Expand Up @@ -118,6 +130,14 @@ set your editor in the preferences to something like
and make sure, that `gnome-terminal-wrapper` is in your
`PATH`.

### Notes on the macOS Terminal.app

As it operates similarly to gnome-terminal (described above),
it has the same issue with exiting prematurely. An appropriate
wrapper script can be found
[here](https://gist.github.com/wosc/680f87845d0fd9d8b4a9e2f8c42f98a2)


### GUI editors

Non-terminal-based editors can also suffer from the same
Expand Down
1 change: 0 additions & 1 deletion native/inotify_simple
Submodule inotify_simple deleted from 979648
32 changes: 19 additions & 13 deletions native/textern.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@
import asyncio
import tempfile
import urllib.parse
from inotify_simple.inotify_simple import INotify, flags
from watchgod.watchgod import awatch

if sys.platform == 'darwin':
TMPDIR = os.environ['TMPDIR']
else:
TMPDIR = os.environ['XDG_RUNTIME_DIR']


class TmpManager():

def __init__(self):
try:
tmpdir_parent = os.path.join(os.environ['XDG_RUNTIME_DIR'], 'textern')
tmpdir_parent = os.path.join(TMPDIR, 'textern')
os.makedirs(tmpdir_parent)
except:
tmpdir_parent = None
Expand Down Expand Up @@ -63,11 +68,10 @@ def has(self, relfn):


def main():
with INotify() as ino, TmpManager() as tmp_mgr:
ino.add_watch(tmp_mgr.tmpdir, flags.CLOSE_WRITE)
with TmpManager() as tmp_mgr:
loop = asyncio.get_event_loop()
loop.create_task(watch_directory(tmp_mgr))
loop.add_reader(sys.stdin.buffer, handle_stdin, tmp_mgr)
loop.add_reader(ino.fd, handle_inotify_event, ino, tmp_mgr)
loop.run_forever()
loop.close()

Expand Down Expand Up @@ -161,14 +165,16 @@ async def handle_message_new_text(tmp_mgr, msg):
}


def handle_inotify_event(ino, tmp_mgr):
for event in ino.read():
# this check is relevant in the case where we're handling the inotify
# event caused by tmp_mgr.new(), but then an exception occurred in
# handle_message() which caused the tmpfile to already be deleted
if tmp_mgr.has(event.name):
text, id = tmp_mgr.get(event.name)
send_text_update(id, text)
async def watch_directory(tmp_mgr):
async for changes in awatch(tmp_mgr.tmpdir):
for typ, path in changes:
path = os.path.basename(path)
# this check is relevant in the case where we're handling the
# event caused by tmp_mgr.new(), but then an exception occurred in
# handle_message() which caused the tmpfile to already be deleted
if tmp_mgr.has(path):
text, id = tmp_mgr.get(path)
send_text_update(id, text)


def send_text_update(id, text):
Expand Down
1 change: 1 addition & 0 deletions native/watchgod
Submodule watchgod added at 15c72b