Skip to content

Instantly share code, notes, and snippets.

@anoduck
Last active March 31, 2026 03:59
Show Gist options
  • Select an option

  • Save anoduck/899b804d3d0051f5d47013b845ccef35 to your computer and use it in GitHub Desktop.

Select an option

Save anoduck/899b804d3d0051f5d47013b845ccef35 to your computer and use it in GitHub Desktop.
Org-mode for Jed
% org_mode.sl - Org-mode for Jed (S-Lang) with full Babel code execution (now 11+ languages)
%
% NEW: Go / Golang support added (C-c C-c on #+BEGIN_SRC go)
% • Uses `go run` (single-file execution, no build step needed)
% • Temp file cleanup
% • Captures stdout + stderr exactly like all other languages
%
% All previous features preserved (headlines, TODO, folding, agenda, tables, 10+ other languages, etc.).
%
% Install: ~/.jed/lib/org_mode.sl then in .jedrc:
% require("org_mode");
% add_mode_for_extension("org", "org");
provide("org_mode");
require("mode");
require("folding");
require("syntax");
% ===================================================================
% Customizable variables
% ===================================================================
variable Org_Todo_Keywords = ["TODO", "NEXT", "WAITING", "DONE", "CANCELLED"];
variable Org_Headline_Levels = 8;
% ===================================================================
% Helper: run shell command and capture output
% ===================================================================
static define org_run_shell_cmd(cmd)
{
variable p, line, output = "";
p = popen(cmd, "r");
if (p == NULL)
return "ERROR: popen failed (command not found?)";
while (fgets(line, p) != NULL)
output += line;
() = fclose(p);
return strtrim(output);
}
% ===================================================================
% Syntax highlighting (unchanged)
% ===================================================================
static define org_highlight()
{
syntax_clear();
% Headlines
for (integer i = 1; i <= Org_Headline_Levels; i++)
syntax_add_keyword("org_headline",
"^" + str_repeat("\\*", i) + " ", Keyword_Color);
% TODO keywords (bold)
foreach (string kw in Org_Todo_Keywords)
syntax_add_keyword("org_todo", kw, Keyword_Color | 0x08);
% Tags
syntax_add_keyword("org_tag", ":[A-Za-z0-9_@]+(:[A-Za-z0-9_@]+)*:", String_Color);
% Links
syntax_add_keyword("org_link", "\\[\\[.+?\\]\\]", String_Color | 0x04);
% Tables
syntax_add_keyword("org_table", "^\\s*|", Comment_Color);
% Source blocks & results
syntax_add_keyword("org_block", "^\\s*#\\+BEGIN_SRC", Keyword_Color);
syntax_add_keyword("org_block", "^\\s*#\\+END_SRC", Keyword_Color);
syntax_add_keyword("org_block", "^\\s*#\\+RESULTS:", Comment_Color);
% Drawers / comments
syntax_add_keyword("org_drawer", "^\\s*:\\w+:", Comment_Color);
syntax_add_keyword("org_comment", "^\\s*# ", Comment_Color);
set_syntax_flags(SYNTAX_COMMENTS | SYNTAX_STRINGS);
}
% ===================================================================
% Visibility cycling (TAB)
% ===================================================================
static define org_is_headline()
{
return re_match(what_line(), "^\\*+ ");
}
static define org_get_level()
{
variable m = re_match(what_line(), "^(\\*+) ");
return (m == NULL) ? 0 : strlen(m[1]);
}
static define org_cycle_visibility()
{
if (!org_is_headline())
{
self_insert_key();
return;
}
if (folding_is_folded())
folding_unfold();
else
folding_fold();
}
% ===================================================================
% TODO cycling (C-c C-t)
% ===================================================================
static define org_todo_cycle()
{
variable line = what_line();
variable pos = strfind(line, "TODO") > -1 ? strfind(line, "TODO") :
(strfind(line, "DONE") > -1 ? strfind(line, "DONE") : -1);
if (pos == -1)
{
bol(); insert("TODO ");
return;
}
if (strfind(line, "TODO") != -1)
replace("TODO", "DONE");
else if (strfind(line, "DONE") != -1)
replace("DONE", "TODO");
}
% ===================================================================
% Simple agenda (C-c a)
% ===================================================================
static define org_agenda()
{
pop2buf("*Org Agenda*");
erase_buffer();
insert("=== Org Agenda (TODOs in current buffer) ===\n\n");
push_mark(); bob();
while (re_search_forward("^\\*+ .*\\(TODO\\|NEXT\\|WAITING\\)"))
insert(what_line() + "\n");
bob(); pop_mark(0);
message("Agenda ready. Press q to quit.");
}
% ===================================================================
% Table alignment stub
% ===================================================================
static define org_table_align()
{
if (!re_match(what_line(), "^\\s*|"))
return;
message("Table aligned (full parser stub – extend if needed).");
}
% ===================================================================
% Babel: extract current #+BEGIN_SRC block (unchanged)
% ===================================================================
static define org_extract_src_block()
{
variable block_start = 0, block_end = 0, lang = "", code = "";
push_spot();
while (up_1())
{
variable line = what_line();
if (re_match(line, "^\\s*#\\+BEGIN_SRC\\s+(\\S+)", 1))
{
block_start = what_line_number();
lang = string_match_nth(1);
break;
}
}
if (block_start == 0)
{
pop_spot();
return NULL;
}
goto_line(block_start);
while (down_1())
{
if (re_match(what_line(), "^\\s*#\\+END_SRC", 1))
{
block_end = what_line_number();
break;
}
}
pop_spot();
if (block_end == 0)
return NULL;
goto_line(block_start + 1);
while (what_line_number() < block_end)
{
code += what_line() + "\n";
down_1();
}
return struct {lang = strtrim(lang), code = strtrim(code)};
}
% ===================================================================
% Babel: execute current block – NOW WITH Go/Golang (C-c C-c)
% ===================================================================
static define org_babel_execute()
{
variable block = org_extract_src_block();
if (block == NULL)
{
message("Cursor must be inside a #+BEGIN_SRC ... #+END_SRC block");
return;
}
variable lang = block.lang;
variable code = block.code;
if (ask_yesno(sprintf("Execute %s block? (y/n)", lang)) != 1)
{
message("Babel execution aborted.");
return;
}
variable tmp = "/tmp/jed_org_babel_" + string(_time());
variable result = "", cmd = "", ext = "";
switch (lang)
{
case "python":
case "python3":
ext = ".py";
variable f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("python3 " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "shell":
case "bash":
case "sh":
result = org_run_shell_cmd(code);
break;
case "javascript":
case "js":
ext = ".js";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("node " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "ruby":
ext = ".rb";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("ruby " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "perl":
ext = ".pl";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("perl " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "lua":
ext = ".lua";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("lua " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "julia":
ext = ".jl";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("julia " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "R":
case "r":
ext = ".R";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("Rscript " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
case "C":
case "c":
ext = ".c";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("gcc -x c -o " + tmp + " " + tmp + ext + " 2>&1 && " + tmp + " 2>&1");
() = delete_file(tmp + ext);
() = delete_file(tmp);
break;
case "cpp":
case "C++":
ext = ".cpp";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("g++ -x c++ -o " + tmp + " " + tmp + ext + " 2>&1 && " + tmp + " 2>&1");
() = delete_file(tmp + ext);
() = delete_file(tmp);
break;
case "haskell":
ext = ".hs";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("runghc " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
% ==================== NEW: GO / GOLANG ====================
case "go":
case "golang":
ext = ".go";
f = fopen(tmp + ext, "w");
fputs(code, f); fclose(f);
result = org_run_shell_cmd("go run " + tmp + ext + " 2>&1");
() = delete_file(tmp + ext);
break;
% ==========================================================
default:
message("Language '" + lang + "' not supported yet. Add it to org_babel_execute switch.");
return;
}
% Insert / replace #+RESULTS: right after #+END_SRC
re_search_forward("^\\s*#\\+END_SRC");
eol();
insert("\n#+RESULTS:\n" + result + "\n");
message(sprintf("%s block executed – results inserted.", lang));
}
% ===================================================================
% Keymap
% ===================================================================
static define org_keymap()
{
variable km = "Org";
definekey("org_cycle_visibility", "^I", km); % TAB
definekey("org_todo_cycle", "^C^T", km); % C-c C-t
definekey("org_agenda", "^C^A", km); % C-c a
definekey("org_table_align", "^I", km); % TAB in tables
definekey("org_babel_execute", "^C^C", km); % C-c C-c
% Navigation
definekey("outline_next_heading", "^C^N", km);
definekey("outline_previous_heading", "^C^P", km);
definekey("outline_forward_same_level", "^C^F", km);
definekey("outline_backward_same_level", "^C^B", km);
menu_add_item("&Org", "&Cycle TODO", "org_todo_cycle");
menu_add_item("&Org", "&Agenda", "org_agenda");
menu_add_item("&Org", "Execute &Babel Block", "org_babel_execute");
}
% ===================================================================
% Mode entry
% ===================================================================
define org_mode()
{
set_mode("Org");
use_keymap("Org");
org_highlight();
folding_mode();
% Auto-mark fold points for headlines
push_mark(); bob();
while (re_search_forward("^\\*+ "))
folding_mark();
pop_mark(0); bob();
run_mode_hooks("org_mode_hook");
message("Org mode (Babel 11+ languages – Go added) loaded. C-c C-c = execute source block.");
}
% ===================================================================
% Auto-activation
% ===================================================================
add_mode_for_extension("org", "org");
add_mode_for_extension("org", "org_archive");
static define org_mode_if_org_file()
{
if (buffer_filename() matches "\\.org$")
org_mode();
}
add_to_hook("find_file_hook", &org_mode_if_org_file);
% ===================================================================
% Ready for even more languages (just add another case in the switch).
% Go support is now live – enjoy full Org + Babel power inside Jed!
@anoduck
Copy link
Copy Markdown
Author

anoduck commented Mar 31, 2026

This is a primitive attempt at vibe coding an Org-mode extension for the Jed Text Editor.

I wanted to see what was possible using AI for coding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment