将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名
This commit is contained in:
326
Apps/Terminal/main.vp
Normal file
326
Apps/Terminal/main.vp
Normal file
@@ -0,0 +1,326 @@
|
||||
import vpsdk.vpui as vpui
|
||||
import vpsdk.window as window
|
||||
import vpsdk.process as process
|
||||
import vpsdk.fs as fs
|
||||
import vpsdk.syscall as _syscall
|
||||
import vpsdk.stdlib as stdlib
|
||||
import string
|
||||
import viperlib
|
||||
from stdint import *
|
||||
import t, c
|
||||
|
||||
@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16))
|
||||
def _start() -> t.CInt | t.CExport:
|
||||
root: vpui.Tk = vpui.Tk()
|
||||
root.title("Terminal")
|
||||
root.set_style(window.STYLE_WIN7)
|
||||
root.geometry(80, 30, 640, 480)
|
||||
root.bg_color = t.CUInt32T(0x0C0C0C)
|
||||
master: vpui.Tk | t.CPtr = c.Addr(root)
|
||||
|
||||
def _sdbg(msg: str):
|
||||
_syscall._syscall1(t.CUInt64T(18), t.CUInt64T(msg))
|
||||
|
||||
_sdbg("[term] start\n")
|
||||
|
||||
_cwd: t.CArray[t.CChar, 64]
|
||||
_cwd[0] = 47
|
||||
for i in range(1, 64):
|
||||
_cwd[i] = 0
|
||||
|
||||
sbar: vpui.Scrollbar = vpui.Scrollbar(master, 16, 446, vpui.VERTICAL)
|
||||
root.pack(0, vpui.PACK_RIGHT, vpui.FILL_Y, 0, 0, 0)
|
||||
|
||||
term: vpui.Text = vpui.Text(master, 624, 446)
|
||||
root.pack(1, vpui.PACK_LEFT, vpui.FILL_BOTH, 1, 0, 0)
|
||||
term.insert("ViperOS Terminal v1.1")
|
||||
term.insert("Type 'help' for commands.")
|
||||
term.insert("")
|
||||
|
||||
term.yscrollbar = t.CType(sbar, vpui.Widget, t.CPtr)
|
||||
|
||||
def _on_scroll():
|
||||
act: t.CInt = sbar.action
|
||||
if act == 1:
|
||||
term.scroll_offset -= 1
|
||||
elif act == 2:
|
||||
term.scroll_offset += 1
|
||||
elif act == 3:
|
||||
vis: t.CInt = term._visible_lines()
|
||||
term.scroll_offset -= vis
|
||||
elif act == 4:
|
||||
vis2: t.CInt = term._visible_lines()
|
||||
term.scroll_offset += vis2
|
||||
elif act == 5:
|
||||
aval: t.CInt = sbar.action_value
|
||||
if term.line_count > 0:
|
||||
term.scroll_offset = aval * term.line_count / 1000
|
||||
vis3: t.CInt = term._visible_lines()
|
||||
max_off: t.CInt = term.line_count - vis3
|
||||
if max_off < 0: max_off = 0
|
||||
if term.scroll_offset < 0: term.scroll_offset = 0
|
||||
if term.scroll_offset > max_off: term.scroll_offset = max_off
|
||||
term._update_scrollbar()
|
||||
|
||||
sbar.command = c.Addr(_on_scroll)
|
||||
|
||||
def _startswith(s: str, prefix: str) -> t.CInt:
|
||||
plen: t.CSizeT = string.strlen(prefix)
|
||||
if string.strncmp(s, prefix, plen) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _build_path(out: str, out_size: t.CInt, rel: str):
|
||||
if c.Deref(rel) == 47:
|
||||
string.strncpy(out, rel, out_size - 1)
|
||||
else:
|
||||
i: t.CInt = 0
|
||||
for i in range(63):
|
||||
ch: t.CChar = _cwd[i]
|
||||
c.DerefAs(out + i, ch)
|
||||
if ch == 0: break
|
||||
cwd_len: t.CInt = i
|
||||
if cwd_len > 0 and _cwd[cwd_len - 1] != 47:
|
||||
c.DerefAs(out + cwd_len, t.CChar(47))
|
||||
cwd_len += 1
|
||||
j: t.CInt = 0
|
||||
for j in range(out_size - 1 - cwd_len):
|
||||
ch2: t.CChar = c.Deref(rel + j)
|
||||
c.DerefAs(out + cwd_len + j, ch2)
|
||||
if ch2 == 0: break
|
||||
c.DerefAs(out + out_size - 1, t.CChar(0))
|
||||
|
||||
def _print_dir_entry(name: str, is_dir: t.CInt):
|
||||
buf: t.CArray[t.CChar, 80]
|
||||
j: t.CInt = 0
|
||||
for j in range(78):
|
||||
ch: t.CChar = c.Deref(name + j)
|
||||
buf[j] = ch
|
||||
if ch == 0: break
|
||||
if is_dir and j < 78:
|
||||
buf[j] = 47
|
||||
j += 1
|
||||
buf[j] = 0
|
||||
term.insert_ptr(c.Addr(buf[0]))
|
||||
|
||||
def _cmd_cd(path: str):
|
||||
if path is None or c.Deref(path) == 0:
|
||||
_cwd[0] = 47
|
||||
for i in range(1, 64):
|
||||
_cwd[i] = 0
|
||||
return
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
dd: t.CInt = fs.opendir(c.Addr(full[0]))
|
||||
if dd < 0:
|
||||
term.insert("Error: dir not found")
|
||||
return
|
||||
fs.closedir(dd)
|
||||
string.strncpy(c.Addr(_cwd[0]), c.Addr(full[0]), 63)
|
||||
_cwd[63] = 0
|
||||
|
||||
def _cmd_ls():
|
||||
dd: t.CInt = fs.opendir(c.Addr(_cwd[0]))
|
||||
if dd < 0:
|
||||
term.insert("Error: cannot open dir")
|
||||
return
|
||||
info: t.CArray[t.CChar, 320]
|
||||
string.memset(c.Addr(info[0]), 0, 320)
|
||||
while True:
|
||||
result: t.CInt = fs.readdir(dd, c.Addr(info[0]))
|
||||
if result != 0: break
|
||||
attr_val: t.CUInt8T = t.CUInt8T(c.Deref(c.Addr(info[4])))
|
||||
name_off: t.CInt = 16
|
||||
name_ptr: str = c.Addr(info[name_off])
|
||||
if c.Deref(name_ptr) == 0: break
|
||||
if c.Deref(name_ptr) == 46:
|
||||
if c.Deref(name_ptr + 1) == 0:
|
||||
string.memset(c.Addr(info[0]), 0, 320)
|
||||
continue
|
||||
if c.Deref(name_ptr + 1) == 46 and c.Deref(name_ptr + 2) == 0:
|
||||
string.memset(c.Addr(info[0]), 0, 320)
|
||||
continue
|
||||
if (attr_val & 0x10) != 0:
|
||||
_print_dir_entry(name_ptr, 1)
|
||||
else:
|
||||
_print_dir_entry(name_ptr, 0)
|
||||
string.memset(c.Addr(info[0]), 0, 320)
|
||||
fs.closedir(dd)
|
||||
|
||||
def _cmd_cat(path: str):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_RDONLY)
|
||||
if fd < 0:
|
||||
term.insert("Error: file not found")
|
||||
return
|
||||
buf: t.CArray[t.CChar, 80]
|
||||
while True:
|
||||
string.memset(c.Addr(buf[0]), 0, 80)
|
||||
n: t.CInt = fs.read(fd, c.Addr(buf[0]), 78)
|
||||
if n <= 0: break
|
||||
if n > 78: n = 78
|
||||
buf[n] = 0
|
||||
term.insert_ptr(c.Addr(buf[0]))
|
||||
fs.close(fd)
|
||||
|
||||
def _cmd_mkdir(path: str):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
result: t.CInt = fs.mkdir(c.Addr(full[0]))
|
||||
if result < 0:
|
||||
term.insert("Error: mkdir failed")
|
||||
else:
|
||||
term.insert("Directory created")
|
||||
|
||||
def _cmd_rm(path: str):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
result: t.CInt = fs.remove(c.Addr(full[0]))
|
||||
if result < 0:
|
||||
term.insert("Error: remove failed")
|
||||
else:
|
||||
term.insert("Removed")
|
||||
|
||||
def _cmd_touch(path: str):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_WRONLY | fs.O_CREAT)
|
||||
if fd < 0:
|
||||
term.insert("Error: touch failed")
|
||||
return
|
||||
fs.close(fd)
|
||||
term.insert("File created")
|
||||
|
||||
def _cmd_sysinfo():
|
||||
term.insert("ViperOS v1.0 (x86_64)")
|
||||
term.insert("Framebuffer: 32bpp")
|
||||
term.insert("Compiler: TransPyC")
|
||||
|
||||
def _cmd_hexdump(path: str):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
fd: t.CInt = fs.open(c.Addr(full[0]), fs.O_RDONLY)
|
||||
if fd < 0:
|
||||
term.insert("Error: file not found")
|
||||
return
|
||||
offset: t.CInt = 0
|
||||
buf: t.CArray[t.CChar, 16]
|
||||
while True:
|
||||
string.memset(c.Addr(buf[0]), 0, 16)
|
||||
n: t.CInt = fs.read(fd, c.Addr(buf[0]), 16)
|
||||
if n <= 0: break
|
||||
if n > 16: n = 16
|
||||
line: t.CArray[t.CChar, 80]
|
||||
string.memset(c.Addr(line[0]), 0, 80)
|
||||
viperlib.snprintf(c.Addr(line[0]), 80, "%08x: ", offset)
|
||||
pos: t.CInt = 10
|
||||
j: t.CInt = 0
|
||||
for j in range(16):
|
||||
if j < n:
|
||||
ub: t.CUInt32T = t.CUInt32T(buf[j]) & 0xFF
|
||||
hi: t.CInt = t.CInt(ub >> 4)
|
||||
lo: t.CInt = t.CInt(ub & 0xF)
|
||||
if hi < 10:
|
||||
line[pos] = t.CChar(48 + hi)
|
||||
else:
|
||||
line[pos] = t.CChar(65 + hi - 10)
|
||||
pos += 1
|
||||
if lo < 10:
|
||||
line[pos] = t.CChar(48 + lo)
|
||||
else:
|
||||
line[pos] = t.CChar(65 + lo - 10)
|
||||
pos += 1
|
||||
else:
|
||||
line[pos] = 32
|
||||
pos += 1
|
||||
line[pos] = 32
|
||||
pos += 1
|
||||
line[pos] = 32
|
||||
pos += 1
|
||||
if j == 7:
|
||||
line[pos] = 32
|
||||
pos += 1
|
||||
line[pos] = 124
|
||||
pos += 1
|
||||
for j in range(n):
|
||||
b2: t.CUInt32T = t.CUInt32T(buf[j]) & 0xFF
|
||||
if b2 >= 32 and b2 < 127:
|
||||
line[pos] = t.CChar(b2)
|
||||
else:
|
||||
line[pos] = 46
|
||||
pos += 1
|
||||
line[pos] = 0
|
||||
term.insert_ptr(c.Addr(line[0]))
|
||||
offset += n
|
||||
fs.close(fd)
|
||||
|
||||
def _cmd_run(path: str, blocking: t.CInt):
|
||||
full: t.CArray[t.CChar, 256]
|
||||
_build_path(c.Addr(full[0]), 256, path)
|
||||
pid: t.CInt = process.spawn(c.Addr(full[0]), blocking)
|
||||
if pid < 0:
|
||||
term.insert("Error: cannot spawn")
|
||||
elif blocking:
|
||||
term.insert("Process exited")
|
||||
else:
|
||||
msg: t.CArray[t.CChar, 32]
|
||||
viperlib.snprintf(c.Addr(msg[0]), 32, "Spawned pid=%d", pid)
|
||||
term.insert_ptr(c.Addr(msg[0]))
|
||||
|
||||
def _on_command() -> t.CInt:
|
||||
_sdbg("[cmd] enter\n")
|
||||
text: str = term.get()
|
||||
_sdbg("[cmd] text=")
|
||||
_sdbg(text)
|
||||
_sdbg("\n")
|
||||
if _startswith(text, "echo "):
|
||||
term.insert_ptr(text + 5)
|
||||
elif string.samestr(text, "echo"):
|
||||
pass
|
||||
elif string.samestr(text, "clear"):
|
||||
term.delete(0, -1)
|
||||
elif string.samestr(text, "help"):
|
||||
term.insert("File: ls cd cat pwd mkdir rm touch")
|
||||
term.insert("Sys: ver about sysinfo reboot")
|
||||
term.insert("Util: echo clear help hexdump run runb")
|
||||
elif string.samestr(text, "ver"):
|
||||
term.insert("ViperOS Terminal v1.1")
|
||||
elif string.samestr(text, "about"):
|
||||
term.insert("ViperOS - A tiny OS in Viper lang")
|
||||
elif string.samestr(text, "pwd"):
|
||||
term.insert_ptr(c.Addr(_cwd[0]))
|
||||
elif string.samestr(text, "ls"):
|
||||
_cmd_ls()
|
||||
elif string.samestr(text, "cd"):
|
||||
_cmd_cd("")
|
||||
elif _startswith(text, "cd "):
|
||||
_cmd_cd(text + 3)
|
||||
elif _startswith(text, "cat "):
|
||||
_cmd_cat(text + 4)
|
||||
elif _startswith(text, "mkdir "):
|
||||
_cmd_mkdir(text + 6)
|
||||
elif _startswith(text, "rm "):
|
||||
_cmd_rm(text + 3)
|
||||
elif _startswith(text, "touch "):
|
||||
_cmd_touch(text + 6)
|
||||
elif string.samestr(text, "sysinfo"):
|
||||
_cmd_sysinfo()
|
||||
elif string.samestr(text, "reboot"):
|
||||
process.exit(0)
|
||||
elif _startswith(text, "hexdump "):
|
||||
_cmd_hexdump(text + 8)
|
||||
elif _startswith(text, "run "):
|
||||
_cmd_run(text + 4, 0)
|
||||
elif _startswith(text, "runb "):
|
||||
_cmd_run(text + 5, 1)
|
||||
else:
|
||||
if text is not None and c.Deref(text) != 0:
|
||||
term.insert("Unknown command. Type 'help'.")
|
||||
return 0
|
||||
|
||||
term.on_command = c.Addr(_on_command)
|
||||
|
||||
root.mainloop()
|
||||
process.exit(0)
|
||||
return 0
|
||||
Reference in New Issue
Block a user