Add markdown previewer

master
Andy Stewart 8 years ago
parent 6b62a614bb
commit 51ec7a0be0
  1. 58
      README.md
  2. 105
      app/markdownpreviewer/buffer.py
  3. 2
      eaf.py
  4. BIN
      screenshot/markdown_previewer.gif

@ -13,6 +13,9 @@ Using this framework, you can use PyQt develop powerful graphics programs to ext
### Browser
![img](./screenshot/browser.gif)
### Markdown Previewer
![img](./screenshot/markdown_previewer.gif)
### Image Viewer
![img](./screenshot/image_viewer.gif)
@ -27,9 +30,17 @@ Using this framework, you can use PyQt develop powerful graphics programs to ext
1. Install python libraries:
```Bash
sudo pacman -S python-xlib python-pyqt5 python-pymediainfo
sudo pip install PyMuPDF
sudo pip install PyMuPDF grip
```
| Package | Use for |
| :-------- | :---- |
| python-xlib | Stick app window into emacs frame |
| python-pyqt5 | GUI library required for application development |
| python-pymediainfo | Detect file type, then choose the right application to open |
| PyMuPDF | Render engine required for PDF Viewer |
| grip | Markdown render server for Markdown Previewer |
2. Clone this repository and add below code in your ~/.emacs
```Elisp
(require 'eaf)
@ -40,28 +51,29 @@ sudo pip install PyMuPDF
```
M-x eaf-open
```
| App | Way to open | Key | Event |
| -------- | :---- | :-----: | :---- |
| Browser | URL | Left Button | Open link current tab |
| | | Ctrl + Left Button | Open link in new tab |
| Image Viewer | Image file path | j | Load next image in current directory |
| | | k | Load previous image in current directory |
| Video Player | Video file path | Space | Play or Pause |
| | | h | Seek backward |
| | | l | Seek forward |
| Pdf Viewer | Pdf file path | j | Scroll up |
| | | k | Scroll down |
| | | Space | Scroll up page |
| | | b | Scroll down page |
| | | , | Scroll to end |
| | | . | Scroll to home |
| | | t | Switch scale mode |
| | | - | Zoom out |
| | | = | Zoom in |
| | | 0 | Zoomn reset |
| | | g | Goto page |
| Camera | Type 'eaf-camera' | | |
| Demo | Type 'eaf-demo' | | |
| App | Way to open | Key | Event |
| :-------- | :---- | :-----: | :---- |
| Browser | URL | Left Button | Open link current tab |
| | | Ctrl + Left Button | Open link in new tab |
| Markdown previewer | Markdown file path | | |
| Image Viewer | Image file path | j | Load next image in current directory |
| | | k | Load previous image in current directory |
| Video Player | Video file path | Space | Play or Pause |
| | | h | Seek backward |
| | | l | Seek forward |
| Pdf Viewer | Pdf file path | j | Scroll up |
| | | k | Scroll down |
| | | Space | Scroll up page |
| | | b | Scroll down page |
| | | , | Scroll to end |
| | | . | Scroll to home |
| | | t | Switch scale mode |
| | | - | Zoom out |
| | | = | Zoom in |
| | | 0 | Zoomn reset |
| | | g | Goto page |
| Camera | Type 'eaf-camera' | | |
| Demo | Type 'eaf-demo' | | |
### Why this awesome framework can't works with MacOS?
There are mainly three obstacles:

@ -0,0 +1,105 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Andy Stewart
#
# Author: Andy Stewart <lazycat.manatee@gmail.com>
# Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt5 import QtCore
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKit import QWebSettings
from core.buffer import Buffer
from core.utils import PostGui
import socket
import subprocess
import threading
class AppBuffer(Buffer):
def __init__(self, buffer_id, url):
Buffer.__init__(self, buffer_id, url, False, QColor(255, 255, 255, 255))
# Get free port to render markdown.
self.port = self.get_free_port()
# Start markdown render process.
subprocess.Popen("grip {0} {1}".format(url, self.port), shell=True)
# Init widget.
self.add_widget(BrowserWidget())
self.buffer_widget.titleChanged.connect(self.change_title)
# Add timer make load markdown preview link after grip process start finish.
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)))
self.buffer_widget.update()
class BrowserWidget(QWebView):
def __init__(self):
super(QWebView, self).__init__()
self.web_page = WebPage()
self.setPage(self.web_page)
self.settings().setAttribute(QWebSettings.PluginsEnabled, True)
self.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
self.settings().setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
class WebPage(QWebPage):
open_url_in_new_tab = QtCore.pyqtSignal(str)
def __init__(self):
super(WebPage, self).__init__()
def acceptNavigationRequest(self, frame, request, type):
modifiers = QApplication.keyboardModifiers()
# Handle myself if got user event.
if type == QWebPage.NavigationTypeLinkClicked:
if modifiers == Qt.ControlModifier:
self.open_url_in_new_tab.emit(request.url().toString())
else:
self.view().load(request.url())
# Return False to stop default behavior.
return False
# # Otherwise, use default behavior.
return QWebPage.acceptNavigationRequest(self, frame, request, type)
def javaScriptConsoleMessage(self, msg, lineNumber, sourceID):
pass

@ -63,6 +63,8 @@ class EAF(dbus.service.Object):
if extension in [".pdf", ".xps", ".oxps", ".cbz", ".epub", ".fb2", "fbz"]:
return self.create_app(buffer_id, url, "app.pdfviewer.buffer")
if extension in [".md"]:
return self.create_app(buffer_id, url, "app.markdownpreviewer.buffer")
else:
file_info = MediaInfo.parse(url)
if file_is_image(file_info):

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Loading…
Cancel
Save