Skip to content

Commit

Permalink
Merge pull request #3 from DavidCEllis/py39_markdown_hotkeys
Browse files Browse the repository at this point in the history
Update to Python 3.10 - Add support for hotkeys - Fix issue with updated Bleach
  • Loading branch information
DavidCEllis authored Jun 7, 2022
2 parents f93622f + b34d455 commit 0d0d09b
Show file tree
Hide file tree
Showing 18 changed files with 695 additions and 139 deletions.
23 changes: 15 additions & 8 deletions application/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

from cx_Freeze import setup, Executable

python3_dll = str(Path(sys.executable).parent / "python3.dll")

base_path = Path(__file__).resolve().parents[1]
templates = str(base_path / "src" / "splitnotes2" / "templates")
static_folder = str(base_path / "src" / "splitnotes2" / "static")
Expand All @@ -21,20 +19,29 @@

options = {
"build_exe": {
"includes": ["atexit", "jinja2.ext"],
"include_files": [python3_dll, templates, static_folder, icon_png],
"includes": [
"atexit",
"jinja2.ext",
"html.parser",
"markdown",
"markdown.extensions",
"markdown.extensions.nl2br",
"markdown.extensions.sane_lists",
"markdown.extensions.tables",
],
"include_files": [templates, static_folder, icon_png],
}
}

executables = [
Executable("app.py", base=base, targetName="splitnotes2", icon=icon_file),
Executable("app_server.py", targetName="splitnotes2_server", icon=icon_file),
Executable("app.py", base=base, target_name="splitnotes2", icon=icon_file),
Executable("app_server.py", target_name="splitnotes2_server", icon=icon_file),
]

setup(
name="splitnotes2",
version="0.5.0",
description="Speedrun splitnotes tool with HTML rendering",
version="0.6.0",
description="Speedrun notes tool with HTML rendering",
options=options,
executables=executables,
)
91 changes: 47 additions & 44 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SplitNotes 2 #

**SplitNotes but bigger***
**Speedrun notes with markdown and html formatting**

SplitNotes2 is an application for displaying speedrun notes in sync with livesplit.
Requires *livesplit server* to be running.
Expand All @@ -23,16 +23,14 @@ There is now a server version included to allow reading from a browser on anothe
The formatting for notes basically follows the format used by the original SplitNotes
with some additional enhancements and exceptions.

1. Comment lines still use square brackets.
2. By default the splits will break on newlines. Multiple newlines and comments are ignored.
3. The notes are now rendered as HTML and so can be formatted as such.
Markdown and HTML formatted notes are supported.
These will be interpreted based on file extension (.md, .txt or .html).
Markdown and plain text formatted notes will automatically have line breaks
inserted in between lines.

This means that it's easy to emphasise important part of the notes using basic HTML tags such as
`<strong>`, `<em>`, and `<mark>`.

The formatter will automatically insert HTML breaks `<br>` between lines,
a backslash `\ ` at the end of a line will indicate that the line should **not**
have a break inserted (useful for headers and lists).
1. Comment lines still use square brackets.
2. By default splits will break on newlines, multiple newlines are ignored in this case.
3. The rendering is done as HTML so HTML formatting can be used.

## splitnotes2_server.exe ##

Expand All @@ -46,44 +44,40 @@ and server_port in settings.json. There is no dialog for editing these settings

#### Source ####

```html
<h3>Moonlight Butterfly</h3>\
<em>Buy Crest of Artorias, Tower Kite Shield and max-1 large arrows</em>
<strong>Prompt swap 99 titanite shards</strong>
In Butterfly Fight:\
<ul>\
<li>Prepare DGH equip in weapon slot 1</li>\
<li>Sort souls to top of inventory</li>\
<li>Equip Homeward Bone</li>\
<li>Mouse cursor in place for prompt swaps</li>\
</ul>\
Kill Moonlight Butterfly (3 Soul Spears)
Darksign

<h3>Lord Vessel</h3>\
Warp to Firelink Shrine
In the warp sort Butterfly's soul above Estus
Talk to Frampt and place the Lordvessel
Warp back up with Frampt
<em>Use prompt swap to sell 99 of each of each soul</em>
<strong>Buy Homing Soulmass and Soul Spear from Griggs</strong>
Homeward Bone

<h3>Hydra</h3>\
<mark>Level 23ATT 15END 10STR 45DEX 66INT</mark>
<strong>Attune FC/GSA/Homing/Spears/Spears/GHSA</strong>
DGH Fall RTSR Setup
Kill Hydra (3 soul spears)
Quitout after obtaining the items
Kill the Gold Crystal Golem
Talk to Dusk
Summon Dusk and buy Hidden Body
Darksign
```markdown
## High Hedge ##
### Friendly Arm Inn ###
* *East*
* *Pick up the ring*
* **Peldvale**

