Execute CopyPasta Language: Difference between revisions
(Added Wren) |
m (→{{header|Phix}}: added syntax colouring the hard way) |
||
Line 778: | Line 778: | ||
If run without command-line parameters it fakes four runs.<br> |
If run without command-line parameters it fakes four runs.<br> |
||
Assumes if clipboard is "hello ", Duplicate 2 should leave it as "hello hello hello ". |
Assumes if clipboard is "hello ", Duplicate 2 should leave it as "hello hello hello ". |
||
<lang Phix> |
<!--<lang Phix>(phixonline)--> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">prog1_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
Copy |
|||
Copy |
|||
Rosetta Code |
|||
Rosetta Code |
|||
Duplicate |
|||
Duplicate |
|||
2 |
|||
2 |
|||
Pasta! |
|||
Pasta! |
|||
La Vista |
|||
La Vista |
|||
""", |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
prog2_cp = """ |
|||
<span style="color: #000000;">prog2_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
CopyFile |
|||
CopyFile |
|||
pasta.txt |
|||
pasta.txt |
|||
Duplicate |
|||
Duplicate |
|||
1 |
|||
1 |
|||
Pasta! |
|||
Pasta! |
|||
""", |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
prog3_cp = """ |
|||
<span style="color: #000000;">prog3_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
Copy |
|||
Copy |
|||
Invalid |
|||
Invalid |
|||
Duplicate |
|||
Duplicate |
|||
1 |
|||
1 |
|||
Goto |
|||
Goto |
|||
3 |
|||
3 |
|||
Pasta! |
|||
Pasta! |
|||
""", |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
pasta_txt = """ |
|||
<span style="color: #000000;">pasta_txt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
I'm the pasta.txt file. |
|||
I'm the pasta.txt file. |
|||
""", |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
fake_files = {"prog1.cp","prog2.cp","prog3.cp","pasta.txt"}, |
|||
<span style="color: #000000;">fake_files</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"prog1.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"prog2.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"prog3.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pasta.txt"</span><span style="color: #0000FF;">},</span> |
|||
fake_texts = { prog1_cp , prog2_cp , prog3_cp , pasta_txt } |
|||
<span style="color: #000000;">fake_texts</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">prog1_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">prog2_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">prog3_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">pasta_txt</span> <span style="color: #0000FF;">}</span> |
|||
function get_file_lines(string filename) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
sequence lines |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> |
|||
integer k = find(filename,fake_files) |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fake_files</span><span style="color: #0000FF;">)</span> |
|||
if k then |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span> <span style="color: #008080;">then</span> |
|||
lines = split(fake_texts[k],"\n") |
|||
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fake_texts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
elsif get_file_type(filename)!=FILETYPE_FILE then |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span> |
|||
crash("file not found:%s",{filename}) |
|||
<span style="color: #008080;">or</span> <span style="color: #7060A8;">get_file_type</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">FILETYPE_FILE</span> <span style="color: #008080;">then</span> |
|||
else |
|||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"file not found:%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span> |
|||
lines = get_text(filename,GT_LF_STRIPPED) |
|||
<span style="color: #008080;">else</span> |
|||
end if |
|||
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">)</span> |
|||
return lines |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end function |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lines</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
procedure interpret(string filename) |
|||
printf(1,"\ninterpret(%s):\n",{filename}) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
sequence pgm = get_file_lines(filename)&{""} |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\ninterpret(%s):\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span> |
|||
string clipboard = "" |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pgm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)&{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}</span> |
|||
integer pc = 1 |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
while true do |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
if pc>=length(pgm) then crash("No Pasta! Sucha mistaka to maka") end if |
|||
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span> |
|||
string cmd = trim(pgm[pc]), arg = pgm[pc+1] |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">pc</span><span style="color: #0000FF;">>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"No Pasta! Sucha mistaka to maka"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
switch cmd do |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">cmd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">]),</span> <span style="color: #000000;">arg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
case "Copy": clipboard &= arg&"\n" |
|||
<span style="color: #008080;">switch</span> <span style="color: #000000;">cmd</span> <span style="color: #008080;">do</span> |
|||
case "CopyFile": clipboard &= join(iff(arg="TheF*ckingCode"?pgm:get_file_lines(arg)),"\n") |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Copy"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">arg</span><span style="color: #0000FF;">&</span><span style="color: #008000;">"\n"</span> |
|||
case "Duplicate": clipboard &= join(repeat(clipboard,to_integer(arg)),"") |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"CopyFile"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"TheF*ckingCode"</span><span style="color: #0000FF;">?</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">:</span><span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">)),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> |
|||
case "Pasta!": puts(1,clipboard); return |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Duplicate"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">clipboard</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">)),</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span> |
|||
case "": pc -= 1; break -- (skip blank lines [w/o arg]) |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Pasta!"</span><span style="color: #0000FF;">:</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">clipboard</span><span style="color: #0000FF;">);</span> <span style="color: #008080;">return</span> |
|||
else crash("unknown command: %s on line %d",{cmd,pc}) |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #008080;">break</span> <span style="color: #000080;font-style:italic;">-- (skip blank lines [w/o arg])</span> |
|||
end switch |
|||
<span style="color: #008080;">else</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"unknown command: %s on line %d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">cmd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">})</span> |
|||
pc += 2 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span> |
|||
end while |
|||
<span style="color: #000000;">pc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">2</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
procedure main() |
|||
sequence cl = command_line() |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
if length(cl)=2 then |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}:</span><span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">())</span> |
|||
for i=1 to 4 do |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> |
|||
try |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> |
|||
interpret(sprintf("prog%d.cp",i)) |
|||
<span style="color: #008080;">try</span> |
|||
<span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"prog%d.cp"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">))</span> |
|||
?e[E_USER] |
|||
<span style="color: #008080;">catch</span> <span style="color: #000000;">e</span> |
|||
end try |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">e</span><span style="color: #0000FF;">[</span><span style="color: #004600;">E_USER</span><span style="color: #0000FF;">]</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">try</span> |
|||
elsif length(cl)=3 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
interpret(cl[3]) |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span> |
|||
else |
|||
<span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">])</span> |
|||
crash("usage: CopyPasta filename") |
|||
<span style="color: #008080;">else</span> |
|||
end if |
|||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"usage: CopyPasta filename"</span><span style="color: #0000FF;">)</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
main()</lang> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<!--</lang>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Revision as of 14:57, 19 May 2021
- Task
Implement a CopyPasta Language interpreter or compiler. These are the commands used by CopyPasta Language:
Command | Description |
---|---|
Copy |
Copy the text of the following line to the clipboard |
CopyFile |
Copy the text of the file cited in the following line to the clipboard or in the case where the next line is TheF*ckingCode copies the code to the clipboard |
Duplicate |
Duplicate the text in the clipboard as many times as the following line specifies |
Pasta! |
Display the clipboard and stop the program |
C++
<lang cpp>#include <fstream>
- include <iostream>
- include <sstream>
- include <streambuf>
- include <string>
- include <stdlib.h>
using namespace std;
// a function to handle fatal errors void fatal_error(string errtext, char *argv[]) { cout << "%" << errtext << endl; cout << "usage: " << argv[0] << " [filename.cp]" << endl; exit(1); }
// functions to trim strings // (http://www.martinbroadhurst.com/how-to-trim-a-stdstring.html) string& ltrim(string& str, const string& chars = "\t\n\v\f\r ") { str.erase(0, str.find_first_not_of(chars)); return str; } string& rtrim(string& str, const string& chars = "\t\n\v\f\r ") { str.erase(str.find_last_not_of(chars) + 1); return str; } string& trim(string& str, const string& chars = "\t\n\v\f\r ") { return ltrim(rtrim(str, chars), chars); }
int main(int argc, char *argv[]) { // get a filename from the command line and read the file in string fname = ""; string source = ""; try { fname = argv[1]; ifstream t(fname);
t.seekg(0, ios::end); source.reserve(t.tellg()); t.seekg(0, ios::beg);
source.assign((istreambuf_iterator<char>(t)), istreambuf_iterator<char>()); } catch(const exception& e) { fatal_error("error while trying to read from specified file", argv); }
// a variable to represent the 'clipboard' string clipboard = "";
// loop over the lines that were read int loc = 0; string remaining = source; string line = ""; string command = ""; stringstream ss; while(remaining.find("\n") != string::npos) { // check which command is on this line line = remaining.substr(0, remaining.find("\n")); command = trim(line); remaining = remaining.substr(remaining.find("\n") + 1);
try { if(line == "Copy") { line = remaining.substr(0, remaining.find("\n")); remaining = remaining.substr(remaining.find("\n") + 1); clipboard += line; } else if(line == "CopyFile") { line = remaining.substr(0, remaining.find("\n")); remaining = remaining.substr(remaining.find("\n") + 1); if(line == "TheF*ckingCode") clipboard += source; else { string filetext = ""; ifstream t(line);
t.seekg(0, ios::end); filetext.reserve(t.tellg()); t.seekg(0, ios::beg);
filetext.assign((istreambuf_iterator<char>(t)), istreambuf_iterator<char>()); clipboard += filetext; } } else if(line == "Duplicate") { line = remaining.substr(0, remaining.find("\n")); remaining = remaining.substr(remaining.find("\n") + 1); int amount = stoi(line); string origClipboard = clipboard; for(int i = 0; i < amount - 1; i++) { clipboard += origClipboard; } } else if(line == "Pasta!") { cout << clipboard << endl; return 0; } else { ss << (loc + 1); fatal_error("unknown command '" + command + "' encounter on line " + ss.str(), argv); } } catch(const exception& e) { ss << (loc + 1); fatal_error("error while executing command '" + command + "' on line " + ss.str(), argv); }
// increment past the command and the next line loc += 2; }
// return in case we never hit a 'Pasta!' statement return 0; }</lang>
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ ./copypasta prog1.cp Rosetta CodeRosetta Code $ ./copypasta prog2.cp I'm the pasta.txt file. $ ./copypasta prog3.cp %unknown command '' encountered on line 5 usage: ./copypasta [filename.cp] $ ./copypasta prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ ./copypasta doesntexist.cp %error while trying to read from specified file usage: ./copypasta [filename.cp]
Go
Here's my tentative attempt at an interpreter for CopyPasta.
I've made the following assumptions:
1. The program to be interpreted is read in from a file whose path is supplied as a command line argument.
2. Writing to the clipboard should always overwrite what (if anything) is already in the clipboard and not append to it.
3. CopyPasta is case sensitive.
4. When writing commands, leading and trailing whitespace should be ignored.
5. Blank commands should be ignored.
6. When a command consumes the following line, that line should not be reprocessed if it is a command itself.
7. The program should terminate with a suitable message if any error is encountered (i.e. no following line, file doesn't exist etc.).
8. When the program is about to end and the contents of the clipboard have (when appropriate) been printed out, the clipboard should be cleared. <lang go>// copypasta.go package main
import (
"fmt" "github.com/atotto/clipboard" "io/ioutil" "log" "os" "runtime" "strconv" "strings"
)
func check(err error) {
if err != nil { clipboard.WriteAll("") // clear clipboard log.Fatal(err) }
}
func interpret(source string) {
source2 := source if runtime.GOOS == "windows" { source2 = strings.ReplaceAll(source, "\r\n", "\n") } lines := strings.Split(source2, "\n") le := len(lines) for i := 0; i < le; i++ { lines[i] = strings.TrimSpace(lines[i]) // ignore leading & trailing whitespace switch lines[i] { case "Copy": if i == le-1 { log.Fatal("There are no lines after the Copy command.") } i++ err := clipboard.WriteAll(lines[i]) check(err) case "CopyFile": if i == le-1 { log.Fatal("There are no lines after the CopyFile command.") } i++ if lines[i] == "TheF*ckingCode" { err := clipboard.WriteAll(source) check(err) } else { bytes, err := ioutil.ReadFile(lines[i]) check(err) err = clipboard.WriteAll(string(bytes)) check(err) } case "Duplicate": if i == le-1 { log.Fatal("There are no lines after the Duplicate command.") } i++ times, err := strconv.Atoi(lines[i]) check(err) if times < 0 { log.Fatal("Can't duplicate text a negative number of times.") } text, err := clipboard.ReadAll() check(err) err = clipboard.WriteAll(strings.Repeat(text, times+1)) check(err) case "Pasta!": text, err := clipboard.ReadAll() check(err) fmt.Println(text) return default: if lines[i] == "" { continue // ignore blank lines } log.Fatal("Unknown command, " + lines[i]) } }
}
func main() {
if len(os.Args) != 2 { log.Fatal("There should be exactly one command line argument, the CopyPasta file path.") } bytes, err := ioutil.ReadFile(os.Args[1]) check(err) interpret(string(bytes)) err = clipboard.WriteAll("") // clear clipboard check(err)
}</lang>
- Output:
The following files have been used for testing:
// prog.cp Copy Rosetta Code Duplicate 2 Pasta! // prog2.cp CopyFile pasta.txt Duplicate 1 Pasta! // prog3.txt Copy Invalid Duplicate 1 Goto 3 Pasta! // pasta.txt I'm the pasta.txt file.
With the following results:
$ go build copypasta.go $ ./copypasta There should be exactly one command line argument, the CopyPasta file path. $ ./copypasta prog4.cp open prog4.cp: no such file or directory $ ./copypasta prog.cp Rosetta CodeRosetta CodeRosetta Code $ ./copypasta prog2.cp I'm the pasta.txt file. I'm the pasta.txt file. $ ./copypasta prog3.cp Unknown command, Goto
Java
<lang Java>import java.io.File; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays;
public class Copypasta { // a function to handle fatal errors public static void fatal_error(String errtext) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); StackTraceElement main = stack[stack.length - 1]; String mainClass = main.getClassName(); System.out.println("%" + errtext); System.out.println("usage: " + mainClass + " [filename.cp]"); System.exit(1); } public static void main(String[] args) { // get a filename from the command line and read the file in String fname = null; String source = null; try { fname = args[0]; source = new String(Files.readAllBytes(new File(fname).toPath())); } catch(Exception e) { fatal_error("error while trying to read from specified file"); }
// convert the source to lines of code ArrayList<String> lines = new ArrayList<String>(Arrays.asList(source.split("\n")));
// a variable to represent the 'clipboard' String clipboard = "";
// loop over the lines that were read int loc = 0; while(loc < lines.size()) { // check which command is on this line String command = lines.get(loc).trim();
try { if(command.equals("Copy")) clipboard += lines.get(loc + 1); else if(command.equals("CopyFile")) { if(lines.get(loc + 1).equals("TheF*ckingCode")) clipboard += source; else { String filetext = new String(Files.readAllBytes(new File(lines.get(loc + 1)).toPath())); clipboard += filetext; } } else if(command.equals("Duplicate")) { String origClipboard = clipboard;
int amount = Integer.parseInt(lines.get(loc + 1)) - 1; for(int i = 0; i < amount; i++) clipboard += origClipboard; } else if(command.equals("Pasta!")) { System.out.println(clipboard); System.exit(0); } else fatal_error("unknown command '" + command + "' encountered on line " + new Integer(loc + 1).toString()); } catch(Exception e) { fatal_error("error while executing command '" + command + "' on line " + new Integer(loc + 1).toString()); }
// increment past the command and the next line loc += 2; } } }</lang>
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ java Copypasta prog1.cp Rosetta CodeRosetta Code $ java Copypasta prog2.cp I'm the pasta.txt file. $ java Copypasta prog3.cp %unknown command '' encountered on line 5 usage: Copypasta [filename.cp] $ java Copypasta prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ java Copypasta doesntexist.cp %error while trying to read from specified file usage: Copypasta [filename.cp]
Julia
<lang julia> function interpretCopyPasta()
clipboard = String[]
if isempty(ARGS) println("Usage: interpretcopypasta <filename>") exit(1) end
thecode = read(ARGS[1], String) codelines = String.(strip.(split(thecode, "\n"))) nextline() = popfirst!(codelines) Copy() = push!(clipboard, nextline())
function CopyFile() txt = nextline() push!(clipboard, txt == "TheF*ckingCode" ? thecode : read(txt, String)) end
function Duplicate() ncopies, txt = parse(Int, nextline()), copy(clipboard) clipboard = foldl(vcat, [txt for _ in 1:ncopies]) end
Pasta!() = (for t in clipboard, x in split(t, "\n") println(x) end; exit(0)) commands = Dict("Copy" => Copy, "CopyFile" => CopyFile, "Duplicate" => Duplicate, "Pasta!" => Pasta!)
while !isempty(codelines) line = nextline() if haskey(commands, line) commands[line]() end end
end
interpretCopyPasta()
</lang>
- Output:
If run on the following CopyPasta "code" file:
Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta!
The output is:
Beginning this run. Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta! Beginning this run. Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta! Ending this run.
Nanoquery
<lang Nanoquery>// a function to handle fatal errors def fatal_error(errtext) println "%" + errtext println "usage: " + args[1] + " [filename.cp]" exit(1) end
// get a filename from the command line and read the file in fname = null source = null try fname = args[2] source = new(Nanoquery.IO.File, fname).readAll() catch fatal_error("error while trying to read from specified file") end
// convert the source to lines of code lines = split(source, "\n")
// a variable to represent the 'clipboard' clipboard = ""
// loop over the lines that were read loc = 0 while (loc < len(lines)) // check which command is on this line command = trim(lines[loc])
try if (command = "Copy") clipboard += lines[loc + 1] else if (command = "CopyFile") if (lines[loc + 1] = "TheF*ckingCode") clipboard += source else filetext = new(Nanoquery.IO.File, lines[loc + 1]).readAll() clipboard += filetext end else if (command = "Duplicate") clipboard += clipboard * ((int(lines[loc + 1])) - 1) else if (command = "Pasta!") println clipboard exit else fatal_error("unknown command '" + command + "' encountered on line " + (loc + 1)) end catch fatal_error("error while executing command '" + command + "' on line " + (loc + 1)) end
// increment past the command and the next line loc += 2 end</lang>
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog1.cp Rosetta CodeRosetta Code $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog2.cp I'm the pasta.txt file. $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog3.cp %unknown command '' encountered on line 5 usage: copypasta.nq [filename.cp] $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq doesntexist.cp %error while trying to read from specified file usage: copypasta.nq [filename.cp]
Perl
<lang perl>use strict; use warnings; use feature 'say'; use Path::Tiny;
sub CopyPasta {
my($code) = @_; my @code = split /\n/, $code =~ s/\s*\n+\s*/\n/gr; return "Program never ends!" unless grep { $_ eq 'Pasta!' } @code;
my @cb; my $PC = 0; while (1) { if ($code[$PC] eq 'Copy') { push @cb, $code[++$PC] } elsif ($code[$PC] eq 'CopyFile') { $PC++; push @cb, join ' ', $code[$PC] eq 'TheF*ckingCode' ? @code : path($code[$PC])->slurp } elsif ($code[$PC] eq 'Duplicate') { @cb = (@cb) x $code[++$PC] } elsif ($code[$PC] eq 'Pasta!') { return @cb } else { return "Does not compute: $code[$PC]" } $PC++; }
}
path('pasta.txt')->spew( "I'm the pasta.txt file.");
for my $prog (
"Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista", "CopyFile\npasta.txt\nDuplicate\n1\nPasta!", "Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!", "CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!", "Copy\nRosetta Code\nDuplicate\n2\n\nPasta"
) {
say for CopyPasta($prog); say ;
}
unlink 'pasta.txt';</lang>
- Output:
Rosetta Code Rosetta Code I'm the pasta.txt file. Does not compute: Goto CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! Program never ends!
Phix
Fakes four files so it can be run w/o any fiddly setup, but will handle (differently-named!) real files as well.
If run without command-line parameters it fakes four runs.
Assumes if clipboard is "hello ", Duplicate 2 should leave it as "hello hello hello ".
constant prog1_cp = """ Copy Rosetta Code Duplicate 2 Pasta! La Vista """, prog2_cp = """ CopyFile pasta.txt Duplicate 1 Pasta! """, prog3_cp = """ Copy Invalid Duplicate 1 Goto 3 Pasta! """, pasta_txt = """ I'm the pasta.txt file. """, fake_files = {"prog1.cp","prog2.cp","prog3.cp","pasta.txt"}, fake_texts = { prog1_cp , prog2_cp , prog3_cp , pasta_txt } function get_file_lines(string filename) sequence lines integer k = find(filename,fake_files) if k then lines = split(fake_texts[k],"\n",false) elsif platform()=JS or get_file_type(filename)!=FILETYPE_FILE then crash("file not found:%s",{filename}) else lines = get_text(filename,GT_LF_STRIPPED) end if return lines end function procedure interpret(string filename) printf(1,"\ninterpret(%s):\n",{filename}) sequence pgm = get_file_lines(filename)&{""} string clipboard = "" integer pc = 1 while true do if pc>=length(pgm) then crash("No Pasta! Sucha mistaka to maka") end if string cmd = trim(pgm[pc]), arg = pgm[pc+1] switch cmd do case "Copy": clipboard &= arg&"\n" case "CopyFile": clipboard &= join(iff(arg="TheF*ckingCode"?pgm:get_file_lines(arg)),"\n") case "Duplicate": clipboard &= join(repeat(clipboard,to_integer(arg)),"") case "Pasta!": puts(1,clipboard); return case "": pc -= 1; break -- (skip blank lines [w/o arg]) else crash("unknown command: %s on line %d",{cmd,pc}) end switch pc += 2 end while end procedure procedure main() sequence cl = iff(platform()=JS?{"",""}:command_line()) if length(cl)=2 then for i=1 to 4 do try interpret(sprintf("prog%d.cp",i)) catch e ?e[E_USER] end try end for elsif length(cl)=3 then interpret(cl[3]) else crash("usage: CopyPasta filename") end if end procedure main()
- Output:
interpret(prog1.cp): Rosetta Code Rosetta Code Rosetta Code interpret(prog2.cp): I'm the pasta.txt file. I'm the pasta.txt file. interpret(prog3.cp): "crash(unknown command: Goto on line 6)" interpret(prog4.cp): "crash(file not found:prog4.cp)"
Python
<lang Python>import sys
- a function to handle fatal errors
def fatal_error(errtext): print("%" + errtext) print("usage: " + sys.argv[0] + " [filename.cp]") sys.exit(1)
- get a filename from the command line and read the file in
fname = None source = None try: fname = sys.argv[1] source = open(fname).read() except: fatal_error("error while trying to read from specified file")
- convert the source to lines of code
lines = source.split("\n")
- a variable to represent the 'clipboard'
clipboard = ""
- loop over the lines that were read
loc = 0 while(loc < len(lines)): # check which command is on this line command = lines[loc].strip()
try: if(command == "Copy"): clipboard += lines[loc + 1] elif(command == "CopyFile"): if(lines[loc + 1] == "TheF*ckingCode"): clipboard += source else: filetext = open(lines[loc+1]).read() clipboard += filetext elif(command == "Duplicate"): clipboard += clipboard * ((int(lines[loc + 1])) - 1) elif(command == "Pasta!"): print(clipboard) sys.exit(0) else: fatal_error("unknown command '" + command + "' encountered on line " + str(loc + 1)) except Exception as e: fatal_error("error while executing command '" + command + "' on line " + str(loc + 1) + ": " + e)
# increment past the command and the next line loc += 2 </lang>
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ python3 copypasta.py prog1.cp Rosetta CodeRosetta Code $ python3 copypasta.py prog2.cp I'm the pasta.txt file. $ python3 copypasta.py prog3.cp %unknown command '' encountered on line 5 usage: copypasta.nq [filename.cp] $ python3 copypasta.py prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ python3 copypasta.py doesntexist.cp %error while trying to read from specified file usage: copypasta.nq [filename.cp]
Raku
(formerly Perl 6) <lang perl6>sub CopyPasta ($code) {
my @code = $code.split("\n")>>.trim.grep: *.so; return "Program never ends!" unless grep { $_ eq 'Pasta!' }, @code;
my @cb; my $PC = 0; loop { given @code[$PC] { when 'Copy' { @cb.push: @code[++$PC] } when 'CopyFile' { $PC++; @cb.push: @code[$PC] eq 'TheF*ckingCode' ?? @code !! slurp @code[$PC] } when 'Duplicate' { @cb = (flat @cb) xx @code[++$PC] } when 'Pasta!' { return @cb } default { return "Does not compute: @code[$PC]" } } $PC++; }
}
spurt 'pasta.txt', "I'm the pasta.txt file.";
(say $_ for .&CopyPasta; say )
for "Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista", "CopyFile\npasta.txt\nDuplicate\n1\nPasta!", "Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!", "CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!", "Copy\nRosetta Code\nDuplicate\n2\n\nPasta";
unlink 'pasta.txt';</lang>
- Output:
Rosetta Code Rosetta Code I'm the pasta.txt file. Does not compute: Goto CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! Program never ends!
Wren
<lang ecmascript>import "os" for Platform, Process import "io" for File
var clipboard = "" // don't have access to real thing
var interpret = Fn.new { |source|
var source2 = source if (Platform.isWindows) source2 = source.replace("\r\n", "\n") var lines = source2.split("\n") var le = lines.count var i = 0 while (i < le) { lines[i] = lines[i].trim() // ignore leading & trailing whitespace if (lines[i] == "Copy") { if (i == le - 1) Fiber.abort("There are no lines after the Copy command.") i = i + 1 clipboard = lines[i] } else if (lines[i] == "CopyFile") { if (i == le - 1) Fiber.abort("There are no lines after the CopyFile command.") i = i + 1 if (lines[i] == "TheF*ckingCode") { clipboard = source } else { var s = File.read(lines[i]) clipboard = s } } else if (lines[i] == "Duplicate") { if (i == le - 1) Fiber.abort("There are no lines after the Duplicate command.") i = i + 1 var times = Num.fromString(lines[i]) if (times < 0) Fiber.abort("Can't duplicate text a negative number of times.") var text = clipboard clipboard = text * (times + 1) } else if (lines[i] == "Pasta!") { var text = clipboard System.print(text) return } else { if (lines[i] == "") { i = i + 1 continue // ignore blank lines } Fiber.abort("Unknown command, %(lines[i])") } i = i + 1 }
}
var args = Process.arguments if (args.count != 1) {
Fiber.abort("There should be exactly one command line argument, the CopyPasta file path.")
} var s = File.read(args[0]) interpret.call(s)</lang>
- Output:
Similar to Go entry.
zkl
<lang zkl>var clipBoard=Data(), srcNm=vm.arglist[0]; pasta:=File(srcNm).read().howza(11); // zkl pastaprog.cp, stripped lines foreach line in (pasta){
switch(line.toLower()){ case("copy"){ clipBoard.clear(next(__lineWalker),"\n") } case("copyfile"){ n:=next(__lineWalker);
if(n=="TheF*ckingCode") clipBoard.clear(pasta); else clipBoard.clear(File(n).read());
} case("duplicate"){ n,t := next(__lineWalker,True), clipBoard.copy();
do(n){ t.append(clipBoard) } // noop if n<1 clipBoard=t;
} case("pasta!"){ print(clipBoard.text); break; } case(""){} else{ error(__lineWalker,"Unknown command: ") } }
} fcn error(w,msg){
println("%s: %d: %s%s".fmt(srcNm, w.n, msg, w.value)); System.exit(1)
} fcn next(w,wantInt=False){
try{ t:=w.next(); if(wantInt) t=t.toInt(); return(t) }catch(TheEnd){ error(w,"Error: End of file: ") } catch{ error(w,wantInt and "Not an int: " or "Error: ") }
}</lang> Input programs:
//////////////prog.cp: Copy Rosetta Code Duplicate 2 Pasta! //////////////prog2.cp: CopyFile pasta.txt Duplicate 1 Pasta! /////////prog3.cp: Copy Invalid Duplicate 1 Goto 3 Pasta! //////////////pasta.txt: I'm the pasta.txt file.
- Output:
$ zkl copyPasta.zkl prog.cp Rosetta Code Rosetta Code Rosetta Code $ zkl copyPasta.zkl prog2.cp I'm the pasta.txt file. I'm the pasta.txt file. $ zkl copyPasta.zkl prog3.cp prog3.cp: 6: Unknown command: Goto