From 18566ed7e85596a26318d8b9b0467b3c7704caf9 Mon Sep 17 00:00:00 2001 From: ayecue Date: Sat, 17 May 2025 15:57:11 +0200 Subject: [PATCH 1/2] add MiniScript support --- .gitmodules | 3 + grammars.yml | 2 + lib/linguist/heuristics.yml | 8 + lib/linguist/languages.yml | 10 + samples/MiniScript/acey-deucey.src | 135 +++++++ samples/MiniScript/countdown.gs | 10 + samples/MiniScript/dogYears.ms | 19 + samples/MiniScript/tetris.ms | 324 +++++++++++++++++ samples/MiniScript/therapist.ms | 334 ++++++++++++++++++ test/test_heuristics.rb | 10 +- vendor/README.md | 1 + vendor/grammars/miniscript-textmate-linguist | 1 + .../miniscript-textmate-linguist.dep.yml | 31 ++ 13 files changed, 887 insertions(+), 1 deletion(-) create mode 100644 samples/MiniScript/acey-deucey.src create mode 100644 samples/MiniScript/countdown.gs create mode 100644 samples/MiniScript/dogYears.ms create mode 100644 samples/MiniScript/tetris.ms create mode 100644 samples/MiniScript/therapist.ms create mode 160000 vendor/grammars/miniscript-textmate-linguist create mode 100644 vendor/licenses/git_submodule/miniscript-textmate-linguist.dep.yml diff --git a/.gitmodules b/.gitmodules index 748e50f5b1..3b04548229 100644 --- a/.gitmodules +++ b/.gitmodules @@ -974,6 +974,9 @@ [submodule "vendor/grammars/metta-textmate-linguist"] path = vendor/grammars/metta-textmate-linguist url = https://github.com/Abigiya-M/metta-textmate-linguist.git +[submodule "vendor/grammars/miniscript-textmate-linguist"] + path = vendor/grammars/miniscript-textmate-linguist + url = https://github.com/ayecue/miniscript-textmate-linguist.git [submodule "vendor/grammars/mint-vscode"] path = vendor/grammars/mint-vscode url = https://github.com/mint-lang/mint-vscode diff --git a/grammars.yml b/grammars.yml index a15a5790af..c998d74130 100644 --- a/grammars.yml +++ b/grammars.yml @@ -925,6 +925,8 @@ vendor/grammars/mercury-tmlanguage: - source.mercury vendor/grammars/metta-textmate-linguist: - source.metta +vendor/grammars/miniscript-textmate-linguist: +- source.ms vendor/grammars/mint-vscode: - source.mint vendor/grammars/mlir-grammar: diff --git a/lib/linguist/heuristics.yml b/lib/linguist/heuristics.yml index c621d3ab4c..d6b42509c3 100644 --- a/lib/linguist/heuristics.yml +++ b/lib/linguist/heuristics.yml @@ -367,6 +367,8 @@ disambiguations: pattern: '^uses (java|gw)\.' - language: Genie pattern: '^\[indent=[0-9]+\]' + - language: MiniScript + pattern: '^\s*\bend (?:function|while|if|for)\b|\s\b(?:isa)\b\s' - extensions: ['.gsc'] rules: - language: GSC @@ -580,6 +582,8 @@ disambiguations: and: - negative_pattern: '/\*' - pattern: '^\s*\.(?:include\s|globa?l\s|[A-Za-z][_A-Za-z0-9]*:)' + - language: MiniScript + pattern: '^\s*\bend (?:function|while|if|for)\b|\s\b(?:isa)\b\s' - language: MAXScript - extensions: ['.msg'] rules: @@ -857,6 +861,10 @@ disambiguations: - language: TSQL pattern: '(?i:^\s*GO\b|BEGIN(\s+TRY|\s+CATCH)|OUTPUT\s+INSERTED|DECLARE\s+@|\[dbo\])' - language: SQL +- extensions: ['.src'] + rules: + - language: MiniScript + pattern: '^\s*\bend (?:function|while|if|for)\b|\s\b(?:isa)\b\s' - extensions: ['.srt'] rules: - language: SubRip Text diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 92b013df81..49f376b798 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -4787,6 +4787,16 @@ MiniD: tm_scope: none ace_mode: text language_id: 231 +MiniScript: + type: programming + color: "#4B4A56" + extensions: + - ".gs" + - ".ms" + - ".src" + tm_scope: source.ms + ace_mode: text + language_id: 704299647 MiniYAML: type: data color: "#ff1111" diff --git a/samples/MiniScript/acey-deucey.src b/samples/MiniScript/acey-deucey.src new file mode 100644 index 0000000000..edf5f6c562 --- /dev/null +++ b/samples/MiniScript/acey-deucey.src @@ -0,0 +1,135 @@ +// Source: https://github.com/JoeStrout/miniscript/blob/master/MiniScript-cpp/demo/acey-deucey.ms +// Acey Deucey card game +// (Text-based version) + +// Define some common stuff that makes this code work both +// in Mini Micro, and in command-line MiniScript. +if version.hostName == "Mini Micro" then + clear + chaChing = file.loadSound("/sys/sounds/cha-ching.wav") + hit = file.loadSound("/sys/sounds/hit.wav") +else + // For command-line MiniScript, make dummy mock-ups + // for the Sound class and our two sounds. + Sound = {} + Sound.play = null + chaChing = new Sound + hit = new Sound +end if + +// Print the welcome message. +print "Welcome to Acey Deucey!" +print "On each round, you ante $2." +print "You are then dealt two cards." +print "Choose how much to bet, then one more card is dealt:" +print " If the new card falls between the first two, you win 2X your bet!" +print " If the new card falls outside the first two, you lose your bet." +print " If the new card matches either of the first two cards exactly, you lose 2X!" +print + +// Initialize our money and card values. +// (We use the Unicode code points for the suit characters.) +money = 100 +cardValues = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "J", "Q", "K"] +suits = [char(9827), char(9830), char(9829), char(9824)] + +// Initialize the deck with all combinations of value and suit. +deck = [] +for cv in cardValues + for suit in suits + deck.push cv + suit + end for +end for +deck.shuffle +discard = [] + +// Function to deal a card from our deck, +// leaving it on the discard pile. +deal = function + if deck.len == 0 then + globals.deck = discard + globals.discard = [] + deck.shuffle + end if + discard.push deck.pop + return discard[-1] +end function + +// Calculate the "rank" of a card. +cardRank = function(card, aceHigh=false) + card = card[0] + if card == "A" then return 1 + 12*aceHigh + return cardValues.indexOf(card) + 1 +end function + +// Get the user's bet. Make sure it's valid. +getBet = function + while true + betStr = input("Enter bet (0 to skip, Q to quit): ").upper + if betStr == "Q" then return betStr + if val(betStr) < 0 then + print "A negative bet? Nice try!" + else if val(betStr) > money then + print "You only have $" + money + "." + else + return betStr + end if + end while +end function + +// Main loop. +while money > 2 + globals.money = money - 2 + print + print "You have $" + money + "." + wait + card1 = deal + rank1 = cardRank(card1, false) + card2 = deal + rank2 = cardRank(card2, true) + print " Card 1: " + card1 + " (Rank: " + rank1 + ")" + wait 0.5 + print " Card 2: " + card2 + " (Rank: " + rank2 + ")" + wait 0.5 + if rank1 == rank2 then + print "Matched pair: ante lost." + wait + continue + end if + + betStr = getBet + if betStr == "Q" then break + bet = val(betStr) + if bet <= 0 then + print "Chicken!" + continue + end if + card3 = deal + rank3 = cardRank(card3) + print " Card 3: " + card3 + " (Rank: " + rank3 + ")" + wait + if rank3 == rank1 or rank3 == rank2 then + print "Ohhh! Double loss!" + hit.play + globals.money = money - bet * 2 + else if rank3 < rank1 and rank3 < rank2 then + print "Too low!" + globals.money = money - bet + else if rank3 > rank1 and rank3 > rank2 then + print "Too high!" + globals.money = money - bet + else + print "You win!" + chaChing.play + globals.money = money + bet + end if + wait +end while + +// Print the result. +if money == 0 then print "You are totally broke." +if money > 0 then print "You end the day with $" + money + "." +if money < 0 then print "You owe the bank $" + (-money) + "!" +print "Thanks for playing!" + + diff --git a/samples/MiniScript/countdown.gs b/samples/MiniScript/countdown.gs new file mode 100644 index 0000000000..e77a0a19d6 --- /dev/null +++ b/samples/MiniScript/countdown.gs @@ -0,0 +1,10 @@ +// Source: https://github.com/JoeStrout/miniscript/blob/master/MiniScript-cpp/demo/countdown.ms +// Countdown +// This is the tiniest Mini Micro demo. +// It shows basic looping, plus use of range, print, and wait. + +for i in range(10,1) + print i + "..." + wait +end for +print "BLASTOFF!" diff --git a/samples/MiniScript/dogYears.ms b/samples/MiniScript/dogYears.ms new file mode 100644 index 0000000000..57d3c9efa4 --- /dev/null +++ b/samples/MiniScript/dogYears.ms @@ -0,0 +1,19 @@ +// Source: https://github.com/JoeStrout/miniscript/blob/master/MiniScript-cpp/demo/dogYears.ms +// Dog Years +// +// Simple demo of input, print, while, if/else, and break. +// + +while true + ageStr = input("Enter your age: ") + age = val(ageStr) + if age == 0 then + print "C'mon, don't be shy..." + else if age < 3 then + print "So young! Really? I don't think so..." + else + print "That's " + age*7 + " in dog years." + if age > 30 then print "Wow, you're old!" + break // (exits the "while" loop) + end if +end while diff --git a/samples/MiniScript/tetris.ms b/samples/MiniScript/tetris.ms new file mode 100644 index 0000000000..13edf82fc4 --- /dev/null +++ b/samples/MiniScript/tetris.ms @@ -0,0 +1,324 @@ +// Source: https://github.com/JoeStrout/miniscript/blob/master/MiniScript-cpp/demo/tetris.ms +// TETRIS +// This demo uses `key.available()` and `key.get()` + +import "vt" + +delay = 0.5 +delaySub = 0.01 +fieldHeight = 20 +fieldWidth = 10 +fieldLeft = 20 +fieldColor = vt.color.black +kUp = char(19) +kDown = char(20) +kRight = char(18) +kLeft = char(17) +anchorRow = fieldHeight + 2 +gameOverFG = vt.color.white +gameOverBG = vt.color.teal + +cell = {} +cell.empty = null +cell.I = vt.color.aqua +cell.O = vt.color.yellow +cell.T = vt.color.fuchsia +cell.L = vt.color.orange +cell.J = vt.color.blue +cell.S = vt.color.lime +cell.Z = vt.color.red +_cell = cell + +field = [] +shape = null + +initField = function + globals.field = [] + for r in range(0, fieldHeight - 1, 1) + field.push [] + for c in range(0, fieldWidth - 1, 1) + field[-1].push _cell.empty + end for + end for +end function + +drawField = function + for r in range(0, fieldHeight - 1, 1) + print vt.cursor.goto(r + 1, fieldLeft - 1) + vt.backColor(fieldColor) + "|", "" + for c in range(0, fieldWidth - 1, 1) + print vt.backColor(field[r][c]) + " ", "" + end for + print vt.backColor(fieldColor) + "|" + end for + print vt.cursor.goto(fieldHeight + 1, fieldLeft - 1) + vt.backColor(fieldColor) + "+" + "-" * fieldWidth * 2 + "+" + print vt.cursor.goto(anchorRow, 1) +end function + +drawGameOver = function + print vt.cursor.goto(10, fieldLeft) + vt.textColor(gameOverFG) + vt.backColor(gameOverBG) + " G A M E " + print vt.cursor.goto(11, fieldLeft) + vt.textColor(gameOverFG) + vt.backColor(gameOverBG) + " O V E R " + print vt.cursor.goto(anchorRow, 1) +end function + +initShape = function + f = [@initI, + @initO, + @initT, + @initL, + @initJ, + @initS, + @initZ][rnd * 7] + s = f + for cell in s.cells + if field[cell.row][cell.col] != _cell.empty then return null + end for + return s +end function + +initI = function + s = {} + s.cells = [] + s.cells.push {"row": 0, "col": 3, "color": _cell.I} + s.cells.push {"row": 0, "col": 4, "color": _cell.I} + s.cells.push {"row": 0, "col": 5, "color": _cell.I} + s.cells.push {"row": 0, "col": 6, "color": _cell.I} + s.centerRow = 0 + s.centerCol = 4 + return s +end function + +initO = function + s = {} + s.cells = [] + s.cells.push {"row": 0, "col": 4, "color": _cell.O} + s.cells.push {"row": 0, "col": 5, "color": _cell.O} + s.cells.push {"row": 1, "col": 5, "color": _cell.O} + s.cells.push {"row": 1, "col": 4, "color": _cell.O} + s.centerRow = 0.5 + s.centerCol = 4.5 + return s +end function + +initT = function + s = {} + s.cells = [] + s.cells.push {"row": 0, "col": 3, "color": _cell.T} + s.cells.push {"row": 0, "col": 4, "color": _cell.T} + s.cells.push {"row": 0, "col": 5, "color": _cell.T} + s.cells.push {"row": 1, "col": 4, "color": _cell.T} + s.centerRow = 0 + s.centerCol = 4 + return s +end function + +initL = function + s = {} + s.cells = [] + s.cells.push {"row": 1, "col": 4, "color": _cell.L} + s.cells.push {"row": 0, "col": 4, "color": _cell.L} + s.cells.push {"row": 0, "col": 5, "color": _cell.L} + s.cells.push {"row": 0, "col": 6, "color": _cell.L} + s.centerRow = 0.5 + s.centerCol = 4.5 + return s +end function + +initJ = function + s = {} + s.cells = [] + s.cells.push {"row": 0, "col": 3, "color": _cell.J} + s.cells.push {"row": 0, "col": 4, "color": _cell.J} + s.cells.push {"row": 0, "col": 5, "color": _cell.J} + s.cells.push {"row": 1, "col": 5, "color": _cell.J} + s.centerRow = 0.5 + s.centerCol = 4.5 + return s +end function + +initS = function + s = {} + s.cells = [] + s.cells.push {"row": 1, "col": 3, "color": _cell.S} + s.cells.push {"row": 1, "col": 4, "color": _cell.S} + s.cells.push {"row": 0, "col": 4, "color": _cell.S} + s.cells.push {"row": 0, "col": 5, "color": _cell.S} + s.centerRow = 0.5 + s.centerCol = 4.5 + return s +end function + +initZ = function + s = {} + s.cells = [] + s.cells.push {"row": 0, "col": 4, "color": _cell.Z} + s.cells.push {"row": 0, "col": 5, "color": _cell.Z} + s.cells.push {"row": 1, "col": 5, "color": _cell.Z} + s.cells.push {"row": 1, "col": 6, "color": _cell.Z} + s.centerRow = 0.5 + s.centerCol = 4.5 + return s +end function + +drawShape = function(s) + for cell in s.cells + print vt.cursor.goto(cell.row + 1, fieldLeft + cell.col * 2) + vt.backColor(cell.color) + " " + end for + print vt.cursor.goto(anchorRow, 1) +end function + +eraseShape = function(s) + for cell in s.cells + print vt.cursor.goto(cell.row + 1, fieldLeft + cell.col * 2) + vt.backColor(fieldColor) + " " + end for + print vt.cursor.goto(anchorRow, 1) +end function + +absorbShape = function(s) + for cell in s.cells + field[cell.row][cell.col] = cell.color + end for +end function + +cloneShape = function(s) + s2 = {} + s2.cells = [] + for cell in s.cells + s2.cells.push cell + {} + end for + s2.centerRow = s.centerRow + s2.centerCol = s.centerCol + return s2 +end function + +moveDown = function(s) + s2 = cloneShape(s) + for cell in s2.cells + cell.row += 1 + if cell.row >= fieldHeight then return null + if field[cell.row][cell.col] != _cell.empty then return null + end for + s2.centerRow += 1 + return s2 +end function + +moveLeft = function(s) + s2 = cloneShape(s) + for cell in s2.cells + cell.col -= 1 + if cell.col < 0 then return null + if field[cell.row][cell.col] != _cell.empty then return null + end for + s2.centerCol -= 1 + return s2 +end function + +moveRight = function(s) + s2 = cloneShape(s) + for cell in s2.cells + cell.col += 1 + if cell.col >= fieldWidth then return null + if field[cell.row][cell.col] != _cell.empty then return null + end for + s2.centerCol += 1 + return s2 +end function + +fall = function(s) + s2 = cloneShape(s) + while true + moved = moveDown(s2) + if moved == null then return s2 + s2 = moved + end while +end function + +rotate = function(s) + s2 = cloneShape(s) + crossedLeftP = false + crossedRightP = false + for cell in s2.cells + r = cell.row + c = cell.col + cell.row = s2.centerRow + (c - s2.centerCol) + cell.col = s2.centerCol - (r - s2.centerRow) + if cell.col < 0 then crossedLeftP = true + if cell.col >= fieldWidth then crossedRightP = true + if cell.row >= fieldHeight then return null + if field[cell.row][cell.col] != _cell.empty then return null + end for + if crossedLeftP then s2 = moveRight(s2) + if crossedRightP then s2 = moveLeft(s2) + return s2 +end function + +deleteRows = function + for i in range(0, fieldHeight - 1, 1) + nNulls = 0 + for cell in field[i] + if cell == _cell.empty then nNulls += 1 + end for + if nNulls == 0 then + emptyRow = [] + for j in range(0, fieldWidth - 1, 1) + emptyRow.push _cell.empty + end for + outer.field = [emptyRow] + field[:i] + field[i + 1:] + outer.delay -= delaySub + end if + end for +end function + + +initField +drawField +key._echo = false +t = time +while true + yield + + if shape == null then + shape = initShape + if shape == null then + drawGameOver + key._echo = true + exit + end if + drawShape shape + end if + + s = shape + moved = null + while key.available + k = key.get + if k == kUp then + moved = rotate(s) + else if k == kDown then + moved = fall(s) + else if k == kLeft then + moved = moveLeft(s) + else if k == kRight then + moved = moveRight(s) + end if + if moved != null then s = moved + end while + + if time > t then + t = time + delay + moved = moveDown(s) + if moved == null then + absorbShape s + deleteRows + drawField + shape = null + s = null + else + s = moved + end if + end if + + if s != shape then + eraseShape shape + drawShape s + shape = s + end if +end while diff --git a/samples/MiniScript/therapist.ms b/samples/MiniScript/therapist.ms new file mode 100644 index 0000000000..14812c1e71 --- /dev/null +++ b/samples/MiniScript/therapist.ms @@ -0,0 +1,334 @@ +// Source: https://github.com/JoeStrout/miniscript/blob/master/MiniScript-cpp/demo/therapist.ms +// Therapist +// a cheezy little Eliza knock-off by Joe Strout +// with some updates by Jeff Epler +// hacked into a module and updated by Jez Higgins +// and finally translated from Python into MiniScript by Joe Strout :) + +import "vt" + +//---------------------------------------------------------------------- +// respond: take a string, a set of regexps, and a corresponding +// set of response lists; find a match, and return a randomly +// chosen response from the corresponding list. +//---------------------------------------------------------------------- +respond = function(s) + // find a match among our patterns + for kv in gPats + match = patMatch(kv[0], s) + if match == null then continue + // Found a match... stuff with corresponding value + // chosen randomly from among the available options + resp = kv[1][rnd * kv[1].len] + // now we have a response; stuff in reflected text where indicated + for i in match.indexes + resp = resp.replace("%"+(i+1), translate(match[i], gReflections)) + end for + resp = resp[0].upper + resp[1:] + return resp + end for +end function + +//---------------------------------------------------------------------- +// translate: take a string, replace any words found in dict.keys() +// with the corresponding dict.values() +//---------------------------------------------------------------------- +translate = function(s, dict) + words = s.split + for i in words.indexes + w = words[i].lower + if dict.hasIndex(w) then words[i] = dict[w] + end for + return words.join +end function + + +//---------------------------------------------------------------------- +// patmatch: Match a given pattern like "Hello *!" against a string +// like "Hello world", and return null if no match, or a list of +// the text that fits into the wildcards, like ["world"]. +//---------------------------------------------------------------------- +patMatch = function(pat, s, wildcard="(.*)") + result = [] + pos = 0 + literals = pat.split(wildcard) + for i in literals.indexes + lit = literals[i] + if s[pos:pos+lit.len] != lit then return null + if i == literals.len-1 then return result + pos = pos + lit.len + if i == literals.len-2 and literals[-1] == "" then + // special case: match to end of line + result.push s[pos:] + return result + end if + nextpos = s.indexOf(literals[i+1], pos) + if nextpos == null then return null + result.push s[pos:nextpos] + pos = nextpos + end for + return result +end function + +//---------------------------------------------------------------------- +// gReflections, a translation table used to convert things you say +// into things the computer says back, e.g. "I am" --> "you are" +//---------------------------------------------------------------------- +gReflections = { +"am" : "are", +"was" : "were", +"i" : "you", +"i'd" : "you would", +"i've" : "you have", +"i'll" : "you will", +"i'm" : "you're", +"my" : "your", +"are" : "am", +"you've": "I have", +"you'll": "I will", +"your" : "my", +"you're": "I'm", +"yours" : "mine", +"you" : "me", +"me" : "you" } + +//---------------------------------------------------------------------- +// gPats, the main response table. Each element of the list is a +// two-element list; the first is an input pattern, and the second is a +// list of possible responses, with group-macros labelled as +// %1, %2, etc. +//---------------------------------------------------------------------- +gPats = [ + ["I need (.*)", + [ "Why do you need %1?", + "Would it really help you to get %1?", + "Are you sure you need %1?"]], + + ["Why don't you (.*)?", + [ "Do you really think I don't %1?", + "Perhaps eventually I will %1.", + "Do you really want me to %1?"]], + + ["Why can't I (.*)?", + [ "Do you think you should be able to %1?", + "If you could %1, what would you do?", + "I don't know -- why can't you %1?", + "Have you really tried?"]], + + ["I can't (.*)", + [ "How do you know you can't %1?", + "Perhaps you could %1 if you tried.", + "What would it take for you to %1?", + "Not with THAT attitude.", + "Are you sure you can't %1?", + "What would you do if you could %1?", + "Do you think others could %1?", + "Have you tried to %1?"]], + + ["I am (.*)", + [ "Did you come to me because you are %1?", + "How long have you been %1?", + "How do you feel about being %1?"]], + + ["I'm (.*)", + [ "How does being %1 make you feel?", + "Do you enjoy being %1?", + "Why do you tell me you're %1?", + "Why do you think you're %1?"]], + + ["Are you (.*)?", + [ "Why does it matter whether I am %1?", + "Would you prefer it if I were not %1?", + "Perhaps you believe I am %1.", + "I may be %1 -- what do you think?"]], + + ["What (.*)", + [ "Why do you ask?", + "How would an answer to that help you?", + "What do you think?"]], + + ["How (.*)", + [ "How do you suppose?", + "Perhaps you can answer your own question.", + "What is it you're really asking?"]], + + ["Because (.*)", + [ "Is that the real reason?", + "What other reasons come to mind?", + "Does that reason apply to anything else?", + "If %1, what else must be true?"]], + + ["(.*) sorry (.*)", + [ "There are many times when no apology is needed.", + "What feelings do you have when you apologize?"]], + + ["Hello(.*)", + [ "Hello... I'm glad you could drop by today.", + "Hi there... how are you today?", + "Hello, how are you feeling today?"]], + + ["I think (.*)", + [ "Do you doubt %1?", + "Do you really think so?", + "But you're not sure %1?"]], + + ["(.*) friend (.*)", + [ "Tell me more about your friends.", + "When you think of a friend, what comes to mind?", + "Why don't you tell me about a childhood friend?"]], + + ["Yes", + [ "You seem quite sure.", + "OK, but can you elaborate a bit?"]], + + ["(.*) computer(.*)", + [ "Are you really talking about me?", + "Does it seem strange to talk to a computer?", + "How do computers make you feel?", + "Do you feel threatened by computers?"]], + + ["Is it (.*)", + [ "Do you think it is %1?", + "Perhaps it's %1 -- what do you think?", + "If it were %1, what would you do?", + "It could well be that %1."]], + + ["It is (.*)", + [ "You seem very certain.", + "If I told you that it probably isn't %1, what would you feel?"]], + + ["Can you (.*)?", + [ "What makes you think I can't %1?", + "If I could %1, then what?", + "Why do you ask if I can %1?"]], + + ["Can I (.*)?", + [ "Perhaps you don't want to %1.", + "Do you want to be able to %1?", + "If you could %1, would you?"]], + + ["You are (.*)", + [ "Why do you think I am %1?", + "Does it please you to think that I'm %1?", + "Perhaps you would like me to be %1.", + "Perhaps you're really talking about yourself?"]], + + ["You're (.*)", + [ "Why do you say I am %1?", + "Why do you think I am %1?", + "Are we talking about you, or me?"]], + + ["I don't (.*)", + [ "Don't you really %1?", + "Why don't you %1?", + "Do you want to %1?"]], + + ["I feel (.*)", + [ "Good, tell me more about these feelings.", + "Do you often feel %1?", + "When do you usually feel %1?", + "When you feel %1, what do you do?"]], + + ["I have (.*)", + [ "Why do you tell me that you've %1?", + "Have you really %1?", + "Now that you have %1, what will you do next?"]], + + ["I would (.*)", + [ "Could you explain why you would %1?", + "Why would you %1?", + "Who else knows that you would %1?"]], + + ["Is there (.*)", + [ "Do you think there is %1?", + "It's likely that there is %1.", + "Would you like there to be %1?"]], + + ["My (.*)", + [ "I see, your %1.", + "Why do you say that your %1?", + "When your %1, how do you feel?"]], + + ["You (.*)", + [ "We should be discussing you, not me.", + "Why do you say that about me?", + "Why do you care whether I %1?"]], + + ["Why (.*)", + [ "Why don't you tell me the reason why %1?", + "Why do you think %1?" ]], + + ["I want (.*)", + [ "What would it mean to you if you got %1?", + "Why do you want %1?", + "What would you do if you got %1?", + "If you got %1, then what would you do?"]], + + ["(.*) mother(.*)", + [ "Tell me more about your mother.", + "What was your relationship with your mother like?", + "How do you feel about your mother?", + "How does this relate to your feelings today?", + "Good family relations are important."]], + + ["(.*) father(.*)", + [ "Tell me more about your father.", + "How did your father make you feel?", + "How do you feel about your father?", + "Does your relationship with your father relate to your feelings today?", + "Do you have trouble showing affection with your family?"]], + + ["(.*) child(.*)", + [ "Did you have close friends as a child?", + "What is your favorite childhood memory?", + "Do you remember any dreams or nightmares from childhood?", + "Did the other children sometimes tease you?", + "How do you think your childhood experiences relate to your feelings today?"]], + + ["(.*)?", + [ "Why do you ask that?", + "Please consider whether you can answer your own question.", + "Perhaps the answer lies within yourself?", + "Why don't you tell me?"]], + + ["quit", + [ "Thank you for talking with me.", + "Good-bye.", + "Thank you, that will be $150. Have a good day!"]], + + ["(.*)", + [ "Please tell me more.", + "Let's change focus a bit... Tell me about your family.", + "Can you elaborate on that?", + "Why do you say that %1?", + "I see.", + "Very interesting.", + "%1.", + "I see. And what does that tell you?", + "How does that make you feel?", + "How do you feel when you say that?"]] ] + + +runInteractive = function + print vt.clear + vt.reset + vt.normal + print "Therapist" + char(13) + "---------" + print "Talk to the program by typing in plain English, using normal upper-" + print "and lower-case letters and punctuation. Enter ""quit"" when done." + print "=" * 68 + print "Hello. How are you feeling today?" + + while true + print vt.textColor(vt.color.gray), "" + s = input("> ") + while s and (s[-1] == "!" or s[-1] == ".") + s = s[:-1] + end while + print vt.normal + print respond(s) + if s.lower == "quit" then break + end while +end function + +if locals == globals then + runInteractive +end if diff --git a/test/test_heuristics.rb b/test/test_heuristics.rb index f708d0fac5..e0e0501af2 100755 --- a/test/test_heuristics.rb +++ b/test/test_heuristics.rb @@ -531,6 +531,7 @@ def test_gs_by_heuristics "GLSL" => all_fixtures("GLSL", "*.gs"), "Genie" => all_fixtures("Genie", "*.gs") - ambiguous, "Gosu" => all_fixtures("Gosu", "*.gs"), + "MiniScript" => all_fixtures("MiniScript", "*.gs"), }) assert_heuristics({ nil => all_fixtures("JavaScript") @@ -773,7 +774,8 @@ def test_ms_by_heuristics assert_heuristics({ "Roff" => all_fixtures("Roff", "*.ms"), "Unix Assembly" => all_fixtures("Unix Assembly", "*.ms"), - "MAXScript" => all_fixtures("MAXScript", "*.ms") + "MAXScript" => all_fixtures("MAXScript", "*.ms"), + "MiniScript" => all_fixtures("MiniScript", "*.ms"), }) end @@ -1045,6 +1047,12 @@ def test_sql_by_heuristics }) end + def test_src_by_heuristics + assert_heuristics({ + "MiniScript" => all_fixtures("MiniScript", "*.src") + }) + end + def test_srt_by_heuristics assert_heuristics({ "SubRip Text" => all_fixtures("SubRip Text", "*.srt") diff --git a/vendor/README.md b/vendor/README.md index 44de308f78..da2711e862 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -393,6 +393,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting - **Meson:** [TingPing/language-meson](https://github.com/TingPing/language-meson) - **Metal:** [mikomikotaishi/c.tmbundle](https://github.com/mikomikotaishi/c.tmbundle) - **Microsoft Visual Studio Solution:** [Nixinova/NovaGrammars](https://github.com/Nixinova/NovaGrammars) +- **MiniScript:** [ayecue/miniscript-textmate-linguist](https://github.com/ayecue/miniscript-textmate-linguist) - **MiniYAML:** [OpenRA/atom-miniyaml](https://github.com/OpenRA/atom-miniyaml) - **MiniZinc:** [Dekker1/vscode-minizinc](https://github.com/Dekker1/vscode-minizinc) - **MiniZinc Data:** [Dekker1/vscode-minizinc](https://github.com/Dekker1/vscode-minizinc) diff --git a/vendor/grammars/miniscript-textmate-linguist b/vendor/grammars/miniscript-textmate-linguist new file mode 160000 index 0000000000..4c5b001e8f --- /dev/null +++ b/vendor/grammars/miniscript-textmate-linguist @@ -0,0 +1 @@ +Subproject commit 4c5b001e8f8adf0b31aadf48ea0b6fd0529799af diff --git a/vendor/licenses/git_submodule/miniscript-textmate-linguist.dep.yml b/vendor/licenses/git_submodule/miniscript-textmate-linguist.dep.yml new file mode 100644 index 0000000000..d41d3be7c1 --- /dev/null +++ b/vendor/licenses/git_submodule/miniscript-textmate-linguist.dep.yml @@ -0,0 +1,31 @@ +--- +name: miniscript-textmate-linguist +version: 4c5b001e8f8adf0b31aadf48ea0b6fd0529799af +type: git_submodule +homepage: https://github.com/ayecue/miniscript-textmate-linguist.git +license: mit +licenses: +- sources: LICENSE + text: | + MIT License + + Copyright (c) 2025 ayecue + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +notices: [] From faa42ed9ad5e681d0890c3f86796c343f6f00c50 Mon Sep 17 00:00:00 2001 From: ayecue Date: Wed, 21 May 2025 16:32:14 +0200 Subject: [PATCH 2/2] remove additional extensions --- lib/linguist/heuristics.yml | 6 ------ lib/linguist/languages.yml | 2 -- samples/MiniScript/{acey-deucey.src => acey-deucey.ms} | 0 samples/MiniScript/{countdown.gs => countdown.ms} | 0 test/test_heuristics.rb | 7 ------- 5 files changed, 15 deletions(-) rename samples/MiniScript/{acey-deucey.src => acey-deucey.ms} (100%) rename samples/MiniScript/{countdown.gs => countdown.ms} (100%) diff --git a/lib/linguist/heuristics.yml b/lib/linguist/heuristics.yml index d6b42509c3..399ea59a57 100644 --- a/lib/linguist/heuristics.yml +++ b/lib/linguist/heuristics.yml @@ -367,8 +367,6 @@ disambiguations: pattern: '^uses (java|gw)\.' - language: Genie pattern: '^\[indent=[0-9]+\]' - - language: MiniScript - pattern: '^\s*\bend (?:function|while|if|for)\b|\s\b(?:isa)\b\s' - extensions: ['.gsc'] rules: - language: GSC @@ -861,10 +859,6 @@ disambiguations: - language: TSQL pattern: '(?i:^\s*GO\b|BEGIN(\s+TRY|\s+CATCH)|OUTPUT\s+INSERTED|DECLARE\s+@|\[dbo\])' - language: SQL -- extensions: ['.src'] - rules: - - language: MiniScript - pattern: '^\s*\bend (?:function|while|if|for)\b|\s\b(?:isa)\b\s' - extensions: ['.srt'] rules: - language: SubRip Text diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 49f376b798..3bb791897c 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -4791,9 +4791,7 @@ MiniScript: type: programming color: "#4B4A56" extensions: - - ".gs" - ".ms" - - ".src" tm_scope: source.ms ace_mode: text language_id: 704299647 diff --git a/samples/MiniScript/acey-deucey.src b/samples/MiniScript/acey-deucey.ms similarity index 100% rename from samples/MiniScript/acey-deucey.src rename to samples/MiniScript/acey-deucey.ms diff --git a/samples/MiniScript/countdown.gs b/samples/MiniScript/countdown.ms similarity index 100% rename from samples/MiniScript/countdown.gs rename to samples/MiniScript/countdown.ms diff --git a/test/test_heuristics.rb b/test/test_heuristics.rb index e0e0501af2..cef2964cd9 100755 --- a/test/test_heuristics.rb +++ b/test/test_heuristics.rb @@ -531,7 +531,6 @@ def test_gs_by_heuristics "GLSL" => all_fixtures("GLSL", "*.gs"), "Genie" => all_fixtures("Genie", "*.gs") - ambiguous, "Gosu" => all_fixtures("Gosu", "*.gs"), - "MiniScript" => all_fixtures("MiniScript", "*.gs"), }) assert_heuristics({ nil => all_fixtures("JavaScript") @@ -1047,12 +1046,6 @@ def test_sql_by_heuristics }) end - def test_src_by_heuristics - assert_heuristics({ - "MiniScript" => all_fixtures("MiniScript", "*.src") - }) - end - def test_srt_by_heuristics assert_heuristics({ "SubRip Text" => all_fixtures("SubRip Text", "*.srt")