### Peldvale ###
* *South*
* **High Hedge**

### High Hedge ###
* Rest and Spin
* *South to Shop*
* Thalantyr (1, 1)
* Shop:
* Sell the wand
* Identify the ring
* Sell the ring
* 3x Potion of Explosions
* Potion of Magic Blocking
* Protection from Magic
* Identify
* Shield
* Mirror Image
* 3x Invisibility
* *South*
* Go to Wilderness Map
/split
```

#### Result ####

![Image of splitnotes rendering](resources/demo_notes.png)
![Image of splitnotes rendering](resources/demo_notes_md.png)

## Configuration ##

Expand All @@ -96,6 +90,15 @@ The settings page offers some customisation and connection settings including:
* Default text and background colour
* HTML (Jinja2) template and CSS files to use for rendering

## Dependencies ##
* pyside2 - QT Gui Bindings
* jinja2 - Templating for the notes page
* bleach - Cleaning HTML to help protect if someone decided to make notes with a malicious script
* flask - Handling the server version
* attrs - Made the settings classes a lot cleaner
* markdown - Converting markdown to html for rendering
* keyboard - Global hotkeys to advance/reverse note offset to splits

---

Inspired by (but otherwise unassociated with) the original splitnotes: https://github.com/joeloskarsson/SplitNotes
Expand Down
Binary file removed resources/demo_notes.png
Binary file not shown.
Binary file added resources/demo_notes_md.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 13 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

__version__ = "0.5.0"
__version__ = "0.6.0"
__author__ = "DavidCEllis"


Expand All @@ -11,16 +11,23 @@
url="",
license="GPLv3",
description="Speedrun notes tool for advancing notes automatically with Livesplit.",
python_requires=">=3.6",
python_requires=">=3.9",
classifiers=[
"Development Status :: 1 - Early Development",
"Development Status :: 3 - Alpha",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
],
package_dir={"": "src"},
install_requires=["pyside2", "jinja2", "bleach", "flask", "attrs"],
install_requires=[
"pyside2",
"jinja2",
"bleach[css]",
"flask",
"attrs",
"markdown",
"keyboard",
],
tests_require=["pytest", "pytest-cov", "pytest-qt"],
extras_require={"build_exe": ["cx-freeze", "pywin32"], "dev": ["black"]},
)
1 change: 1 addition & 0 deletions src/splitnotes2/hotkeys/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .keyboard_fixer import Hotkey, read_hotkey, hotkey_or_none
58 changes: 58 additions & 0 deletions src/splitnotes2/hotkeys/keyboard_fixer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
The keyboard library does not handle numpad hotkeys correctly.
This is a rewrite of the relevant functions to handle this.
"""

import queue as _queue
import json

import attr
import keyboard


KEY_DOWN = "down"
KEY_UP = "up"


# Hotkey = namedtuple("Hotkey", "scancodes, name")
@attr.s
class Hotkey:
scancodes = attr.ib(default=None)
name = attr.ib(default=None)

def to_json(self):
as_dict = attr.asdict(self)
return json.dumps(as_dict)


def hotkey_or_none(keydict):
return Hotkey(**keydict) if keydict else None


def read_hotkey(suppress=True):
"""
Modified read_hotkey function to correctly support numpad keys.
The original function returns just the names, this returns a ([scancodes], name) tuple.
The scancodes can then be stored while the name can be displayed.
"""

queue = _queue.Queue()

# Replace lambda with
def hook_func(event):
queue.put(event)
return event.event_type == KEY_DOWN

hooked = keyboard.hook(hook_func, suppress=suppress)
while True:
keychange = queue.get()
if keychange.event_type == KEY_UP:
keyboard.unhook(hooked)
with keyboard._pressed_events_lock:
key_events = list(keyboard._pressed_events.values())
key_events.append(keychange)
key_codes = [e.scan_code for e in key_events]
key_string = keyboard.get_hotkey_name([e.name for e in key_events])
return Hotkey(key_codes, key_string)
Loading

0 comments on commit 0d0d09b

Please sign in to comment.