fixed examples, fixed bug due to VType changes

This commit is contained in:
mark
2023-06-12 19:06:20 +02:00
parent d94f727eaa
commit 3032d3c115
13 changed files with 76 additions and 483 deletions

View File

@@ -9,7 +9,7 @@ fn random(min int max int) {
}
fn rnd() {
r := random(5 15)
switch r {
switch! r {
int r r
[] [] 10
}

View File

@@ -1,51 +0,0 @@
lib mers_libs/gui
base = gui_init()
column = base.gui_add(Column: [])
text = column.gui_add(Text: "Welcome to MERS GUI!")
button = column.gui_add(Button: "This is a button.")
second_button = column.gui_add(Button: "This is a second button.")
text_state = -2
second_text = column.gui_add(Text: "press the button above to remove this text!")
loop {
for event gui_updates() {
switch! event {
ButtonPressed([int ...]) {
e = event.noenum()
match e {
&e.eq(&button) println("First button pressed")
&e.eq(&second_button) {
// don't match on text_state because we need to change the original from inside the match statement
state = text_state
match state {
// the first, third, fifth, ... time the button is pressed: remove the text
text_state.mod(2).eq(0) {
if text_state.eq(-2) {
// the first time the button is pressed
text_state = 0
set_title("keep pressing the button!")
}
second_text.gui_remove()
}
// the 2nd, 4th, 6th, ... time the button is pressed: add the text back
text_state.eq(1) second_text = column.gui_add(Text: "i'm back!")
text_state.eq(3) second_text = column.gui_add(Text: "you can't fully get rid of me!")
true {
second_text = column.gui_add(Text: "i always come back")
// restart (set text_state to 0)
text_state = -1
}
}
text_state = text_state.add(1)
}
true println("A different button was pressed (unreachable)")
}
}
}
}
[]
}

View File

@@ -1,17 +0,0 @@
lib mers_libs/http_requests
t = thread(() {
// because this downloads for so long, the println() will appear after the other one.
http_get("https:\//raw.githubusercontent.com/dwyl/english-words/master/words.txt").assume_no_enum()
println("got words from word list!")
})
sleep(0.1)
// this will finish before the thread does.
http_get("https:\//github.com/").assume_no_enum()
println("got github start page as html")
t.await()
http_get("not a url").debug()

View File

@@ -1,4 +1,4 @@
fn map_string_to_int(list [string ...] func fn((string int))) {
fn map_string_to_int(list [string ...], func fn((string) int)) {
// return a function that can be used as an iterator
() {
// this function will be called by the for loop
@@ -36,4 +36,4 @@ fn square_numbers() {
for n square_numbers() {
println(n.to_string())
n >= 100
}
}

View File

@@ -1,74 +0,0 @@
lib mers_libs/gui
// GUI for xrandr, because arandr doesn't let me change the framerates.
// [ WIP ]
base = gui_init()
set_title("MersRandr")
randr_output = run_command("xrandr")
switch! randr_output {
Err(string) {
println(randr_output.noenum())
}
[[]/int string string] {
lines = randr_output.1.regex(".*")
screen_name = ""
screen_resolutions = [["" ["" ...]] ...]
screens = [
[
screen_name
screen_resolutions
]
...]
&screen_resolutions.pop()
&screens.pop()
for line lines {
if line.starts_with("Screen ") {
// ignore
} else if line.starts_with(" ") {
// split at spaces (and ignore +*)
refresh_rates = line.regex("[^ +\\*]+").assume_no_enum()
resolution = &refresh_rates.remove(0).assume1()
print("{0} ::".format(resolution))
for rate refresh_rates {
print(" \"{0}\"".format(rate))
}
&screen_resolutions.push([resolution refresh_rates])
println("")
} else {
index = line.index_of(" ")
switch! index {
int {
if not(screen_name.len().eq(0)) {
&screens.push([screen_name screen_resolutions])
}
screen_resolutions = [ ...]
screen_name = line.substring(0 index)
println("> \"{0}\"".format(screen_name))
}
[] {}
}
}
}
if not(screen_name.len().eq(0)) {
&screens.push([screen_name screen_resolutions])
}
for screen screens {
println(screen.0)
gui_screen = base.gui_add(Row: [])
gui_name = gui_screen.gui_add(Text: screen.0)
for res screen.1 {
gui_resolution = gui_screen.gui_add(Button: res.0)
print(" ")
println(res.0)
for rate res.1 {
print(" ")
println(rate)
}
}
}
}
}

View File

@@ -1,205 +0,0 @@
lib mers_libs/http_requests
lib mers_libs/gui
// MusicDB is a private project of mine.
// Basically, a SBC is hooked up to some speakers.
// It has a database of my songs and can play them.
// It can be controlled through HTTP requests, such as
// p- to stop
// p+ to play
// qi to get the queue index / playback position
// l to list all the songs
// ql or qL to list the queue
// ...
// this mers program should work as a very simple gui to remotely control
// the playback of songs. It should be able to add/remove songs to/from the queue,
// to start/stop playback, and to display some information about the current song.
// the url used to connect to the SBC and use the HTTP api
api_url = "http:\//192.168.2.103:26315/api/raw?"
// start the GUI
base = gui_init()
set_title("Mers MusicDB Remote")
playback_controls = base.gui_add(Row: [])
play_button = playback_controls.gui_add(Button: "Play")
stop_button = playback_controls.gui_add(Button: "Stop")
// these functions abstract away the api interactions
// because they aren't pretty.
// feel free to skip past this section and look at the gui code instead
fn make_api_request(to_api string) {
http_get(api_url.add(to_api))
}
fn get_queue_index() {
r = make_api_request("qi")
switch! r {
string {
r.regex("[0-9]").assume_no_enum().get(0).assume1().parse_int().assume1()
}
// return the error
Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r
}
}
fn get_db_contents() {
// list only 7 = 1 (title) + 2 (artist) + 4 (album)
r = make_api_request("lo7,")
switch! r {
string {
entries = r.regex("#.*:\n.*\n.*\n.*").assume_no_enum()
// initialize the list with a default value
// because mers doesnt know the inner type without it.
db = [[0 "title" "artist" "album"] ...]
&db.remove(0)
for entry entries {
lines = entry.regex(".*")
switch! lines {
[string ...] {
index_line = &lines.get(0).assume1()
index = index_line.substring(1 index_line.len().sub(1)).parse_int().assume1()
title = &lines.get(1).assume1().substring(1)
artist = &lines.get(2).assume1().substring(1)
album = &lines.get(3).assume1().substring(1)
&db.push([index title artist album])
}
Err(string) {
println("invalid response from server; 3u123128731289")
exit(1)
}
}
}
db
}
Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) {
println("couldn't request db from server:")
print(" ")
println(r.to_string())
exit(1)
}
}
}
fn get_queue() {
r = make_api_request("ql")
switch! r {
string {
queue = [0 ...]
&queue.remove(0)
for index r.regex("[0-9]+[ \n]").assume_no_enum() {
&queue.push(index.substring(0 index.len().sub(1)).parse_int().assume1())
}
queue
}
Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) {
println("couldn't request queue from server:")
print(" ")
println(r.to_string())
exit(1)
}
}
}
fn play() {
r = make_api_request("p+")
switch! r {
// success! but nothing to return.
string []
// return the error
Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r
}
}
fn stop() {
r = make_api_request("p-")
switch! r {
// success! but nothing to return.
string []
// return the error
Err(ErrBuildingRequest(string)/ErrGettingResponseText(string)) r
}
}
fn queue_song(song_id int) {
make_api_request("q+{0}".format(song_id.to_string()))
}
// fetch the database contents (a list of songs)
database = get_db_contents()
// this is where all the songs will be displayed.
songs_gui = base.gui_add(Row: [])
queue_list = songs_gui.gui_add(Column: [])
library = songs_gui.gui_add(Column: [])
limit = 0 // set to 0 to disable library length limit
for entry database {
// <SONG> by <ARTIST> on <ALBUM>
song = library.gui_add(Row: [])
song.gui_add(Button: entry.1)
song.gui_add(Text: "by {0} on {1}".format(entry.2 entry.3))
limit = limit.sub(1)
if limit.eq(0) [[]] else []
}
// regularly update the queue
thread(() {
queue_index = get_queue_index().assume_no_enum("if the server isn't reachable, it's ok to crash")
queue_list_inner = queue_list.gui_add(Column: [])
prev_artist = ""
prev_album = ""
for song_id get_queue() {
this_is_playing = if queue_index.eq(0) { queue_index = -1 true } else if queue_index.gt(0) { queue_index = queue_index.sub(1) false } else { false }
song = &database.get(song_id).assume1()
row = queue_list_inner.gui_add(Row: [])
text = if this_is_playing ">> " else ""
text = text.add(song.1)
if prev_artist.eq(song.2) {
if prev_album.eq(song.3) {
} else {
text = text.add("(on {0})".format(song.3))
}
} else {
text = text.add("(by {0} on {1})".format(song.2 song.3))
}
row.gui_add(Text: text)
[]
}
sleep(10)
queue_list_inner.gui_remove()
})
loop {
for event gui_updates() {
switch! event {
ButtonPressed([int ...]) {
e = event.noenum()
println("Pressed button {0}".format(e.to_string()))
match e {
&e.eq(&play_button) {
println("pressed play.")
play()
}
&e.eq(&stop_button) {
println("pressed stop.")
stop()
}
{
// the button is in a row that is in the library,
// so pop()ing twice gets the library path.
// THIS WILL BREAK IF THE GUI LIBRARY SWITCHES TO IDs INSTEAD OF PATHS!
last = &e.pop().assume1()
slast = &e.pop().assume1()
matches = &e.eq(&library)
&e.push(slast)
&e.push(last)
if matches e else []
} {
// the second to last part of the path is the row within library, which is also the index in the db
song = &database.get(&e.get(e.len().sub(2)).assume1()).assume1()
println("Added song \"{0}\" to queue.".format(song.1))
queue_song(song.0)
}
true println("A different button was pressed (unreachable)")
}
}
}
}
[]
}

View File

@@ -3,7 +3,17 @@ type myStruct [
int,
string
]
to give names to the fields, we define functions:
// to give names to the fields, we define functions:
fn count(s myStruct) s.0
// to allow users to change the value, add &myStruct to the valid types for s (only through references can values be changed)
fn note(s myStruct/&myStruct) s.1
my_struct := [12, "test"]
my_struct.count().debug()
my_struct.note().debug()
&my_struct.note() = "changed"
my_struct.note().debug()