Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

148 sardine gui #157

Merged
Merged
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
49 changes: 48 additions & 1 deletion fishery/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import click

from . import console
from .console import ConsoleManager
from .profiler import Profiler

CONTEXT_SETTINGS = {
Expand All @@ -21,6 +21,7 @@
@click.pass_context
def main(ctx: click.Context):
if ctx.invoked_subcommand is None:
console = ConsoleManager()
console.start()


Expand Down Expand Up @@ -53,9 +54,55 @@ def main(ctx: click.Context):
)
def profile(clock: str, filepath: str):
profiler = Profiler(clock=clock, filepath=filepath)
console = ConsoleManager()
with profiler:
console.start()


# fishery web
# fishery web --host
# fishery web --port
# fishery web --host --port
@main.command(
short_help="Starts sardine as a web server.",
help="""
This command starts sardine as a web server. The server can be accessed
at http://localhost:5000 by default.
""",
)
@click.option(
"-h",
"--host",
default="localhost",
help="The host to bind the server to.",
show_default=True,
type=str,
)
@click.option(
"-p",
"--port",
default=5000,
help="The port to bind the server to.",
show_default=True,
type=int,
)
@click.option(
"--no-browser",
is_flag=True,
help="Prevents the server from opening a browser window.",
)
def web(host: str, port: int, no_browser: bool):
from .server import WebServer
consoleManager = ConsoleManager()
server = WebServer(host=host, port=port, )
server.start_in_thread(consoleManager.console)
if not no_browser:
server.open_in_browser()
consoleManager.start()





if __name__ == "__main__":
main()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
21 changes: 16 additions & 5 deletions sardine/client/src/App.js → fishery/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ def baba():

function kedDownHandler(event) {
// Ctrl + Enter
if(event.key === 'Enter' && event.ctrlKey) {
console.log(getSelectedLines());
executeCode(getSelectedLines());
if(event.key === 'Enter' && event.shiftKey) {
event.preventDefault();
executeCode(getSelectedLines()+"\n\n");
}
}

Expand All @@ -53,11 +53,22 @@ def baba():

return state?.doc.sliceString(fromLine.from, toLine.to)
}

useEventListener('keydown', kedDownHandler);

const codeMirror = useRef();

const [logs, setLogs] = useState([]);
useEffect(() => {
let source = new EventSource("/log");
console.log("source", source)
source.onmessage = (event)=>{
console.log("onmessage",event)
setLogs( logs => [...logs, event.data] );
}
return () => {};
}, []);

return (
<div id="editor">
<Menubar
Expand All @@ -79,7 +90,7 @@ def baba():
[vim(), python({})] : [python({})]}
onChange={onChange}
/>
<Log />
<Log logs={logs} />
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import './Log.css'
import Console from './console/Console';

Expand All @@ -9,16 +9,22 @@ const logExample = [
"[19:33] ERROR: ... blabla",
]



