Luis-Filipe commited on
Commit
976e045
·
verified ·
1 Parent(s): e3f5888

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -78
app.py CHANGED
@@ -1,84 +1,91 @@
1
- import pcbasic
2
- import streamlit as st
 
 
 
 
3
 
4
- def run_basic_code(code):
5
- # Salva o código BASIC em um arquivo temporário
6
- with open("temp_program.bas", "w") as f:
7
- f.write(code)
8
-
9
- # Executa o PCBasic com opções para:
10
- # --exec: executar o código,
11
- # --ink=green: definir a tinta (texto) como verde,
12
- # --paper=black: definir o fundo como preto,
13
- # --border=green: definir a borda como verde.
14
- output = pcbasic.run(
15
- "temp_program.bas",
16
- options=["--exec", "--ink=green", "--paper=black", "--border=green"]
17
- )
18
- return output
19
 
20
- # Configuração da página
21
- st.set_page_config(page_title="PC-BASIC 2.0 - IBM 5150 Emulator", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- # CSS personalizado para unificar a aparência de todos os elementos (cabeçalho, edição e rodapé)
24
- st.markdown("""
25
- <style>
26
- @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&display=swap');
27
- .terminal {
28
- background-color: black !important;
29
- color: #00FF00 !important;
30
- font-family: 'IBM Plex Mono', monospace !important;
31
- padding: 10px !important;
32
- border: 3px solid #00FF00 !important;
33
- border-radius: 5px !important;
34
- margin: 0 !important;
35
- }
36
- /* Customizar a textarea do Streamlit */
37
- .stTextArea textarea {
38
- background-color: black !important;
39
- color: #00FF00 !important;
40
- font-family: 'IBM Plex Mono', monospace !important;
41
- border: 3px solid #00FF00 !important;
42
- border-radius: 5px !important;
43
- padding: 10px !important;
44
- }
45
- /* Remover espaçamentos extras dos contêineres do Streamlit */
46
- .stTextArea, .css-18e3th9, .css-1d391kg {
47
- margin: 0 !important;
48
- padding: 0 !important;
49
- }
50
- </style>
51
- """, unsafe_allow_html=True)
52
 
53
- # Cabeçalho do terminal (sem margem inferior)
54
- st.markdown("""
55
- <div class="terminal">
56
- PC-BASIC 2.0<br>
57
- (C) Copyright 2013—2018 Rob Hagemans.<br>
58
- IBM 5150 Emulator<br>
59
- 60300 Bytes free<br>
60
- OK
61
- </div>
62
- """, unsafe_allow_html=True)
63
-
64
- # Área de edição de código com aparência unificada
65
- code = st.text_area("Digite o código BASIC", height=200, key="code_input")
66
-
67
- # Botão para executar o código e exibir a saída logo abaixo, sem separação
68
- if st.button("Executar Código (RUN)"):
69
- if code:
70
- result = run_basic_code(code)
71
- st.markdown(f"""
72
- <div class="terminal">
73
- {result}
74
- </div>
75
- """, unsafe_allow_html=True)
76
  else:
77
- st.warning("Por favor, insira um código BASIC para executar.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
- # Menu inferior fixo, com aparência unificada e sem margem superior
80
- st.markdown("""
81
- <div class="terminal" style="margin-top: 0px;">
82
- 1LIST 2RUN 3LOAD 4SAVE 5CONT 6LPT1 7TRON 8TROFF 9NEW 0SYSTEM
83
- </div>
84
- """, unsafe_allow_html=True)
 
1
+ import os
2
+ import pty
3
+ import subprocess
4
+ import threading
5
+ from flask import Flask, render_template_string
6
+ from flask_sockets import Sockets
7
 
8
+ app = Flask(__name__)
9
+ sockets = Sockets(app)
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # HTML que carrega o xterm.js e conecta via WebSocket
12
+ HTML = """
13
+ <!doctype html>
14
+ <html>
15
+ <head>
16
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm/css/xterm.css" />
17
+ <script src="https://cdn.jsdelivr.net/npm/xterm/lib/xterm.js"></script>
18
+ <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit/lib/xterm-addon-fit.js"></script>
19
+ </head>
20
+ <body style="margin:0; padding:0; background:black;">
21
+ <div id="terminal" style="width:100vw; height:100vh;"></div>
22
+ <script>
23
+ const term = new Terminal({
24
+ cols: 80,
25
+ rows: 24,
26
+ theme: {
27
+ background: '#000000',
28
+ foreground: '#00FF00'
29
+ }
30
+ });
31
+ const fitAddon = new FitAddon.FitAddon();
32
+ term.loadAddon(fitAddon);
33
+ term.open(document.getElementById('terminal'));
34
+ fitAddon.fit();
35
+
36
+ const protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
37
+ const socketUrl = protocol + location.host + "/ws";
38
+ const socket = new WebSocket(socketUrl);
39
+
40
+ socket.onmessage = function(event) {
41
+ term.write(event.data);
42
+ };
43
+
44
+ term.onData(function(data) {
45
+ socket.send(data);
46
+ });
47
+ </script>
48
+ </body>
49
+ </html>
50
+ """
51
 
52
+ @app.route("/")
53
+ def index():
54
+ return render_template_string(HTML)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
+ @sockets.route("/ws")
57
+ def echo_socket(ws):
58
+ # Inicia o PCBasic em um pseudo-terminal
59
+ pid, fd = pty.fork()
60
+ if pid == 0:
61
+ # No processo filho, executa o PCBasic com as opções desejadas
62
+ # (por exemplo, --run para executar um arquivo, ou apenas iniciar o interpretador interativo)
63
+ os.execvp("pcbasic", ["pcbasic", "--run"]) # ajuste conforme necessário
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  else:
65
+ # Em thread, do pseudo-terminal e envia via WebSocket
66
+ def read_and_forward():
67
+ while True:
68
+ try:
69
+ data = os.read(fd, 1024)
70
+ if not data:
71
+ break
72
+ ws.send(data.decode(errors="ignore"))
73
+ except Exception:
74
+ break
75
+ thread = threading.Thread(target=read_and_forward)
76
+ thread.daemon = True
77
+ thread.start()
78
+
79
+ # Recebe os dados enviados pelo cliente e encaminha para o processo
80
+ while not ws.closed:
81
+ message = ws.receive()
82
+ if message is None:
83
+ break
84
+ os.write(fd, message.encode())
85
+ return
86
 
87
+ if __name__ == "__main__":
88
+ from gevent import pywsgi
89
+ from geventwebsocket.handler import WebSocketHandler
90
+ server = pywsgi.WSGIServer(("", 5000), app, handler_class=WebSocketHandler)
91
+ server.serve_forever()