diff --git a/README.md b/README.md
index 6e4039e..d21ad1c 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ EAF is extensible, you can develop any PyQt application and integrate it into Em
| Terminal Emulator | RSS Reader |
| :--------: | :------: |
-|
|
|
+|
|
|
| | |
## Install EAF
@@ -62,28 +62,32 @@ If you use [use-package](https://github.com/jwiegley/use-package), a sample conf
sudo pip3 install dbus-python python-xlib pyqt5 pyqtwebengine pymupdf grip qrcode feedparser
```
-3. Compile ```qtermwidget-git``` use the following command:
-```Elisp
-git clone https://github.com/lxqt/qtermwidget.git --depth=1
-mkdir build && cd build
-cmake .. -DQTERMWIDGET_BUILD_PYTHON_BINDING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr
-make
-sudo make install
+3. Install and config ```wetty```:
+```Bash
+# Install wetty
+sudo yarn global add wetty
+
+# Make wetty login with public key
+ssh-keygen
+cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
+
+# You need add below in .bashrc if you are Chinese
+echo 'export LANG=zh_CN.UTF-8' >> ~/.bashrc
```
Package info:
-| Package | Package Repo | Classification | Package Description |
-| :-------- | :---- | :------ | :------ |
-| dbus-python | pip3 | Core | DBus IPC to communicate python with elisp |
-| python-xlib | pip3 | Core | Stick app window into Emacs frame |
-| pyqt5 | pip3 | Core | GUI library required for applications |
-| pyqtwebengine | pip3 | Core | Browser: QtWebEngine for browser application |
-| pymupdf | pip3 | Application | PDF Viewer: Rendering engine |
-| grip | pip3 | Application | Markdown Previewer: Markdown render server |
-| qrcode | pip3 | Application | File Transfer: Render QR code pointing local files |
-| feedparser | pip3 | Application | RSS Reader: feed parser |
-| qtermwidget-git | compile from source | Application | Terminal: QTermWidget, PyQt5 terminal emulator |
+| Package | Package Repo | Classification | Package Description |
+| :-------- | :---- | :------ | :------ |
+| dbus-python | pip3 | Core | DBus IPC to communicate python with elisp |
+| python-xlib | pip3 | Core | Stick app window into Emacs frame |
+| pyqt5 | pip3 | Core | GUI library required for applications |
+| pyqtwebengine | pip3 | Core | Browser: QtWebEngine for browser application |
+| pymupdf | pip3 | Application | PDF Viewer: Rendering engine |
+| grip | pip3 | Application | Markdown Previewer: Markdown render server |
+| qrcode | pip3 | Application | File Transfer: Render QR code pointing local files |
+| feedparser | pip3 | Application | RSS Reader: feed parser |
+| wetty | yarn | Application | Terminal: Share SSH over Web |
## Launch EAF Applications
diff --git a/app/file-sender/buffer.py b/app/file-sender/buffer.py
index 171e11f..878bb4d 100644
--- a/app/file-sender/buffer.py
+++ b/app/file-sender/buffer.py
@@ -24,11 +24,11 @@ from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout
from core.buffer import Buffer
+from core.utils import get_free_port
import http.server as BaseHTTPServer
import os
import qrcode
import shutil
-import socket
import sys
import threading
@@ -130,24 +130,12 @@ class FileTransferWidget(QWidget):
print("Network is unreachable")
sys.exit()
- def get_free_port(self):
- """
- Determines a free port using sockets.
- """
- free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- free_socket.bind(('0.0.0.0', 0))
- free_socket.listen(5)
- port = free_socket.getsockname()[1]
- free_socket.close()
-
- return port
-
def start_server(self, filename):
global local_file_path
local_file_path = filename
- self.port = self.get_free_port()
+ self.port = get_free_port()
self.local_ip = self.get_local_ip()
self.set_address("http://{0}:{1}/{2}".format(self.local_ip, self.port, filename))
diff --git a/app/markdown-previewer/buffer.py b/app/markdown-previewer/buffer.py
index f349ed1..985434d 100644
--- a/app/markdown-previewer/buffer.py
+++ b/app/markdown-previewer/buffer.py
@@ -22,9 +22,8 @@
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor
from core.browser import BrowserBuffer
-from core.utils import PostGui
+from core.utils import PostGui, get_free_port
import os
-import socket
import subprocess
import threading
@@ -33,7 +32,7 @@ class AppBuffer(BrowserBuffer):
BrowserBuffer.__init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, False, QColor(255, 255, 255, 255))
# Get free port to render markdown.
- self.port = self.get_free_port()
+ self.port = get_free_port()
self.url = url
# Start markdown render process.
@@ -46,18 +45,6 @@ class AppBuffer(BrowserBuffer):
timer = threading.Timer(2, self.load_markdown_server)
timer.start()
- def get_free_port(self):
- """
- Determines a free port using sockets.
- """
- free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- free_socket.bind(('0.0.0.0', 0))
- free_socket.listen(5)
- port = free_socket.getsockname()[1]
- free_socket.close()
-
- return port
-
@PostGui()
def load_markdown_server(self):
self.buffer_widget.setUrl(QUrl("http://localhost:{0}".format(self.port)))
diff --git a/app/terminal/buffer.py b/app/terminal/buffer.py
index 9c433a4..fba66e6 100644
--- a/app/terminal/buffer.py
+++ b/app/terminal/buffer.py
@@ -19,30 +19,48 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from PyQt5.QtGui import QColor, QFont
-from core.buffer import Buffer
-import QTermWidget
+from PyQt5.QtCore import QUrl
+from PyQt5.QtGui import QColor
+from core.browser import BrowserBuffer
+from core.utils import PostGui, get_free_port
+import os
+import subprocess
+import signal
+import threading
+import getpass
-class AppBuffer(Buffer):
+class AppBuffer(BrowserBuffer):
def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict):
- Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict, True, QColor(0, 0, 0, 255))
+ BrowserBuffer.__init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict, False, QColor(255, 255, 255, 255))
- self.add_widget(QTermWidget.QTermWidget())
+ # Get free port to render markdown.
+ self.port = get_free_port()
+ self.url = url
- self.buffer_widget.setTerminalFont(QFont('Source Code Pro', 14))
- self.buffer_widget.setColorScheme('Linux')
+ # Start wetty process.
+ self.background_process = subprocess.Popen(
+ "wetty -p {0} --base / --sshuser {1} --sshauth publickey -c bash".format(self.port, getpass.getuser()),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
- self.buffer_widget.finished.connect(self.request_close_buffer)
+ # Add timer make load markdown preview link after grip process start finish.
+ threading.Timer(1, self.load_wetty_server).start()
- def get_key_event_widgets(self):
- return self.buffer_widget.children()
+ self.reset_default_zoom()
- def fake_key_event_filter(self, event_string):
- if event_string == "RET":
- self.buffer_widget.sendText("\n")
+ @PostGui()
+ def load_wetty_server(self):
+ self.buffer_widget.setUrl(QUrl("http://localhost:{0}".format(self.port)))
- def zoom_out(self):
- self.buffer_widget.zoomOut()
+ paths = os.path.split(self.url)
+ if len(paths) > 0:
+ self.change_title(paths[-1])
- def zoom_in(self):
- self.buffer_widget.zoomIn()
+ def handle_destroy(self):
+ os.killpg(os.getpgid(self.background_process.pid), signal.SIGTERM)
+
+ self.before_destroy_hook.emit()
+
+ if self.buffer_widget is not None:
+ self.buffer_widget.destroy()
diff --git a/core/utils.py b/core/utils.py
index 2ac4e4b..9ad638a 100644
--- a/core/utils.py
+++ b/core/utils.py
@@ -22,6 +22,7 @@
from PyQt5 import QtCore
import functools
import os
+import socket
class PostGui(QtCore.QObject):
@@ -59,3 +60,15 @@ def touch(path):
with open(path, 'a'):
os.utime(path)
+
+def get_free_port():
+ """
+ Determines a free port using sockets.
+ """
+ free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ free_socket.bind(('0.0.0.0', 0))
+ free_socket.listen(5)
+ port = free_socket.getsockname()[1]
+ free_socket.close()
+
+ return port
diff --git a/eaf.el b/eaf.el
index 507c6ca..8a7d062 100644
--- a/eaf.el
+++ b/eaf.el
@@ -7,7 +7,7 @@
;; Copyright (C) 2018, Andy Stewart, all rights reserved.
;; Created: 2018-06-15 14:10:12
;; Version: 0.5
-;; Last-Updated: Tue Jan 14 00:36:40 2020 (-0500)
+;; Last-Updated: Wed Jan 22 23:11:57 2020 (-0500)
;; By: Mingde (Matthew) Zeng
;; URL: http://www.emacswiki.org/emacs/download/eaf.el
;; Keywords:
@@ -1062,7 +1062,8 @@ This function works best if paired with a fuzzy search package."
(history (completing-read "[EAF/browser] Search || URL || History: " history-list))
(history-url (when (string-match "[^\s]+$" history)
(match-string 0 history))))
- (if (string-match "^\\(https?://\\)?[a-z0-9]+\\([-.][a-z0-9]+\\)*.+\\..+[a-z0-9.]\\{2,5\\}\\(:[0-9]{1,5}\\)?\\(/.*\\)?$" history-url)
+ (if (and history-url
+ (string-match "^\\(https?://\\)?[a-z0-9]+\\([-.][a-z0-9]+\\)*.+\\..+[a-z0-9.]\\{2,5\\}\\(:[0-9]{1,5}\\)?\\(/.*\\)?$" history-url))
(eaf-open-browser history-url)
(eaf-open-browser history))))))
diff --git a/screenshot/terminal.gif b/screenshot/terminal.gif
new file mode 100644
index 0000000..8c3dce6
Binary files /dev/null and b/screenshot/terminal.gif differ
diff --git a/screenshot/terminal.png b/screenshot/terminal.png
deleted file mode 100644
index b4e412f..0000000
Binary files a/screenshot/terminal.png and /dev/null differ