Fandom

Foldit Wiki

Lua Export and Import of Scripts

1,465pages on
this wiki
Add New Page
Comment1 Share

Note: This page is mostly out-of-date, but it does contain some interesting ideas about working with the all.macro file.

Foldit has long since added "Import" and "Export" to the recipe editor, meaning you can save your Lua recipes to your computer, work with them using the editor of your choice, and then load them back in to the cookbook. See Editing Foldit Recipes for a full description.

For quick-and-dirty editing, you can also paste text into the Foldit recipe editor window. There's no way to copy a selection from the Foldit recipe editor (it's a really bad editor), but select all (ctrl-a) plus copy (ctrl-c) does work.

There's a suggestion in this article about updating all.macro. The all.macro file now contains a "verify" keyword at the end, which appears to be some kind of digital signature. It's likely that attempts to update all.macro outside of the Foldit client will be foiled by this signature.

Earlier Update Describing Cut-and-Paste MethodEdit

In windows easier way is


  1. open recipe you want export
  2. press ctrl+x - it will cut entire code into clipboard
  3. press ctrl+v to restore script in editor
  4. open your editor (I use n++ or WordPad) and ctrl+v to paste it to editor :)

To use modified version you can:


  1. cut original from foldit, paste modified version, change description and "save as"
  2. create new empty recipe, paste code, save as.

Outdated and Possibly Non-Operational InfoEdit

The following text is for ex- and importing Lua scripts (it could also work on GUI scripts) from all.macro.

Mac/linux directions are now added at the bottom.

This method can work with other OS, but there will be another place where the files are stored.

How to do it:

Things you need:

  1. A text editor (wordpad will work best)
  2. A HEX editor (I recommend WinHEX)
  3. You need to know where Foldit stores its files and the file all.macro


Folders which contain these files are invisible. So you have to tell WINDOWS to show hidden files.
Usually, the file we need is stored in "C:\Documents and settings\all Users\application data\foldit"
If not, try searching it.


Preparation:

Before you start, it will be a great help to find the script quickly,
Open it in Foldit and write some UNIQUE word at the beginning and at the end of the script.
Take something like "mixedpickles", "Kumquat", "artichoke", "rhubarb" ... whatever.
"if", "Print" or "Wiggle" for example would be a very bad choice, because you'll find this everywhere.
I assume we´ve taken "rhubarb" as "keyword".

Save the script as new and leave Foldit. The game needs to be closed completely.
Open the folder containing the file all.macro (as written in 3.), which stores all recipes.
If you've found it, create an extra folder and copy it into this folder.


Trimming the file:
Start the text-editor,

Open your copy of all.macro
Search for "rhubarb" -- you will find something like "script\" : \"rhubarb
Click right behind the word "rhubarb", right to "b", hold shift and press Ctrl-Pos1.
For mouse-lovers, You can also hold Shift, and drag the selection to the top of the whole file.
Press delete key or select "delete"
Search for "rhubarb" again, finding something like \\nrhubarb\"\n \"type\" : \"script
Click right before the word "rhubarb", left to "r", hold shift and press Ctrl-End.
You can also hold Shift, and drag the selection to the end of the whole file.
Delete the selection and save over.


Removing the garbage:

The Option "Show all symbols" (Pilcrow-Symbol, the reversed Double-P) will help, we activate it.
Use "replace" (in the edit tab of your text editor)

Replace all \\\" with "
Replace all \\\, with ,
Replace all \\\# with #

In general, replace every \\\x with x and leave only \\n (You can delete the very first \\n in the beginning)

When you are sure, that you haven't used any \ in the script you can replace all \ by nothing.