class Log extends React.Component {

render() {

let logs = this.props.logs;

return (
<div id="log">
<textarea
id="logwindow"
>
Welcome to Sardine REPL: the embedded code editor for Sardine! Press Shift+Enter to eval selection.
</textarea>
<Console logs={logExample} />
<Console logs={logs} />
</div>
)
}
Expand Down
4 changes: 4 additions & 0 deletions fishery/client/src/components/console/Console.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.console{
color: white;
font-family: monospace;
}
23 changes: 23 additions & 0 deletions fishery/client/src/components/console/Console.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import './Console.css'

const Console = ({ logs }) => {


return (
<div className="console">
<div className="console-header">
<h3>Console</h3>
</div>
<div className="console-content">
<ul>
{logs.map((log) => {
return <li>{log}</li>
})}
</ul>
</div>
</div>
);
};

export default Console;
File renamed without changes.
File renamed without changes.
File renamed without changes.
74 changes: 39 additions & 35 deletions fishery/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,40 +128,44 @@ async def run_forever():
await loop.create_future()


def start():
loop = sardine.event_loop.new_event_loop()

repl_locals = {"asyncio": asyncio}
for key in (
"__name__",
"__package__",
"__loader__",
"__spec__",
"__builtins__",
"__file__",
):
repl_locals[key] = globals()[key]

console = AsyncIOInteractiveConsole(repl_locals, loop)

try:
import readline # NoQA
except ImportError:
pass

repl_thread = REPLThread(console=console)
repl_thread.daemon = True
repl_thread.start()

with Runner(loop=loop) as runner:
while True:
try:
runner.run(run_forever())
except KeyboardInterrupt:
if console.repl_future and not console.repl_future.done():
console.repl_future.cancel()
console.repl_future_interrupted = True
class ConsoleManager:

def __init__(self):
self.loop = sardine.event_loop.new_event_loop()

repl_locals = {"asyncio": asyncio}
for key in (
"__name__",
"__package__",
"__loader__",
"__spec__",
"__builtins__",
"__file__",
):
repl_locals[key] = globals()[key]

self.console = AsyncIOInteractiveConsole(repl_locals, self.loop)


def start(self):
try:
import readline # NoQA
except ImportError:
pass

repl_thread = REPLThread(console=self.console)
repl_thread.daemon = True
repl_thread.start()

with Runner(loop=self.loop) as runner:
while True:
try:
runner.run(run_forever())
except KeyboardInterrupt:
if self.console.repl_future and not self.console.repl_future.done():
self.console.repl_future.cancel()
self.console.repl_future_interrupted = True
else:
break
else:
break
else:
break
File renamed without changes.
71 changes: 71 additions & 0 deletions fishery/server/flask_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import os
from flask import Flask, send_from_directory, request, Response
from pygtail import Pygtail


from appdirs import *
from pathlib import Path

APP_NAME, APP_AUTHOR = "Sardine", "Bubobubobubo"
USER_DIR = Path(user_data_dir(APP_NAME, APP_AUTHOR))
LOG_FILE = USER_DIR / "sardine.log"

__all__ = ("WebServer",)

class WebServer():
def __init__(self, host="localhost", port=5000):
self.host = host
self.port = port

def start(self, console):
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
print("Starting server" + str(self.host) + ":" + str(self.port))
app = server_factory(console)
app.run(host=self.host, port=self.port, use_reloader=False, debug=False)

def start_in_thread(self, console):
from threading import Thread
Thread(target=self.start, args=(console,)).start()

def open_in_browser(self):
import webbrowser
print("[red]Opening embedded editor at: [yellow]http://127.0.0.1:5000[/yellow][/red]")
webbrowser.open(f"http://{self.host}:{self.port}")


def server_factory(console):
app = Flask(__name__, static_folder='../client/build')

@app.post('/execute')
def execute():
code = request.json['code']
try:
console.push(code)
return { 'code': code }
except Exception as e:
return { 'error': str(e) }

# Serve React App
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def serve(path):
if path != "" and os.path.exists(app.static_folder + '/' + path):
return send_from_directory(app.static_folder, path)
else:
return send_from_directory(app.static_folder, 'index.html')


@app.route('/log')
def progress_log():
def generate():
for line in Pygtail(str(LOG_FILE), every_n=0.01):
yield "data:" + str(line) + "\n\n"
return Response(generate(), mimetype= 'text/event-stream')

return app


if __name__ == '__main__':
server_factory().run()
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ classifiers = [

# Requirements: This is done differently by poetry!
dependencies = [
"pygtail>=0.14.0",
"Flask-SocketIO>=5.3.2",
"Flask>=2.2.2",
"Click>=8.1.3",
Expand Down
2 changes: 1 addition & 1 deletion sardine/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from InquirerPy import inquirer
from rich.panel import Panel
from pathlib import Path
from rich import print
from ..logger import print
from appdirs import * # Wildcard used in docs
import click
import json
Expand Down
29 changes: 0 additions & 29 deletions sardine/client/src/components/console/Console.js

This file was deleted.

2 changes: 1 addition & 1 deletion sardine/handlers/midi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional, Union

import mido
from rich import print
from ..logger import print

from ..utils import alias_param
from .sender import Number, NumericElement, Sender
Expand Down
2 changes: 1 addition & 1 deletion sardine/handlers/midi_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import mido
from mido import Message, get_input_names, open_input, parse_string_stream
from rich import print
from ..logger import print

from ..base.handler import BaseHandler

Expand Down
Loading