Save the file.
Be sure formatting is saved.  (Don't save an unformatted file, because you will destroy the white-space-information, making it hard to read!)
Close it and launch your HEX-editor.

Open the file with the HEX-editor

Use search and replace HEX-Values!
Search for 5C5C6E (five-cee-five-cee-six-ee in words) and replace it with 0D0A (zero-dee-zero-ay in words)

A good program will ask if we want to replace a 3-Bit length term to 2-bit and shorten the file this way. This is what we want! YES!
Because this creates our desired line-feed.

Save the file and open it again with the text edior.

Now, you have got a readable form of your script... for your Text-Editor!
So we are now finished with export.

Now to the Import using Cut-and-Paste
To insert it back into foldit, you have to do the following:
Open you HEX-editor again, search and replace all 0D0A (zero-dee-zero-ay) HEX-Values to just 0A (zero-ay), and save it under another filename.
If you now open it with your editor again, there should be some special symbols, but don't worry about them.
They have to be there for Foldit.


Now Copy the WHOLE text (Ctrl-a, Ctrl-c or mouse)
Relaunch FoldIt, switch to Foldit's cookbook, select new(script)
and press Ctrl-v!

Now you only have to give some information (filename and description) and save it.


Congratulations, you have now exported and imported a script!


Alternatively, if you use Vim, add this to your .vimrc and hit F7 (or just do the regexes):

map <F7> :%s/\\n/\r/g <ENTER> :%s/\\//g <ENTER>

Linux MethodEdit

In Linux, thanks to the developers, ^X/^C/^V has been used successfully to cut/copy/paste to the clipboard.

Mac/linux perl methodsEdit

On the Mac version, cut and paste doesn't work in foldit (yet). However, you can use perl scripts in the Terminal window to change the all.macro file to a text file, and edit the text file in emacs, convert the text file back to all.macro. Then relaunch foldit to pick up the results.

First, find the all.macro file. It might be at a location like: "~/Desktop/Foldit.app/Contents/Resources/all.macro"

If that doesn't work, try this to look for it: find / -name "all.macro" or locate all.macro

Translate from all.macro to text with a perl script like this:

#!/usr/bin/perl
while (<>) {
s/\\\\\\([",#])/$1/g;
s/\\t/ /g;
s/\\r//g;
s/\\n/\n/g;
s/\\//g;
print;
}

Save the perl script to f2t.pl', remember to chmod +x f2t.pl in linux, then run './f2t.pl all.macro > all.macro.txt

You will get an output text file like:

version: 1
{ "Example 1: Basic" : "{
"action-0" : "{
"comment" : "{
"is_defined" : "1"
"name" : "text"


Unfortunately, Reverse-translating the text back to all.macro is much, much trickier. The perl script below reverse-translates most macros correctly (both Lua script and GUI style); when it doesn't work, it leaves out some slashes, and the cookbook responds by just cutting out the one mangled macro.

Comments with "\" or lines with tab or \r have lost those special characters in the translation to text, and they cannot be restored on reverse-translation. But this should not affect macro functionality.

#!/usr/bin/perl
my ($d,$bonus,$open_single_quote,$in_comment)=(0)x4;
my ($s_for_q,$s_for_n);
while (<>) {
  ## Code by jlangsdo (Jack Langsdorf) October 2011

  ## If we are within a section that requires extra slashes, add them.
  my $original_line = $_;
  chomp $original_line;

  if ($d > 0) {
    $s_for_q = "\\" x ((2**($d+$bonus))-1);
    $s_for_n = "\\" x (2**($d-1+$bonus));

    ## Possible special end: when closing a double quoted section, the final double quote and newline
    ## get fewer slashes.
    my $special_end = 0;
    if ($bonus and tr/\"/\"/ %2 == 1 and s/\"\n//) {
      ## Closing "
      $special_end++;
    }

    ## Single quotes are rare and strange. Opening a single quote doubles the slashes only for the newline on this line.
    if (/--\[\[/) { $in_comment = 1; }
    if (/--\]\]/) { $in_comment = 0; }
    if ($bonus and not /--.*\'/ and not $in_comment) {
      if (tr/\'/\'/ == 1) {
    if ($open_single_quote) { $open_single_quote = 0; }
    else { $open_single_quote++; $s_for_n .= $s_for_n; }
      }
      elsif (tr/\'/\'/ %2 == 1) {
    ## In this case, single quotes in the middle get slashes, but not the ones on the ends!
    my ($pre, $middle, $post) = m/^([^\']*\')(.*)(\'[^\']*)$/;
    $middle =~ s/\'/$s_for_q\\\'/g;
    $_ = $pre . $middle . $post;
      }
    }

    ## Standard translation - adding slashes for special characters and \n
    s/([",#])/${s_for_q}$1/g;
    s/\n/${s_for_n}n/; 

    if ($special_end) {
      $bonus = 0;
      $s_for_q = "\\" x ((2**($d+$bonus))-1);
      $s_for_n = "\\" x (2**($d-1+$bonus));
      $_ .= "${s_for_q}\"${s_for_n}n";
    }
   
  } else {
    ## Reset between macros.
    $s_for_n = "";
    $s_for_q = "";
    $bonus = 0;
    $open_single_quote = 0;
    $in_comment = 0;
  }
 
  if ($original_line =~ /^ \"([^\"]+)\" : \"(.*)$/) {
    ## Special translation for main assignment lines
    ## Double quoting for quotes inside of the original quotes!
    my $key = $1;
    my $value = $2;
    $bonus = 0;

    ## Did the value being set close off this line, or does it open up
    ## a new multi-line region ?
    my $suffix = "";
    if ($value =~ s/([\"\{])$//) {
      $suffix = $1;
    }

    $key =~  s/([",#])/${s_for_q}${s_for_q}$1/g;
    $value =~  s/([",#])/${s_for_q}${s_for_q}\\$1/g;
    $_ = " ${s_for_q}\"$key${s_for_q}\" : ${s_for_q}\"$value";
   
    if ($suffix eq "\"") {
      ## Opened and Closed
      $_ .= "${s_for_q}\"";
    } elsif ($suffix) {
      ## Opened with a {
      $_ .= $suffix;
      $_ .= $s_for_n || "\\";
      $d++;
    } else {
      ## Opened with a "
      $bonus = 1;
      $_ .= $s_for_n;
    }
 
    if ($d > 0) { $_ .= "${s_for_n}n"; }
    else { $_ .= "\n"; }
  }
 
  if (not $bonus and $original_line =~ /^}$/) {
    ## Closing }
    $d--;
  }
  print;
}

Back up all.macro first: cp all.macro all.macro.bak

Save the perl script to t2f.pl', remember to chmod +x t2f.pl in linux, then run './f2t.pl all.macro.txt > all.macro

Then relaunch foldit to accept the new all.macro.


Portable Tcl methodEdit

While the tricks mentioned above to clean all.macro up by hand somehow work, they are approximate.

The Tcl script below, f2t.tcl, will convert a pristine all.macro to a correct Tcl representation of the same info. It does so by actually parsing the two or three levels of nested JSON lurking at the heart of that dreadful format (if you think you've seen Quoting Hell, look again). Yeah, it gets rid of all those \\\\\\\, not by wiping them out, but by interpreting them.

As of this writing, the output is just a [source]able Tcl script/data file. By defining an 'entry' Tcl function to output Lua code, one can turn it into an actual GUI-to-Lua converter, letting people do a smooth transition from their legacy cookbook to Lua scripting. Another use is to fix bugs in GUI primitives, by replacing them with handcrafted Lua here and there. 

#! /bin/sh
#\
exec tclsh $0

proc stupidjson txt {
    set in 0
    set out {}
    foreach li [split $txt \n] {
#	puts stderr "JSON-LI:<<<$li>>>"
	if {!$in} {
	    if {[string trim $li]==""} continue
	    if {[info complete $li]} {
		set colon [lindex $li 1]
		if {$colon != ":"} {
		    error "Invalid structure: non-colon: $colon"
		}
	    } else {
		regsub {[""]([^""]*)$} $li "\{\\1" li
		set ac "$li\n"
		set in 1
		continue
	    }
	} else {
	    if {$li=="\""} {
		append ac \}
		set in 0
		set li $ac
	    } else {
		append ac "$li\n"
		continue
	    }
	}
	if {[llength $li]!=3} {
	    error "Invalid structure: non-triplet: $li"
	}
	set val [lindex $li 2]
	if {[string index $val 0]=="\{"} {
#	    puts stderr "RECURS-JSON: <<<[lindex $val 0]>>>"
	    set val [stupidjson [lindex $val 0]]
	} else {
#	    puts stderr "FLAT-JSON: <<<$val>>>"
	}
	set val [subst -nocommand -novariable $val]
	lappend out [lindex $li 0] $val
    }
    if {$in} {error "Unterminated opening quote: $ac"}

    return $out
}



set accu {}

while {[gets stdin line]>=0} {
    append accu $line \n
    if {[info complete $accu]} {
	switch -glob -- $accu {
	    version:* {puts "set version [lindex $accu 1]"}
	    verify:* {}
	    * {
		if {[llength $accu]>1} {
		    error "Invalid structure: multiple words instead of {list}: $accu"
		}
		set l [lindex $accu 0]
		if {[llength $l] % 3} {
		    error "Invalid structure: non-triple-sized list: $l"
		}
		foreach {name colon body} $l {
		    if {$colon != ":"} {
			error "Invalid structure: non-colon: $colon"
		    }
		    set body [subst -nocommand -novariable $body]
		    if {[llength $body]>1} {
			error "Invalid structure: multiple words instead of {list}: $body"
		    }
		    set body [lindex $body 0]
		    set json [stupidjson $body]
		    puts "entry [list $name] [list $json]"
		}
	    }
	}
	set accu {}
    }
}
flush stdout
exit 0

Save the Tcl script to 'f2t.tcl, remember to chmod a+x f2t.tcl in linux, then run './f2t.tcl < all.macro > all.macro.tcl

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.