Repository: ihdavids/orgextended Branch: master Commit: 3e84ceadcd5a Files: 273 Total size: 1.7 MB Directory structure: gitextract_ivyc_bf5/ ├── .gitattributes ├── .github/ │ └── ISSUE_TEMPLATE/ │ └── bug_report.md ├── .python-version ├── Default.sublime-keymap ├── Indentation Rules.tmPreferences ├── LICENSE ├── Main.sublime-menu ├── OrgBeancount.sublime-settings ├── OrgBeancount.sublime-syntax ├── OrgExtended-Light.sublime-color-scheme ├── OrgExtended.sublime-color-scheme ├── OrgExtended.sublime-commands ├── OrgExtended.sublime-keymap ├── OrgExtended.sublime-project ├── OrgExtended.sublime-settings ├── OrgExtended.sublime-syntax ├── OrgExtended.sublime-syntax-template ├── README.md ├── Symbol List.tmPreferences ├── asettings.py ├── balloontip.ps1 ├── beancount.py ├── dependencies.json ├── htmlstyles/ │ ├── blocky.css │ ├── blocky_heading.html │ ├── blocky_inheader.html │ ├── funky.css │ ├── funky_inheader.html │ ├── plain.css │ ├── plain_heading.html │ ├── plain_inheader.html │ ├── refined.css │ └── refined_inheader.html ├── languagelist.yaml ├── messages/ │ ├── 1.0.1.org │ ├── 1.0.10.org │ ├── 1.0.2.org │ ├── 1.0.3.org │ ├── 1.0.4.org │ ├── 1.0.5.org │ ├── 1.0.6.org │ ├── 1.0.7.org │ ├── 1.0.8.org │ ├── 1.0.9.org │ ├── 1.1.0.org │ ├── 1.1.1.org │ ├── 1.1.10.org │ ├── 1.1.11.org │ ├── 1.1.12.org │ ├── 1.1.13.org │ ├── 1.1.14.org │ ├── 1.1.15.org │ ├── 1.1.16.org │ ├── 1.1.17.org │ ├── 1.1.18.org │ ├── 1.1.19.org │ ├── 1.1.2.org │ ├── 1.1.20.org │ ├── 1.1.21.org │ ├── 1.1.22.org │ ├── 1.1.23.org │ ├── 1.1.24.org │ ├── 1.1.25.org │ ├── 1.1.26.org │ ├── 1.1.27.org │ ├── 1.1.28.org │ ├── 1.1.29.org │ ├── 1.1.3.org │ ├── 1.1.30.org │ ├── 1.1.4.org │ ├── 1.1.5.org │ ├── 1.1.6.org │ ├── 1.1.7.org │ ├── 1.1.8.org │ ├── 1.1.9.org │ ├── 1.2.0.org │ ├── 1.2.1.org │ ├── 1.2.10.org │ ├── 1.2.11.org │ ├── 1.2.12.org │ ├── 1.2.13.org │ ├── 1.2.14.org │ ├── 1.2.15.org │ ├── 1.2.16.org │ ├── 1.2.17.org │ ├── 1.2.18.org │ ├── 1.2.19.org │ ├── 1.2.2.org │ ├── 1.2.20.org │ ├── 1.2.21.org │ ├── 1.2.22.org │ ├── 1.2.23.org │ ├── 1.2.24.org │ ├── 1.2.25.org │ ├── 1.2.26.org │ ├── 1.2.27.org │ ├── 1.2.28.org │ ├── 1.2.29.org │ ├── 1.2.3.org │ ├── 1.2.30.org │ ├── 1.2.31.org │ ├── 1.2.32.org │ ├── 1.2.33.org │ ├── 1.2.34.org │ ├── 1.2.35.org │ ├── 1.2.36.org │ ├── 1.2.37.org │ ├── 1.2.38.org │ ├── 1.2.39.org │ ├── 1.2.4.org │ ├── 1.2.40.org │ ├── 1.2.41.org │ ├── 1.2.42.org │ ├── 1.2.43.org │ ├── 1.2.44.org │ ├── 1.2.45.org │ ├── 1.2.46.org │ ├── 1.2.47.org │ ├── 1.2.48.org │ ├── 1.2.49.org │ ├── 1.2.5.org │ ├── 1.2.50.org │ ├── 1.2.51.org │ ├── 1.2.52.org │ ├── 1.2.53.org │ ├── 1.2.54.org │ ├── 1.2.55.org │ ├── 1.2.56.org │ ├── 1.2.6.org │ ├── 1.2.7.org │ ├── 1.2.8.org │ ├── 1.2.9.org │ ├── gantt-demo.org │ └── install.org ├── messages.json ├── orgagenda.py ├── orgagenda.sublime-color-scheme ├── orgagenda.sublime-settings ├── orgagenda.sublime-syntax ├── orgbuiltinresources.py ├── orgcapture.py ├── orgcheckbox.py ├── orgclocking.py ├── orgdateeditor.sublime-settings ├── orgdateeditor.sublime-syntax ├── orgdatepicker.py ├── orgdatepicker.sublime-color-scheme ├── orgdatepicker.sublime-settings ├── orgdatepicker.sublime-syntax ├── orgdaypage.py ├── orgdb.py ├── orgduration.py ├── orgdwim.py ├── orgdynamic/ │ ├── clocktable.py │ ├── columnview.py │ └── insertdatetime.py ├── orgdynamicblock.py ├── orgediting.py ├── orgexporter.py ├── orgextended.py ├── orgextension.py ├── orgfolding.py ├── orghtml.py ├── orghtmlexporter.py ├── orginput.sublime-syntax ├── orginsertselected.py ├── orginternalediting.py ├── orginternalhelpers.py ├── orglatex.py ├── orglinks.py ├── orglist.py ├── orgmouse.py ├── orgnavigation.py ├── orgneovi.py ├── orgnotifications.py ├── orgnumberedlist.py ├── orgpandoc.py ├── orgparse/ │ ├── __init__.py │ ├── date.py │ ├── enum.py │ ├── inline.py │ ├── loader.py │ ├── node.py │ ├── startup.py │ ├── sublimenode.py │ └── utils/ │ ├── __init__.py │ ├── _py3compat.py │ └── py3compat.py ├── orgplist.py ├── orgproperties.py ├── orgreadtheorg.py ├── orgresolver/ │ ├── __init__.py │ ├── abstract.py │ ├── email.py │ ├── file.py │ ├── http.py │ ├── https.py │ ├── internal.py │ ├── jira.py │ └── prompt.py ├── orgrevealjs.py ├── orgsnippets/ │ ├── beancount/ │ │ └── transaction.sublime-snippet │ ├── capture_heading.sublime-snippet │ ├── dayPageSnippet.sublime-snippet │ ├── dynamicblock.sublime-snippet │ ├── example.sublime-snippet │ ├── heading1.sublime-snippet │ ├── heading2.sublime-snippet │ ├── heading3.sublime-snippet │ ├── heading4.sublime-snippet │ ├── heading5.sublime-snippet │ ├── link.sublime-snippet │ ├── meeting_heading.sublime-snippet │ ├── note_heading.sublime-snippet │ ├── notes.sublime-snippet │ ├── page.sublime-snippet │ ├── plain_template.sublime-snippet │ ├── quote.sublime-snippet │ ├── src.sublime-snippet │ ├── tag.sublime-snippet │ ├── todo_heading.sublime-snippet │ └── verse.sublime-snippet ├── orgsourceblock.py ├── orgsrc/ │ ├── beancount.py │ ├── cmd.py │ ├── csharp.py │ ├── ditaa.py │ ├── gnuplot.py │ ├── graphviz.py │ ├── javascript.py │ ├── mermaid.py │ ├── perl.py │ ├── plantuml.py │ ├── powershell.py │ ├── python.py │ └── sh.py ├── orgswiper.py ├── orgtableformula.py ├── orgtableplot.py ├── orgtimechart.py ├── orgtrello.py ├── orguniqueview.py ├── orgunittests.py ├── orgutil/ │ ├── __init__.py │ ├── addmethod.py │ ├── asciiclock.py │ ├── navigation.py │ ├── temp.py │ ├── template.py │ ├── util.py │ └── webpull.py ├── orgxmlthemeparser.py ├── packagecon.py ├── pandoc/ │ ├── blocky.css │ └── blocky_inheader.html ├── pandoc.css ├── pandoc2.css ├── pandoc3.css ├── pandoc4.css ├── pandoc5.css ├── pandoc6.css ├── pymitter.py ├── readtheorg/ │ ├── htmlize.css │ ├── readtheorg.css │ ├── readtheorg.js │ └── rtd-full.css ├── simple_eval.py ├── tests/ │ ├── revealjs.org │ ├── revealjs_ok.html │ ├── sourceunittests.org │ ├── tableunittests.org │ └── testfile.org └── todo.org ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.gif filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Platform:** - Eg Mac ST3 or PC ST4 ** Sublime debug console output** Ctrl-~ and include the output here. This may have an exception we need to deal with. **Additional context** Add any other context about the problem here. ================================================ FILE: .python-version ================================================ 3.8 ================================================ FILE: Default.sublime-keymap ================================================ [ { "keys": ["ctrl+shift+x"], "command": "org_capture" }, { "keys": ["ctrl+up"], "command": "org_up" , "context": [{ "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }]}, { "keys": ["ctrl+down"], "command": "org_down" , "context": [{ "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }]}, // TODO: ST4 REQUIRES the use of context vs wrapping. // Split these appart to make the easier to manage. { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_table", "operator": "equal", "operand": true }, { "key": "has_next_field", "operator": "not_equal", "operand": true}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["shift+tab"], "command": "table_editor_previous_field", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_table", "operator": "equal", "operand": true }, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_heading", "operator": "equal", "operand": true }, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["shift+tab"], "command": "org_global_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_heading", "operator": "equal", "operand": true }, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_link", "operator": "equal", "operand": true }, { "key": "auto_complete_visible", "operator": "equal", "operand": false}, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_global", "operator": "equal", "operand": true }, { "key": "org_table", "operator": "equal", "operand": false }, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_checkbox", "operator": "equal", "operand": true }, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["tab"], "command": "org_tab_cycling", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "org_block", "operator": "equal", "operand": true }, { "key": "has_next_field", "operator": "not_equal", "operand": true} ] }, { "keys": ["tab"], "command": "expand_snippet", "context": [ { "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }, { "key": "has_snippet" } ] }, { "keys": ["ctrl+alt+x"], "command": "org_open_refile" }, // Core OrgMode Behaviour //{ "keys": ["enter"], "command": "orgmode_toggle_checkbox", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.checkbox" }]}, //{ "keys": ["enter"], "command": "orgmode_recalc_checkbox_summary", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.checkbox.summary" }]}, { "keys": ["enter"], "command": "org_open_link", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.link" },{ "key": "auto_complete_visible", "operator": "equal", "operand": false}]}, { "keys": ["enter"], "command": "orgmode_cycle_internal_link", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.link.internal" }]}, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline" }], "args": { "Indent": 1} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline2" }], "args": { "Indent": 2} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline3" }], "args": { "Indent": 3} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline4" }], "args": { "Indent": 4} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline5" }], "args": { "Indent": 5} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline6" }], "args": { "Indent": 6} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline7" }], "args": { "Indent": 7} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline8" }], "args": { "Indent": 8} }, { "keys": ["enter"], "command": "org_enter_on_heading", "context": [{ "key": "selector", "operator": "equal", "operand": "orgmode.headline9" }], "args": { "Indent": 9} }, { "keys": ["ctrl+enter"], "command": "org_generic_insert", "context": [{ "key": "selector", "operator": "equal", "operand": "text.orgmode" }]}, { "keys": ["ctrl+shift+enter"], "command": "org_generic_insert_aux", "context": [{ "key": "selector", "operator": "equal", "operand": "text.orgmode" }]}, // Normal non vim style bindings { "keys": ["alt+o","z"], "command": "org_capture" }, { "keys": ["alt+o","a", "d"], "command": "org_agenda_day_view" }, { "keys": ["alt+o", "t"], "command": "org_toggle", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "R"], "command": "org_refile", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "p"], "command": "org_priority_change", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "right"], "command": "org_change_indent", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "left"], "command": "org_change_de_indent", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "up"], "command": "org_move_heading_up", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "down"], "command": "org_move_heading_down", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "h"], "command": "org_insert_heading_sibling", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "c"], "command": "org_insert_heading_child", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "d", "i"], "command": "org_insert_date_inactive", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "d", "a"], "command": "org_insert_date_active", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "t"], "command": "org_insert_tag", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "i"], "command": "org_insert_custom_id", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "s"], "command": "org_schedule", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "t"], "command": "org_active_timestamp", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "i", "e"], "command": "org_deadline", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "c", "i"], "command": "org_clock_in", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "c", "o"], "command": "org_clock_out", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "c", "c"], "command": "org_recalc", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "c", "s"], "command": "org_insert_checkbox_summary", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "y", "l"], "command": "org_create_link", "context": []}, { "keys": ["alt+o", "m", "s"], "command": "org_select_subtree", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}]}, { "keys": ["alt+o", "m", "e"], "command": "org_select_entity", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}]}, { "keys": ["alt+o", "y", "s"], "command": "org_copy_subtree", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}]}, { "keys": ["alt+o", "y", "e"], "command": "org_copy_entity", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}]}, // DAYPAGE { "keys": ["alt+o", "d", "n"], "command": "org_day_page_next", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "d", "p"], "command": "org_day_page_previous", "context": [{ "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": ["alt+o", "d", "c"], "command": "org_day_page_create", }, // TABLES { "keys": ["alt+o", "t", "a"], "command": "table_editor_align", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["alt+o","t","j"], "command": "table_editor_join_lines", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+o","t", "-"], "command": "table_editor_insert_single_hline", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["alt+o","t", "="], "command": "table_editor_insert_double_hline", "context": [ { "key": "eol_selector", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["alt+o","enter"], "command": "table_editor_hline_and_move", "context": [ { "key": "eol_selector", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": ["enter"], "command": "table_editor_next_row", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["shift+enter"], "command": "table_editor_split_column_down", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+right"], "command": "table_editor_move_column_right", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+left"], "command": "table_editor_move_column_left", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+shift+left"], "command": "table_editor_delete_column", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+shift+right"], "command": "table_editor_insert_column", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+shift+up"], "command": "table_editor_kill_row", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+shift+down"], "command": "table_editor_insert_row", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+up"], "command": "table_editor_move_row_up", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": ["alt+down"], "command": "table_editor_move_row_down", "context": [ { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, // ORG AGENDA NORMAL KEYBINDING { "keys": ["alt+o", "o", "a"], "command": "org_agenda_custom_view", "context": [] }, { "keys": ["enter"], "command": "org_agenda_go_to", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [" "], "command": "org_agenda_go_to_split", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["g"], "command": "org_agenda_day_view", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [","], "command": "org_agenda_change_priority", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["s"], "command": "org_agenda_change_todo", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["e"], "command": "org_agenda_insert_effort", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["i"], "command": "org_agenda_id" , "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["t"], "command": "org_agenda_insert_tag", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["a"], "command": "org_agenda_assign", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["c","i"], "command": "org_agenda_clock_in", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["c","o"], "command": "org_agenda_clock_out", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [">"], "command": "org_agenda_goto_next_day", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["<"], "command": "org_agenda_goto_prev_day", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["alt+o", "f", "f"], "command": "org_agenda_re_open_filter_view", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, // NeoVintageous - Command / Normal Mode - Quick commands // GLOBAL BINDINGS { "keys": ["Z"], "command": "org_capture", "context": [{"key": "vi_command_mode_aware"}] }, { "keys": ["shift+space"], "command": "org_agenda_day_view", "context": [{"key": "vi_command_mode_aware"}] }, { "keys": [" ", "y", "l"], "command": "org_create_link", "context": [{"key": "vi_command_mode_aware"}]}, // Personal Doom/Spacemacs style keybindings. Really should be in their own package. // I will move at some future point. // Spacemacs style group switching. I prefer this, feel free to remove. { "keys": [" ", "1"], "command": "focus_group", "context": [{"key": "vi_command_mode_aware"}], "args": { "group": 0} }, { "keys": [" ", "2"], "command": "focus_group", "context": [{"key": "vi_command_mode_aware"}], "args": { "group": 1} }, { "keys": [" ", "3"], "command": "focus_group", "context": [{"key": "vi_command_mode_aware"}], "args": { "group": 2} }, { "keys": [" ", "4"], "command": "focus_group", "context": [{"key": "vi_command_mode_aware"}], "args": { "group": 3} }, { "keys": [" ", "5"], "command": "focus_group", "context": [{"key": "vi_command_mode_aware"}], "args": { "group": 4} }, // Spacemacs style save file { "keys": [" ", "f", "s"], "command": "save", "context": [{"key": "vi_command_mode_aware"}]}, // ORGMODE BINDINGS { "keys": [" ", "t"], "command": "org_toggle", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}, { "key": "selector", "operator": "not_equal", "operand": "orgmode.table"} ] }, { "keys": ["R"], "command": "org_refile", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ","r","f"], "command": "org_refile_to_file", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ","r","r"], "command": "org_refile_to_file_and_headline","context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ","r","m"], "command": "org_remove_tag", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ","r","a","m"], "command": "org_remove_all_tags", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "p"], "command": "org_priority_change", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "right"], "command": "org_change_indent", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "left"], "command": "org_change_de_indent", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "up"], "command": "org_move_heading_up", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "down"], "command": "org_move_heading_down", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "h"], "command": "org_insert_heading_sibling", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "c"], "command": "org_insert_heading_child", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "d", "i"], "command": "org_insert_date_inactive", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "d", "a"], "command": "org_insert_date_active", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "m"], "command": "org_insert_tag", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "i"], "command": "org_insert_custom_id", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "s"], "command": "org_schedule", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "t"], "command": "org_active_timestamp", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "i", "e"], "command": "org_deadline", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "c", "i"], "command": "org_clock_in", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "c", "o"], "command": "org_clock_out", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "c", "c"], "command": "org_recalc", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "c", "s"], "command": "org_insert_checkbox_summary", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "m", "s"], "command": "org_select_subtree", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "m", "e"], "command": "org_select_entity", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "y", "s"], "command": "org_copy_subtree", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "y", "e"], "command": "org_copy_entity", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "f", "o"], "command": "org_fold_all_but_me", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "f", "m"], "command": "org_fix_tags", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, // DAYPAGE { "keys": [" ", "d", "n"], "command": "org_day_page_next", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "d", "p"], "command": "org_day_page_previous", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "text.orgmode"}] }, { "keys": [" ", "d", "c"], "command": "org_day_page_create", "context": [{"key": "vi_command_mode_aware"}] }, // ORG AGENDA { "keys": [" ", "o", "a"], "command": "org_agenda_custom_view", "context": [{"key": "vi_command_mode_aware"}] }, { "keys": ["enter"], "command": "org_agenda_go_to", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [" "], "command": "org_agenda_go_to_split", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["g"], "command": "org_agenda_day_view", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [","], "command": "org_agenda_change_priority", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["t"], "command": "org_agenda_change_todo", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["c","i"], "command": "org_agenda_clock_in", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["c","o"], "command": "org_agenda_clock_out", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": [">"], "command": "org_agenda_goto_next_day", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["<"], "command": "org_agenda_goto_prev_day", "context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["f", "f"], "command": "org_agenda_re_open_filter_view","context": [{"key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "source.orgagenda"}] }, // TABLES { "keys": [" ", "t", "a"], "command": "table_editor_align", "context": [ { "key": "vi_command_mode_aware"}, { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": [" ","t","j"], "command": "table_editor_join_lines", "context": [ { "key": "vi_command_mode_aware"}, { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "\\|", "match_all": true } ] }, { "keys": [" ","t", "-"], "command": "table_editor_insert_single_hline", "context": [ { "key": "vi_command_mode_aware"}, { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": [" ","t", "="], "command": "table_editor_insert_double_hline", "context": [ { "key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": [" ","enter"], "command": "table_editor_hline_and_move", "context": [ { "key": "vi_command_mode_aware"}, { "key": "eol_selector", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": [" ", "t", "e"], "command": "org_edit_formula_for_cell", "context": [ { "key": "vi_command_mode_aware"}, { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, { "keys": [" ", "t", "k"], "command": "org_clear_cell", "context": [ { "key": "vi_command_mode_aware"}, { "key": "selector", "operator": "equal", "operand": "orgmode.table"}, { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } ] }, // ORG DATE PICKER { "keys": [">"], "command": "org_date_picker_next_day", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["<"], "command": "org_date_picker_prev_day", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["ctrl+,"], "command": "org_date_picker_prev_week", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["ctrl+."], "command": "org_date_picker_next_week", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["alt+,"], "command": "org_date_picker_prev_month", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["alt+."], "command": "org_date_picker_next_month", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["ctrl+shift+,"], "command": "org_date_picker_prev_hour", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["ctrl+shift+."], "command": "org_date_picker_next_hour", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["alt+shift+,"], "command": "org_date_picker_prev_minute", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, { "keys": ["alt+shift+."], "command": "org_date_picker_next_minute", "context": [{ "key": "eol_selector", "operand": "source.orgdateeditor"}] }, // ORG INPUT SELECTOR { "keys": ["down"], "command": "org_input_down", "context": [{ "key": "eol_selector", "operand": "source.orginput"}] }, { "keys": ["up"], "command": "org_input_up", "context": [{ "key": "eol_selector", "operand": "source.orginput"}] } ] ================================================ FILE: Indentation Rules.tmPreferences ================================================ name orgmode scope text.orgmode settings increaseIndentPattern (^\s*[#][+]((BEGIN)|(begin)))|(^\s*[*]+ ) decreaseIndentPattern (^\s*[#][+]((END)|(end))) uuid BC062860-3346-4D3B-8421-C3543F83D11F ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 Ian Davids 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. ================================================ FILE: Main.sublime-menu ================================================ [ { "mnemonic": "n", "caption": "Preferences", "id": "preferences", "children": [ { "mnemonic": "P", "caption": "Package Settings", "id": "package-settings", "children": [ { "caption": "Org Extended", "children": [ { "caption": "Docs", "args": { "url": "https://github.com/ihdavids/orgextended_docs/blob/master/start.org" }, "command": "open_url" }, { "caption": "-" }, { "caption": "Setup MouseMap", "command": "org_setup_mouse_map" }, { "caption": "Open MouseMap", "args": { "file": "${packages}/User/Default.sublime-mousemap" }, "command": "open_file" }, { "caption": "-" }, { "caption": "Settings", "command": "edit_settings", "args": { "base_file": "${packages}/OrgExtended/OrgExtended.sublime-settings", "default": "// OrgExtended Settings - User\n{\n\t$0\n}\n" } }, { "caption": "Key Bindings", "command": "edit_settings", "args": { "base_file": "${packages}/OrgExtended/Default.sublime-keymap", "user_file": "${packages}/User/Default ($platform).sublime-keymap" } }, { "caption": "-" } ] } ] } ] } ] ================================================ FILE: OrgBeancount.sublime-settings ================================================ { "somevalue": true, } ================================================ FILE: OrgBeancount.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: OrgBeancount file_extensions: - orgbeancount version: 2 extends: Packages/OrgExtended/OrgExtended.sublime-syntax scope: source.orgbeancount text.orgmode contexts: comment: # Comment - match: ;.* scope: comment.line.beancount comments: - match: (?<=\s)(;.*)(?=\n) captures: 1: comment.line.beancount illegal: - match: ([^\s]) scope: invalid.illegal.unrecognized.beancount amount: - match: ([\-|\+]?)((?:\d|\d[\d,]*\d)(?:\.\d*)?)\s*([A-Z][A-Z0-9\'\.\_\-]{0,22}[A-Z0-9]) captures: 1: keyword.operator.modifier.beancount 2: constant.numeric.currency.beancount 3: entity.type.commodity.beancount scope: meta.amount.beancount commodity: - match: ([A-Z][A-Z0-9\'\.\_\-]{0,22}[A-Z0-9]) scope: entity.type.commodity.beancount cost: - match: \{\{? captures: 0: keyword.operator.assignment.beancount push: - meta_scope: meta.cost.beancount - include: amount - include: date - match: \, scope: punctuation.separator.beancount - include: illegal - match: \}\}? captures: 0: keyword.operator.assignment.beancount pop: true date: - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2}) scope: meta.date.beancount captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount flag: - match: (?<=\s)([*!&#?%PSTCURM]) scope: keyword.other.beancount link: - match: (?<=\s)(\^)([A-Za-z0-9\-_/.]+)(?=\s) captures: 1: keyword.operator.link.beancount 2: markup.underline.link.beancount meta: - match: ^\s*([a-z][A-Za-z0-9\-]+)([:])\s captures: 1: keyword.operator.directive.beancount 2: punctuation.separator.beancount push: - meta_scope: meta.meta.beancount - include: string - include: comments - include: illegal - match: \n pop: true posting: - match: ^\s+(?=([A-Z\!])) push: - meta_scope: meta.posting.beancount - include: meta - include: comments - include: flag - include: account - include: amount - include: cost - include: date - include: price - include: illegal - match: (?=(^\s*$|^\S|^\s*[A-Z])) pop: true price: - match: \@\@? captures: 0: keyword.operator.assignment.beancount push: - meta_scope: meta.price.beancount - include: amount - include: illegal - match: (?=(;|\n)) pop: true string: - match: \" push: - meta_scope: string.quoted.double.beancount - match: \\. scope: constant.character.escape.beancount - match: \" pop: true tag: - match: (?<=\s)(#)([A-Za-z0-9\-_/.]+)(?=\s) captures: 1: keyword.operator.tag.beancount 2: entity.name.tag.beancount account: # Account - match: ([A-Z][A-Za-z0-9\-]+)(:) captures: 1: constant.language.beancount 2: punctuation.separator.beancount push: - meta_scope: meta.account.beancount # Sub Accounts - match: ([A-Z][A-Za-z0-9\-]+)([:]?) captures: 1: variable.account.beancount 2: punctuation.separator.beancount push: - match: ([:]?)|(\s) pop: true - include: illegal - include: $self - match: \s pop: true main: - meta_append: true # Tag directive - match: ^(poptag|pushtag)\s+(#)([A-Za-z0-9\-_/.]+) captures: 1: support.function.beancount 2: keyword.operator.tag.beancount 3: entity.name.tag.beancount push: - meta_scope: meta.directive.tag.beancount - include: comment - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Include - match: ^(include)\s+(\".*\") captures: 1: support.function.beancount 2: string.quoted.double.beancount push: - meta_scope: meta.directive.include.beancount - include: comment - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Option directive - match: ^(option)\s+(\".*\")\s+(\".*\") captures: 1: support.function.beancount 2: support.variable.beancount 3: support.quoted.double.beancount push: - meta_scope: meta.directive.option.beancount - include: comment - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Plugin - match: ^(plugin)\s+(\"(.*)\")\s+(\".*\") captures: 1: support.function.beancount 2: support.quoted.double.beancount 3: entity.name.function.beancount 4: string.quoted.double.beancount push: - meta_scope: keyword.operator.directive.beancount - include: comment - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Open/Close/Pad directive - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s+(open|close|pad) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.beancount push: - meta_scope: meta.directive.dated.beancount - include: comment - include: illegal - include: account - include: commodity - match: \, scope: punctuation.separator.beancount - match: (?=(^\s*$|^\S)) pop: true # Event directive - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s(event) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount push: - meta_scope: meta.directive.dated.beancount - include: comment - include: meta - include: string - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Commodity directive - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s(commodity) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount push: - meta_scope: meta.directive.dated.beancount - include: comments - include: meta - include: commodity - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Note/Document directive - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s(note|document) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount push: - meta_scope: meta.directive.dated.beancount - include: comments - include: meta - include: account - include: string - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Price directives - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s(price) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount push: - meta_scope: meta.directive.dated.beancount - include: comments - include: meta - include: commodity - include: amount - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Balance directives - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s(balance) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount push: - meta_scope: meta.directive.dated.beancount - include: comments - include: meta - include: account - include: amount - include: illegal - match: (?=(^\s*$|^\S)) pop: true # Transaction directive - match: ([0-9]{4})([\-|/])([0-9]{2})([\-|/])([0-9]{2})\s+(txn|[*!&#?%PSTCURM])(?:\s+(".*")(?=\s+"))?\s+(".*?")(?=((?:\s+#[a-zA-z\-]+(?=\s))*(?:\s+\^[a-zA-z\-\.]+(?=\s))*(?:\s+;\s*.*)?)\s) captures: 1: constant.numeric.date.year.beancount 2: punctuation.separator.beancount 3: constant.numeric.date.month.beancount 4: punctuation.separator.beancount 5: constant.numeric.date.day.beancount 6: support.function.directive.beancount 7: string.quoted.tiers.beancount 8: string.quoted.narration.beancount} push: - meta_scope: meta.directive.transaction.beancount - include: comments - include: posting - include: meta - include: tag - include: link - include: illegal - match: (?=(^\s*$|^\S)) pop: true ================================================ FILE: OrgExtended-Light.sublime-color-scheme ================================================ { "name": "Org Extended Light", "globals": { "background": "#fafafa", "foreground": "#575f66", "invisibles": "#575f664d", "caret": "#ff9940", "block_caret": "#ff99404d", "line_highlight": "#8a91991a", "accent": "#ff9940", "popup_css": "\n html, body {\n background-color: #ffffff;\n color: #575f66;\n }\n body {\n padding: 1px 3px;\n }\n a {\n color: rgba(85,180,212, .7);\n }\n ", "gutter": "#fafafa", "gutter_foreground": "#8a919966", "line_diff_width": "2", "line_diff_added": "#99bf4d", "line_diff_modified": "#709ecc", "line_diff_deleted": "#f27983", "selection": "#d1e4f4", "selection_border": "#e1e1e2", "selection_border_width": "1", "inactive_selection": "#e7e8e9", "inactive_selection_foreground": "#575f664d", "selection_corner_style": "round", "selection_corner_radius": "3", "highlight": "#ff994066", "find_highlight": "#ff9940", "find_highlight_foreground": "#fafafa", "guide": "#8a91992e", "active_guide": "#8a919959", "stack_guide": "#8a919966", "shadow": "#fafafa4d", "shadow_width": "0" }, "rules": [ { "background": "#000000", "scope": "col_gutter", "foreground": "#ffffff" }, { "background": "#FFC0CBFF", "scope": "col_FFC0CBFF", "foreground": "#545454FF" }, { "background": "#0000FFFF", "scope": "col_0000FFFF", "foreground": "#9D9D9DFF" }, { "background": "#FF0000FF", "scope": "col_FF0000FF", "foreground": "#CCCCCCFF" }, { "background": "#800080FF", "scope": "col_800080FF", "foreground": "#B4B4B4FF" }, { "name": "Comment", "scope": "comment", "font_style": "italic", "foreground": "#abb0b6" }, { "name": "String", "scope": "string, constant.other.symbol", "foreground": "#86a300" }, { "name": "Regular Expressions and Escape Characters", "scope": "string.regexp, constant.character, constant.other", "foreground": "#4cbf99" }, { "name": "Number", "scope": "constant.numeric", "foreground": "#ff9940" }, { "name": "Built-in constants", "scope": "constant.language", "foreground": "#ff9940" }, { "name": "Constants", "scope": "meta.constant, entity.name.constant", "foreground": "#a37acc" }, { "name": "Variable", "scope": "variable", "foreground": "#575f66" }, { "name": "Member Variable", "scope": "variable.member", "foreground": "#f07171" }, { "name": "Language variable", "scope": "variable.language", "font_style": "italic", "foreground": "#55b4d4" }, { "name": "Storage", "scope": "storage, storage.type.keyword", "foreground": "#fa8d3e" }, { "name": "Keyword", "scope": "keyword", "foreground": "#fa8d3e" }, { "name": "Java keyword fixes", "scope": "source.java meta.class.java meta.class.identifier.java storage.type.java", "foreground": "#fa8d3e" }, { "name": "Operators", "scope": "keyword.operator", "foreground": "#ed9366" }, { "name": "Separators like ; or ,", "scope": "punctuation.separator, punctuation.terminator", "foreground": "#575f66b3" }, { "name": "Punctuation", "scope": "punctuation.section", "foreground": "#575f66" }, { "name": "Accessor", "scope": "punctuation.accessor", "foreground": "#ed9366" }, { "name": "Types fixes", "scope": "source.java storage.type, source.haskell storage.type, source.c storage.type", "foreground": "#399ee6" }, { "name": "Inherited class type", "scope": "entity.other.inherited-class", "foreground": "#55b4d4" }, { "name": "Lambda arrow", "scope": "storage.type.function", "foreground": "#fa8d3e" }, { "name": "Java primitive variable types", "scope": "source.java storage.type.primitive", "foreground": "#55b4d4" }, { "name": "Function name", "scope": "entity.name.function", "foreground": "#f2ae49" }, { "name": "Function arguments", "scope": "variable.parameter, meta.parameter", "foreground": "#a37acc" }, { "name": "Function call", "scope": "variable.function, variable.annotation, meta.function-call.generic, support.function.go", "foreground": "#f2ae49" }, { "name": "Library function", "scope": "support.function, support.macro", "foreground": "#f07171" }, { "name": "Imports and packages", "scope": "entity.name.import, entity.name.package", "foreground": "#86b300" }, { "name": "Entity name", "scope": "entity.name, source.js meta.function-call.constructor variable.type", "foreground": "#399ee6" }, { "name": "Tag", "scope": "entity.name.tag, meta.tag.sgml", "foreground": "#55b4d4" }, { "name": "Tag start/end", "scope": "punctuation.definition.tag.end, punctuation.definition.tag.begin, punctuation.definition.tag", "foreground": "#55b4d480" }, { "name": "Tag attribute", "scope": "entity.other.attribute-name", "foreground": "#f2ae49" }, { "name": "Library constant", "scope": "support.constant", "font_style": "italic", "foreground": "#ed9366" }, { "name": "Library class/type", "scope": "support.type, support.class, source.go storage.type", "foreground": "#55b4d4" }, { "name": "Decorators/annotation", "scope": "meta.decorator variable.other, meta.decorator punctuation.decorator, storage.type.annotation, variable.annotation, punctuation.definition.annotation", "foreground": "#e6ba7e" }, { "name": "Invalid", "scope": "invalid", "foreground": "#f51818" }, { "name": "diff.header", "scope": "meta.diff, meta.diff.header", "foreground": "#c594c5" }, { "name": "Ruby class methods", "scope": "source.ruby variable.other.readwrite", "foreground": "#f2ae49" }, { "name": "CSS tag names", "scope": "source.css entity.name.tag, source.sass entity.name.tag, source.scss entity.name.tag, source.less entity.name.tag, source.stylus entity.name.tag", "foreground": "#399ee6" }, { "name": "CSS browser prefix", "scope": "source.css support.type, source.sass support.type, source.scss support.type, source.less support.type, source.stylus support.type", "foreground": "#abb0b6" }, { "name": "CSS Properties", "scope": "support.type.property-name", "font_style": "normal", "foreground": "#55b4d4" }, { "name": "Search Results Nums", "scope": "constant.numeric.line-number.find-in-files - match", "foreground": "#abb0b6" }, { "name": "Search Results Match Nums", "scope": "constant.numeric.line-number.match", "foreground": "#fa8d3e" }, { "name": "Search Results Lines", "scope": "entity.name.filename.find-in-files", "foreground": "#86b300" }, { "scope": "message.error", "foreground": "#f51818" }, { "name": "Markup heading", "scope": "markup.heading, markup.heading entity.name", "font_style": "bold", "foreground": "#86b300" }, { "name": "Markup links", "scope": "markup.underline.link, string.other.link", "foreground": "#55b4d4" }, { "name": "Markup Italic", "scope": "markup.italic", "font_style": "italic", "foreground": "#f07171" }, { "name": "Markup Bold", "scope": "markup.bold", "font_style": "bold", "foreground": "#f07171" }, { "name": "Markup Bold/italic", "scope": "markup.italic markup.bold, markup.bold markup.italic", "font_style": "bold italic" }, { "name": "Markup Code", "scope": "markup.raw", "background": "#575f6605" }, { "name": "Markup Code Inline", "scope": "markup.raw.inline", "background": "#575f660f" }, { "name": "Markdown Separator", "scope": "meta.separator", "font_style": "bold", "background": "#575f660f", "foreground": "#abb0b6" }, { "name": "Markup Blockquote", "scope": "markup.quote", "foreground": "#4cbf99", "font_style": "italic" }, { "name": "Markup List Bullet", "scope": "markup.list punctuation.definition.list.begin", "foreground": "#f2ae49" }, { "name": "Markup added", "scope": "markup.inserted", "foreground": "#99bf4d" }, { "name": "Markup modified", "scope": "markup.changed", "foreground": "#709ecc" }, { "name": "Markup removed", "scope": "markup.deleted", "foreground": "#f27983" }, { "name": "Markup Strike", "scope": "markup.strike", "foreground": "#e6ba7e" }, { "name": "Markup Table", "scope": "markup.table", "background": "#575f660f", "foreground": "#55b4d4" }, { "name": "Markup Raw Inline", "scope": "text.html.markdown markup.inline.raw", "foreground": "#ed9366" }, { "name": "Markdown - Line Break", "scope": "text.html.markdown meta.dummy.line-break", "background": "#abb0b6", "foreground": "#abb0b6" }, { "name": "Markdown - Raw Block Fenced", "scope": "punctuation.definition.markdown", "background": "#575f66", "foreground": "#abb0b6" }, { "scope": "orgmode.break", "foreground": "#ed188a", }, { "scope": "orgmode.page", "foreground": "#f5eebf", }, { "scope": "orgmode.headline", "foreground": "#14adfa", "font_style": "bold italic", }, { "scope": "orgmode.headline2", "foreground": "#bb86fc", "font_style": "bold", }, { "scope": "orgmode.headline3", "foreground": "#03cab5", "font_style": "bold", }, { "scope": "orgmode.headline4", "foreground": "#afb681", "font_style": "italic", }, { "scope": "orgmode.headline5", "foreground": "#018786", "font_style": "italic", }, { "scope": "orgmode.headline6", //"foreground": "#afe3de", "foreground": "#7fa3ae", "font_style": "italic", }, // Stars before the last star in a headline // make these background to hide them. { "scope": "orgmode.preamble", "foreground": "var(bgcol)", "font_style": "italic", }, // Maybe I can use regions to collapse these? // Right now they look uber ugly { "scope": "orgmode.link", "foreground": "#3cb7da", "font_style": "", }, { "scope": "orgmode.link.href", "foreground": "#777788", "font_style": "italic", }, { "scope": "orgmode.link.text", "foreground": "#7aa7ed", "font_style": "bold", }, { "scope": "orgmode.email", "foreground": "#a188b3", "font_style": "italic", }, { "scope": "orgmode.deadline", "foreground": "#d1771d", "font_style": "italic", }, { "scope": "orgmode.scheduled", "foreground": "#d1771d", "font_style": "italic", }, // #+PRIORITIES: A B C { "scope": "orgmode.controltag", "foreground": "#aaaaaa", }, // controltag.text also exists { "scope": "orgmode.controltag.tag", "foreground": "#aaaaaa", "font_style": "italic", }, // < DATETIME > { "scope": "orgmode.datetime", "foreground": "#b0a497", }, // [ DATETIME ] { "scope": "orgmode.unscheddatetime", "foreground": "#b0a497", }, // CLOSED: SCHEDULED: DEADLINE: { "scope": "orgmode.statekeyword", "foreground": "#d1771d", "font_style": "italic", }, { "scope": "orgmode.checkbox", "foreground": "#a99e5b", }, { "scope": "orgmode.checkbox.checked", "foreground": "#00cc00", }, { "scope": "orgmode.checkbox.blocked", "foreground": "#cc0000", }, { "scope": "orgmode.tags", "foreground": "#3e349b", //"foreground": "#ded49b", }, { "scope": "orgmode.tags.headline", //"foreground": "#deff9b", "foreground": "#aebf7b", }, { "scope": "orgmode.priority", "foreground": "#c27532", }, { "scope": "orgmode.priority.value", "foreground": "#f5a55f", }, { "scope": "orgmode.priority.value.a", "foreground": "#e05a7b", }, { "scope": "orgmode.priority.value.b", "foreground": "#f59a76", }, { "scope": "orgmode.priority.value.c", "foreground": "#fab978", }, { "scope": "orgmode.priority.value.d", "foreground": "#f5d976", }, { "scope": "orgmode.priority.value.e", "foreground": "#bcbfae", }, { "scope": "orgmode.priority.value.general", "foreground": "#b59eb5", }, { "scope": "orgmode.state.todo", "foreground": "#e6ab4c", }, { "scope": "orgmode.state.blocked", "foreground": "#FF0000", }, { "scope": "orgmode.state.done", "foreground": "#47c94f", }, { "scope": "orgmode.state.cancelled", "foreground": "#bab9b8", }, { "scope": "orgmode.state.meeting", "foreground": "#bea7dc", }, { "scope": "orgmode.state.phone", "foreground": "#67cbcd", }, { "scope": "orgmode.state.note", "foreground": "#a272a0", }, { "scope": "orgmode.state.doing", "foreground": "#9c9c17", }, { "scope": "orgmode.state.inprogress", "foreground": "#9c9c17", }, { "scope": "orgmode.state.next", "foreground": "#37dae6", }, { "scope": "orgmode.state.reassigned", "foreground": "#bab9b8", }, { "scope": "orgmode.tack", "foreground": "#a963a4", "font_style": "bold", }, { "scope": "orgmode.numberedlist", "foreground": "#a963a4", "font_style": "bold", }, { "scope": "orgmode.definition", "foreground": "#42a8c4", "font_style": "bold", }, { "scope": "orgmode.definition.marker", "foreground": "#E1A2E8", "font_style": "bold", }, { "scope": "orgmode.follow_up", "foreground": "#FF0000", "font_style": "bold", }, { "scope": "orgmode.fence", "background": "#f2f0f0", "font_style": "bold", }, { "scope": "orgmode.fence.language", "background": "#f2f0f0", "foreground": "#f1bff2", "font_style": "bold", }, { "scope": "orgmode.raw.block", "background": "#e5e5e0", "font_style": "bold", }, { "scope": "orgmode.table.block", "background": "#e7e8e8", }, { "scope": "orgmode.bold", "foreground": "#aaffaa", "font_style": "bold", }, { "scope": "orgmode.italics", "foreground": "#aaffff", "font_style": "italic", }, { "scope": "orgmode.underline", "foreground": "#aaaaff", "font_style": "underline", }, { "scope": "orgmode.strikethrough", "foreground": "#aaaaaa", }, { "scope": "orgmode.code", "foreground": "#ffaaff", }, { "scope": "orgmode.verbatim", "foreground": "#ffaaaa", }, // MONOKAI EXTENDED COLORING // Generic colorization // function call { "scope": "support.function", "foreground": "#66d9ef", }, { "scope": "keyword", "foreground": "#f92672", }, { "scope": "comment", "foreground": "#75715e", }, { "scope": "string", "foreground": "#c6bb54", }, { "scope": "constant.numeric", "foreground": "#be84ff", }, { "scope": "constant.language", "foreground": "#be84ff", }, { "scope": "meta.preprocessor", "foreground": "#be84ff", }, { "scope": "constant.character", "foreground": "#be84ff", }, { "scope": "constant.other", "foreground": "#be84ff", }, { "scope": "variable.language", "foreground": "#000000", }, { "scope": "variable.other", "foreground": "#000000", }, { "scope": "storage", "foreground": "#f92672", }, { "scope": "storage.type", "foreground": "#56c9df", }, { "scope": "entity.name.class", "foreground": "#66D9EF", "font_style": "underline" }, { "scope": "entity.other.inherited-class", "foreground": "#a6e22e", "font_style": "italic underline" }, { "scope": "variable.parameter", "foreground": "#fd971f", "font_style": "italic" }, { "scope": "entity.name.tag", "foreground": "#f92672", }, { "scope": "entity.other.attribute-name", "foreground": "#a6e22e", }, { "scope": "entity.name.function", "foreground": "#86c22e", }, { "scope": "entity.constant", "foreground": "#66d9ef", }, { "scope": "support.constant", "foreground": "#66d9ef", }, { "scope": "support.type", "foreground": "#A6E22E", "font_style": "italic", }, { "scope": "support.other.variable", }, { "scope": "string.constant", "foreground": "#66d9ef", }, { "scope": "string.regexp", "foreground": "#f6aa11", }, { "scope": "string.variable", "foreground": "#ffffff", }, { "scope": "punctuation.definition.variable", "foreground": "#ffffff", }, // Html / Xml { "scope": "meta.tag.sgml.doctype.xml", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype entity", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype string", "foreground": "#c8cecc", }, { "scope": "content.block.html", "foreground": "#7c7865", }, { "scope": "entity.name.tag.script.html", "font_style": "italic",}, { "scope": "text.html.basic meta.tag.other.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.block.any", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.inline.any", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic source.js.embedded.html", "foreground": "#a6e22e", }, { "scope": "punctuation.separator.key-value.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic entity.other.attribute-name", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html", "foreground": "#ffffff", }, { "scope": "punctuation.definition.string.begin.html", "foreground": "#000000", }, { "scope": "punctuation.definition.string.end.html", "foreground": "#000000", }, { "scope": "punctuation.definition.tag.end", "foreground": "#000000", }, { "scope": "punctuation.definition.tag.begin", "foreground": "#000000", }, { "scope": "punctuation.definition.tag", "foreground": "#000000", }, // Handlebars { "scope": "variable.parameter.handlebars", "foreground": "#f6aa11", }, { "scope": "support.constant.handlebars", "foreground": "#66d9ef", }, { "scope": "meta.function.block.start.handlebars", "foreground": "#66d9ef", }, // CSS { "scope": "meta.preprocessor.at-rule", "foreground": "#f6aa11", }, { "scope": "meta.selector.css entity.other.attribute-name.id", "foreground": "#f6aa11", }, { "scope": "meta.selector.css entity.other.attribute-name.class", "foreground": "#a6e22e", }, { "scope": "support.type.property-name.css", "foreground": "#66d9ef", }, { "scope": "meta.constructor.argument.css", "foreground": "#f6aa11", }, { "scope": "punctuation.section.property-list.css", "foreground": "#ffffff", }, { "scope": "punctuation.definition.tag.css", "foreground": "#f92672", }, { "scope": "punctuation.separator.key-value.css", "foreground": "#ffffff", }, { "scope": "punctuation.terminator.rule.css", "foreground": "#ffffff", }, { "scope": "entity.other.attribute-name.pseudo-element.css", "foreground": "#a6e22e", }, { "scope": "entity.other.attribute-name.pseudo-class.css", "foreground": "#a6e22e", }, { "scope": "entity.other.attribute-name.pseudo-selector.css", "foreground": "#a6e22e", }, // LESS Variables { "scope": "variable.other.less", "foreground": "#ffffff", }, { "scope": "variable.other.less.mixin", "foreground": "#e0fdce", "font_style": "italic"}, { "scope": "entity.other.attribute-name.pseudo-element.less", "foreground": "#ff9117", }, // Javascript { "scope": "meta.instance.constructor meta.function-call.constructor.js", "foreground": "#a6e22e", }, { "scope": "meta.template.expression.js punctuation.definition.template-expression.begin.js", "foreground": "#AFF132", }, { "scope": "meta.template.expression.js punctuation.definition.template-expression.end.js", "foreground": "#AFF132", }, { "scope": "meta.template.expression.js punctuation.accessor", "foreground": "#AFF132", }, { "scope": "meta.function.js", "foreground": "#a6e22e", }, { "scope": "entity.name.function.js", "foreground": "#a6e22e", }, { "scope": "support.function.dom.js", "foreground": "#a6e22e", }, { "scope": "source.js meta.function.js punctuation.separator.parameter.function.js", "foreground": "#ffffff", }, { "scope": "meta.property.object.js", "foreground": "#ffffff", }, { "scope": "keyword.operator.accessor.js", "foreground": "#ffffff", }, { "scope": "source.js meta.group.braces.curly constant.other.object.key.js punctuation.separator.key-value.js", "foreground": "#ffffff", }, { "scope": "source.js meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js", "foreground": "#ffffff", }, { "scope": "support.type.object.module.js", "foreground": "#66d9ef", }, { "scope": "source.js meta.function.declaration.js support.class.js", "foreground": "#66d9ef", }, { "scope": "support.type.object.module.js support.type.object.module.js", "foreground": "#a6e22e", }, { "scope": "storage.type.js", "foreground": "#66d9ef", "font_style": "italic",}, { "scope": "text.html.basic source.js.embedded.html", "foreground": "#ffffff", }, { "scope": "storage.type.function.js", "foreground": "#66d9ef", }, { "scope": "constant.numeric.js", "foreground": "#ae81ff", }, // JS: Literal language variable { "scope": "variable.language.arguments.js, variable.language.super.js, variable.language.this.js, variable.language.self.js, variable.language.proto.js, variable.language.constructor.js, variable.language.prototype.js", "foreground": "#66d9ef", "font_style": "italic",}, // JS: [] { "scope": "meta.brace.square.js", "foreground": "#ffffff", }, // JS: () { "scope": "meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js, punctuation.definition.group", "foreground": "#ffffff", }, // JS: object literal {} { "scope": "meta.brace.curly.js, meta.object-literal.js", "foreground": "#ffffff", }, // JSON String { "scope": "meta.structure.dictionary.json string.quoted.double.json", "foreground": "#cfcfc2", }, // CoffeeScript String Interpolated { "scope": "punctuation.section.embedded.coffee", "foreground": "#e69f66", }, // PHP: [] { "scope": "keyword.operator.index-start.php, keyword.operator.index-end.php", "foreground": "#ffffff", }, // PHP: Array { "scope": "meta.array.php", "foreground": "#ffffff", }, // PHP: Array() { "scope": "meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php", "foreground": "#e42e70", }, // PHP: Array Construct { "scope": "support.function.construct.php", "foreground": "#e42e70", }, // PHP: Storage Type Function { "scope": "storage.type.function.php", "foreground": "#f92672dd", }, // PHP: Numeric Constant { "scope": "constant.numeric.php", "foreground": "#be84ff", }, // PHP: New { "scope": "keyword.other.new.php", "foreground": "#f6aa11", }, // PHP: :: { "scope": "support.class.php", "foreground": "#ffffff", }, // PHP: Other Property { "scope": "variable.other.property.php", "foreground": "#f6aa11", }, // PHP: Class { "scope": "storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php", "foreground": "#a6e22e", }, // PHP: Inherited Class { "scope": "meta.other.inherited-class.php", "foreground": "#a6e22e", }, // PHP: Storage Type { "scope": "storage.type.php", "foreground": "#66d9ef", }, // PHP: Function { "scope": "entity.name.function.php", "foreground": "#66d9ef", }, // PHP: Function Construct { "scope": "support.function.construct.php", "foreground": "#a6e22e", }, // PHP: Function Call { "scope": "entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php", "foreground": "#ffffff", }, // PHP: Comment { "scope": "keyword.other.phpdoc", "foreground": "#7c7865", }, // PHP: Source Emebedded { "scope": "source.php.embedded.block.html", "foreground": "#ffffff", }, // Invalid { "scope": "invalid", "foreground": "#f8f8f0","background": "#f92672", }, // Invalid deprecated { "scope": "invalid.deprecated", "foreground": "#f8f8f0","background": "#ae81ff", }, // diff.header { "scope": "meta.diff, meta.diff.header", "foreground": "#75715e", }, // diff.deleted { "scope": "markup.deleted", "foreground": "#f92672", }, // diff.inserted { "scope": "markup.inserted", "foreground": "#a6e22e", }, // diff.changed { "scope": "markup.changed", "foreground": "#e6db74", }, // diff.range { "scope": "meta.diff, meta.diff.range", "foreground": "#3bc0f0", }, // Python: storage { "scope": "storage.type.class.python, storage.type.function.python, storage.modifier.global.python", "foreground": "#a6e22e", }, // Python: import { "scope": "keyword.control.import.python, keyword.control.import.from.python", "foreground": "#f92672dd", }, // Python: Support.exception { "scope": "support.type.exception.python", "foreground": "#66d9ef", }, // Perl: variables { "scope": "punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl", "foreground": "#e42e70", }, // Perl: functions { "scope": "support.function.perl", "foreground": "#66d9ef", }, // Perl: comments { "scope": "comment.line.number-sign.perl", "foreground": "#75715e","font_style": "italic", }, // Perl: quotes { "scope": "punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl", "foreground": "#ffffff", }, // Perl: char { "scope": "constant.character.escape.perl", "foreground": "#dc322f", }, // Ruby: Constant { "scope": "constant.language.ruby, constant.numeric.ruby", "foreground": "#ae81ff", }, // Ruby: Variable definition { "scope": "punctuation.definition.variable.ruby", "foreground": "#f6aa11", }, // Ruby: Function Name { "scope": "meta.function.method.with-arguments.ruby", "foreground": "#a6e22e", }, // Ruby: Variable { "scope": "variable.language.ruby", "foreground": "#ffffff", }, // Ruby: Function { "scope": "entity.name.function.ruby", "foreground": "#f6aa11", }, // Ruby: Keyword Control { "scope": "keyword.control.ruby, keyword.control.def.ruby", "foreground": "#a6e22e","font_style": "bold", }, // Ruby: Class { "scope": "keyword.control.class.ruby, meta.class.ruby", "foreground": "#a6e22e", }, // Ruby: Class Name { "scope": "entity.name.type.class.ruby", "foreground": "#66d9ef", }, // Ruby: Keyword { "scope": "keyword.control.ruby", "foreground": "#a6e22e", }, // Ruby: Support Class { "scope": "support.class.ruby", "foreground": "#66d9ef", }, // Ruby: Special Method { "scope": "keyword.other.special-method.ruby", "foreground": "#a6e22e", }, // Ruby: Constant Other { "scope": "variable.other.constant.ruby", "foreground": "#66d9ef", }, // Ruby: :symbol { "scope": "constant.other.symbol.ruby", "foreground": "#f6f080", }, // Ruby: Punctuation Section { "scope": "punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby", "foreground": "#f92672", }, // Ruby: Special Method { "scope": "keyword.other.special-method.ruby", "foreground": "#e42e70", }, // Markdown: plain { "scope": "text.html.markdown", "foreground": "#ffffff", }, // Markup: raw inline { "scope": "text.html.markdown markup.raw.inline", "foreground": "#ec3533", }, // Markdown: linebreak { "scope": "text.html.markdown meta.dummy.line-break", "foreground": "#e0eddd", }, // Markdown: heading { "scope": "markdown.heading, markup.heading | markup.heading entity.name, markup.heading.markdown punctuation.definition.heading.markdown", "foreground": "#fd971f", }, // Markup: italic { "scope": "markup.italic", "foreground": "#e42e70","font_style": "italic", }, // Markup: bold { "scope": "markup.bold", "foreground": "#f92672","font_style": "bold", }, // Markup: underline { "scope": "markup.underline", "foreground": "#a6e22e","font_style": "underline", }, // Markup: strike { "scope": "markup.strike", "foreground": "#cc4273", }, // Markdown: Blockquote { "scope": "markup.quote, punctuation.definition.blockquote.markdown", "foreground": "#66d9ef","font_style": "italic", }, // Markup: Quote { "scope": "markup.quote", "foreground": "#66d9ef","font_style": " italic", }, // Markdown: Link { "scope": "string.other.link.title.markdown", "foreground": "#66d9ef","font_style": "underline", }, // Markup: Raw block { "scope": "markup.raw.block", "foreground": "#ae81ff", }, // Markdown: List Items Punctuation { "scope": "punctuation.definition.list_item.markdown", "foreground": "#777777", }, // Markdown: Raw Block fenced { "scope": "markup.raw.block.fenced.markdown", "foreground": "#ffffff","background": "#222", }, // Markdown: Fenced Bode Block { "scope": "punctuation.definition.fenced.markdown, variable.language.fenced.markdown", "foreground": "#636050","background": "#222222", }, // Markdown: Fenced Language { "scope": "variable.language.fenced.markdown", "foreground": "#7c7865", }, // Markdown: Separator { "scope": "meta.separator", "foreground": "#ffffff33","background": "#ffffff0f","font_style": "bold", }, // Markup: table { "scope": "markup.table", "foreground": "#b42a1d","background": "#ff3a281a", }, // LaTeX: Math Variables { "scope": "variable.other.math.tex", "foreground": "#e6db74", }, // Other: Removal { "scope": "other.package.exclude, other.remove", "foreground": "#d3201f", }, // Shell: builtin { "scope": "support.function.builtin.shell", "foreground": "#a6e22e", }, // Shell: variable { "scope": "variable.other.normal.shell", "foreground": "#66d9ef", }, // Shell: DOTFILES { "scope": "source.shell", "foreground": "#ffffff", }, // Shell: meta scope in loop { "scope": "meta.scope.for-in-loop.shell, variable.other.loop.shell", "foreground": "#fd971f", }, // Shell: Function name { "scope": "entity.name.function.shell", "foreground": "#a6e22e", }, // Shell: Quotation Marks { "scope": "punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell", "foreground": "#ffffff", }, // Shell: Meta Block { "scope": "meta.scope.case-block.shell, meta.scope.case-body.shell", "foreground": "#fd971f", }, // Shell: [] { "scope": "punctuation.definition.logical-expression.shell", "foreground": "#ffffff", }, // Shell: Comment { "scope": "comment.line.number-sign.shell", "foreground": "#7c7865","font_style": "italic", }, // Makefile: Comment { "scope": "comment.line.number-sign.makefile", "foreground": "#7c7865", }, // Makefile: Comment punctuation { "scope": "punctuation.definition.comment.makefile", "foreground": "#7c7865", }, // Makefile: Variables { "scope": "variable.other.makefile", "foreground": "#f92672", }, // Makefile: Function name { "scope": "entity.name.function.makefile", "foreground": "#a6e22e", }, // Makefile: Function { "scope": "meta.function.makefile", "foreground": "#66d9ef", }, // GitGutter deleted { "scope": "markup.deleted.git_gutter", "foreground": "#F92672", }, // GitGutter inserted { "scope": "markup.inserted.git_gutter", "foreground": "#A6E22E", }, // GitGutter changed { "scope": "markup.changed.git_gutter", "foreground": "#FC951E", }, // GitGutter ignored { "scope": "markup.ignored.git_gutter", "foreground": "#565656", }, // GitGutter untracked { "scope": "markup.untracked.git_gutter", "foreground": "#565656", }, // Nginx path { "scope": "string.other.path.nginx", "foreground": "#fc951e", }, ] } ================================================ FILE: OrgExtended.sublime-color-scheme ================================================ { "name": "OrgExtended", "variables": { "bgcol": "#071812", // Define variables here }, "globals": { "foreground": "#F8F8F2", "background": "var(bgcol)", "accent": "#ffffff", "selection": "#9D550F", "selectionBackground": "#000000", "selectionForeground": "#FF0000", "caret": "#FF55ff", "line_highlight": "#373730" }, "rules": [ { "foreground": "#191919FF", "scope": "col_999999FF", "background": "#999999FF" }, { "foreground": "#C1C1C1FF", "scope": "col_0645CDFF", "background": "#0645CDFF" }, { "foreground": "#E0E0E0FF", "scope": "col_1E74ACFF", "background": "#1E74ACFF" }, { "foreground": "#7E7E7EFF", "scope": "col_FEFEFEFF", "background": "#FEFEFEFF" }, { "foreground": "#939393FF", "scope": "col_0B0090FF", "background": "#0B0090FF" }, { "foreground": "#4C4C4CFF", "scope": "col_CCCCCCFF", "background": "#CCCCCCFF" }, { "foreground": "#D8D8D8FF", "scope": "col_765037FF", "background": "#765037FF" }, { "foreground": "#C4C4C4FF", "scope": "col_444444FF", "background": "#444444FF" }, { "foreground": "#C9C9C9FF", "scope": "col_66402FFF", "background": "#66402FFF" }, { "foreground": "#D7D7D7FF", "scope": "col_0066EEFF", "background": "#0066EEFF" }, { "foreground": "#2C2C2CFF", "scope": "col_FAA700FF", "background": "#FAA700FF" }, { "foreground": "#616161FF", "scope": "col_FFFF00FF", "background": "#FFFF00FF" }, { "foreground": "#DBDBDBFF", "scope": "col_1E747CFF", "background": "#1E747CFF" }, { "foreground": "#D0D0D0FF", "scope": "col_FFFF004C", "background": "#FFFF004C" }, { "foreground": "#BEBEBEFF", "scope": "col_0645ADFF", "background": "#0645ADFF" }, { "foreground": "#737373FF", "scope": "col_FFFF99FF", "background": "#FFFF99FF" }, { "foreground": "#2A2A2AFF", "scope": "col_AAAAAAFF", "background": "#AAAAAAFF" }, { "foreground": "#C6C6C6FF", "scope": "col_474356FF", "background": "#474356FF" }, { "foreground": "#5D5D5DFF", "scope": "col_DDDDDDFF", "background": "#DDDDDDFF" }, { "foreground": "#6E6E6EFF", "scope": "col_EEEEEEFF", "background": "#EEEEEEFF" }, { "foreground": "#3B3B3BFF", "scope": "col_BBBBBBFF", "background": "#BBBBBBFF" }, { "scope": "col_008000FF", "background": "#008000FF", "foreground": "#CBCBCBFF" }, { "scope": "col_D2B48CFF", "background": "#D2B48CFF", "foreground": "#383838FF" }, { "scope": "col_000000FF", "background": "#000000FF", "foreground": "#808080FF" }, { "scope": "col_339966FF", "background": "#339966FF", "foreground": "#F4F4F4FF" }, { "background": "#000000", "scope": "col_gutter", "foreground": "#ffffff" }, { "background": "#FFC0CBFF", "scope": "col_FFC0CBFF", "foreground": "#545454FF" }, { "background": "#800080FF", "scope": "col_800080FF", "foreground": "#B4B4B4FF" }, { "background": "#0000FFFF", "scope": "col_0000FFFF", "foreground": "#9D9D9DFF" }, { "background": "#FF0000FF", "scope": "col_FF0000FF", "foreground": "#CCCCCCFF" }, { "scope": "orgmode.break", "foreground": "#ed188a", }, { "scope": "orgmode.page", "foreground": "#f5eebf", }, { "scope": "orgmode.headline", "foreground": "#14adfa", "background": "#172822", "font_style": "bold italic", }, { "scope": "orgmode.headline2", "background": "#172822", "foreground": "#bb86fc", "background": "#171812", "font_style": "bold underline", }, { "scope": "orgmode.headline3", "foreground": "#03dac5", "font_style": "bold", }, { "scope": "orgmode.headline4", "foreground": "#dfe6a1", "font_style": "italic", }, { "scope": "orgmode.headline5", "foreground": "#018786", "font_style": "italic", }, { "scope": "orgmode.headline6", "foreground": "#afe3de", "font_style": "italic", }, { "scope": "orgmode.headline7", "foreground": "#afe3fe", "font_style": "italic", }, { "scope": "orgmode.headline8", "foreground": "#ffe3de", "font_style": "italic", }, { "scope": "orgmode.headline9", "foreground": "#fff3de", "font_style": "italic", }, // Stars before the last star in a headline // make these background to hide them. { "scope": "orgmode.preamble", "foreground": "var(bgcol)", "font_style": "italic", }, // Links can target these { "scope": "orgmode.target", "foreground": "#7c004a", "font_style": "italic", }, // Links can target these { "scope": "orgmode.target.bracket", "foreground": "#7c004a", "font_style": "bold", }, // Maybe I can use regions to collapse these? // Right now they look uber ugly { "scope": "orgmode.link", "foreground": "#3cd7fa", "font_style": "", }, { "scope": "orgmode.link.href", "foreground": "#9999aa", "font_style": "italic", }, { "scope": "orgmode.link.text", "foreground": "#4ce7fd", "font_style": "bold", }, { "scope": "orgmode.email", "foreground": "#a188b3", "font_style": "italic", }, { "scope": "orgmode.deadline", "foreground": "#d1771d", "font_style": "italic", }, { "scope": "orgmode.scheduled", "foreground": "#d1771d", "font_style": "italic", }, // #+PRIORITIES: A B C { "scope": "orgmode.controltag", "foreground": "#aaaaaa", }, // controltag.text also exists { "scope": "orgmode.controltag.tag", "foreground": "#aaaaaa", "font_style": "italic", }, // < DATETIME > { "scope": "orgmode.datetime", "foreground": "#b0a497", }, // [ DATETIME ] { "scope": "orgmode.unscheddatetime", "foreground": "#b0a497", }, // CLOSED: SCHEDULED: DEADLINE: { "scope": "orgmode.statekeyword", "foreground": "#d1771d", "font_style": "italic", }, { "scope": "orgmode.checkbox", "foreground": "#c9be7b", }, { "scope": "orgmode.checkbox.checked", "foreground": "#00FF00", }, { "scope": "orgmode.checkbox.blocked", "foreground": "#FF0000", }, { "scope": "orgmode.tags", "foreground": "#ded49b", }, { "scope": "orgmode.tags.headline", "foreground": "#deff9b", }, { "scope": "orgmode.priority", "foreground": "#c27532", }, { "scope": "orgmode.priority.value", "foreground": "#f5a55f", }, { "scope": "orgmode.priority.value.a", "foreground": "#e05a7b", }, { "scope": "orgmode.priority.value.b", "foreground": "#f59a76", }, { "scope": "orgmode.priority.value.c", "foreground": "#fab978", }, { "scope": "orgmode.priority.value.d", "foreground": "#f5d976", }, { "scope": "orgmode.priority.value.e", "foreground": "#bcbfae", }, { "scope": "orgmode.priority.value.general", "foreground": "#b59eb5", }, { "scope": "orgmode.state.todo", "foreground": "#e6ab4c", }, { "scope": "orgmode.state.blocked", "foreground": "#FF0000", }, { "scope": "orgmode.state.done", "foreground": "#47c94f", }, { "scope": "orgmode.state.cancelled", "foreground": "#bab9b8", }, { "scope": "orgmode.state.meeting", "foreground": "#dec7fc", }, { "scope": "orgmode.state.phone", "foreground": "#77ebed", }, { "scope": "orgmode.state.note", "foreground": "#d2a2e0", }, { "scope": "orgmode.state.doing", "foreground": "#9c9c17", }, { "scope": "orgmode.state.inprogress", "foreground": "#9c9c17", }, { "scope": "orgmode.state.flag", "foreground": "#9c9c17", }, { "scope": "orgmode.state.cleanup", "foreground": "#9c9c17", }, { "scope": "orgmode.state.next", "foreground": "#37dae6", }, { "scope": "orgmode.state.reassigned", "foreground": "#bab9b8", }, { "scope": "orgmode.state.fixed", "foreground": "#bab9b8", }, { "scope": "orgmode.tack", "foreground": "#c993c4", "font_style": "bold", }, { "scope": "orgmode.numberedlist", "foreground": "#c993c4", "font_style": "bold", }, { "scope": "orgmode.definition", "foreground": "#A2E8E4", "font_style": "bold", }, { "scope": "orgmode.definition.marker", "foreground": "#E1A2E8", "font_style": "bold", }, { "scope": "orgmode.follow_up", "foreground": "#FF0000", "font_style": "bold", }, { "scope": "orgmode.fence", "background": "#322830", "font_style": "bold", }, { "scope": "orgmode.fence.language", "background": "#322830", "foreground": "#f1bff2", "font_style": "bold", }, { "scope": "orgmode.raw.block", "background": "#252520", "font_style": "bold", }, { "scope": "orgmode.table.block", "background": "#272828", }, { "scope": "orgmode.bold", "foreground": "#aaffaa", "font_style": "bold", }, { "scope": "orgmode.italics", "foreground": "#aaffff", "font_style": "italic", }, { "scope": "orgmode.underline", "foreground": "#aaaaff", "font_style": "underline", }, { "scope": "orgmode.strikethrough", "foreground": "#aaaaaa", }, { "scope": "orgmode.code", "foreground": "#ffaaff", }, { "scope": "orgmode.verbatim", "foreground": "#ffaaaa", }, // MONOKAI EXTENDED COLORING // Generic colorization // function call { "scope": "support.function", "foreground": "#66d9ef", }, { "scope": "keyword", "foreground": "#f92672", }, { "scope": "comment", "foreground": "#75715e", }, { "scope": "string", "foreground": "#e6db74", }, { "scope": "constant.numeric", "foreground": "#be84ff", }, { "scope": "constant.language", "foreground": "#be84ff", }, { "scope": "meta.preprocessor", "foreground": "#be84ff", }, { "scope": "constant.character", "foreground": "#be84ff", }, { "scope": "constant.other", "foreground": "#be84ff", }, { "scope": "variable.language", "foreground": "#ffffff", }, { "scope": "variable.other", "foreground": "#ffffff", }, { "scope": "storage", "foreground": "#f92672", }, { "scope": "storage.type", "foreground": "#66d9ef", }, { "scope": "entity.name.class", "foreground": "#66D9EF", "font_style": "underline" }, { "scope": "entity.other.inherited-class", "foreground": "#a6e22e", "font_style": "italic underline" }, { "scope": "variable.parameter", "foreground": "#fd971f", "font_style": "italic" }, { "scope": "entity.name.tag", "foreground": "#f92672", }, { "scope": "entity.other.attribute-name", "foreground": "#a6e22e", }, { "scope": "entity.name.function", "foreground": "#a6e22e", }, { "scope": "entity.constant", "foreground": "#66d9ef", }, { "scope": "support.constant", "foreground": "#66d9ef", }, { "scope": "support.type", "foreground": "#A6E22E", "font_style": "italic", }, { "scope": "support.other.variable", }, { "scope": "string.constant", "foreground": "#66d9ef", }, { "scope": "string.regexp", "foreground": "#f6aa11", }, { "scope": "string.variable", "foreground": "#ffffff", }, { "scope": "punctuation.definition.variable", "foreground": "#ffffff", }, // Html / Xml { "scope": "meta.tag.sgml.doctype.xml", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype entity", "foreground": "#c8cecc", }, { "scope": "declaration.sgml.html declaration.doctype string", "foreground": "#c8cecc", }, { "scope": "content.block.html", "foreground": "#7c7865", }, { "scope": "entity.name.tag.script.html", "font_style": "italic",}, { "scope": "text.html.basic meta.tag.other.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.block.any", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.inline.any", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic source.js.embedded.html", "foreground": "#a6e22e", }, { "scope": "punctuation.separator.key-value.html", "foreground": "#a6e22e", }, { "scope": "text.html.basic entity.other.attribute-name", "foreground": "#a6e22e", }, { "scope": "text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html", "foreground": "#ffffff", }, { "scope": "punctuation.definition.string.begin.html", "foreground": "#ffffff", }, { "scope": "punctuation.definition.string.end.html", "foreground": "#ffffff", }, { "scope": "punctuation.definition.tag.end", "foreground": "#ffffff", }, { "scope": "punctuation.definition.tag.begin", "foreground": "#ffffff", }, { "scope": "punctuation.definition.tag", "foreground": "#ffffff", }, // Handlebars { "scope": "variable.parameter.handlebars", "foreground": "#f6aa11", }, { "scope": "support.constant.handlebars", "foreground": "#66d9ef", }, { "scope": "meta.function.block.start.handlebars", "foreground": "#66d9ef", }, // CSS { "scope": "meta.preprocessor.at-rule", "foreground": "#f6aa11", }, { "scope": "meta.selector.css entity.other.attribute-name.id", "foreground": "#f6aa11", }, { "scope": "meta.selector.css entity.other.attribute-name.class", "foreground": "#a6e22e", }, { "scope": "support.type.property-name.css", "foreground": "#66d9ef", }, { "scope": "meta.constructor.argument.css", "foreground": "#f6aa11", }, { "scope": "punctuation.section.property-list.css", "foreground": "#ffffff", }, { "scope": "punctuation.definition.tag.css", "foreground": "#f92672", }, { "scope": "punctuation.separator.key-value.css", "foreground": "#ffffff", }, { "scope": "punctuation.terminator.rule.css", "foreground": "#ffffff", }, { "scope": "entity.other.attribute-name.pseudo-element.css", "foreground": "#a6e22e", }, { "scope": "entity.other.attribute-name.pseudo-class.css", "foreground": "#a6e22e", }, { "scope": "entity.other.attribute-name.pseudo-selector.css", "foreground": "#a6e22e", }, // LESS Variables { "scope": "variable.other.less", "foreground": "#ffffff", }, { "scope": "variable.other.less.mixin", "foreground": "#e0fdce", "font_style": "italic"}, { "scope": "entity.other.attribute-name.pseudo-element.less", "foreground": "#ff9117", }, // Javascript { "scope": "meta.instance.constructor meta.function-call.constructor.js", "foreground": "#a6e22e", }, { "scope": "meta.template.expression.js punctuation.definition.template-expression.begin.js", "foreground": "#AFF132", }, { "scope": "meta.template.expression.js punctuation.definition.template-expression.end.js", "foreground": "#AFF132", }, { "scope": "meta.template.expression.js punctuation.accessor", "foreground": "#AFF132", }, { "scope": "meta.function.js", "foreground": "#a6e22e", }, { "scope": "entity.name.function.js", "foreground": "#a6e22e", }, { "scope": "support.function.dom.js", "foreground": "#a6e22e", }, { "scope": "source.js meta.function.js punctuation.separator.parameter.function.js", "foreground": "#ffffff", }, { "scope": "meta.property.object.js", "foreground": "#ffffff", }, { "scope": "keyword.operator.accessor.js", "foreground": "#ffffff", }, { "scope": "source.js meta.group.braces.curly constant.other.object.key.js punctuation.separator.key-value.js", "foreground": "#ffffff", }, { "scope": "source.js meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js", "foreground": "#ffffff", }, { "scope": "support.type.object.module.js", "foreground": "#66d9ef", }, { "scope": "source.js meta.function.declaration.js support.class.js", "foreground": "#66d9ef", }, { "scope": "support.type.object.module.js support.type.object.module.js", "foreground": "#a6e22e", }, { "scope": "storage.type.js", "foreground": "#66d9ef", "font_style": "italic",}, { "scope": "text.html.basic source.js.embedded.html", "foreground": "#ffffff", }, { "scope": "storage.type.function.js", "foreground": "#66d9ef", }, { "scope": "constant.numeric.js", "foreground": "#ae81ff", }, // JS: Literal language variable { "scope": "variable.language.arguments.js, variable.language.super.js, variable.language.this.js, variable.language.self.js, variable.language.proto.js, variable.language.constructor.js, variable.language.prototype.js", "foreground": "#66d9ef", "font_style": "italic",}, // JS: [] { "scope": "meta.brace.square.js", "foreground": "#ffffff", }, // JS: () { "scope": "meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js, punctuation.definition.group", "foreground": "#ffffff", }, // JS: object literal {} { "scope": "meta.brace.curly.js, meta.object-literal.js", "foreground": "#ffffff", }, // JSON String { "scope": "meta.structure.dictionary.json string.quoted.double.json", "foreground": "#cfcfc2", }, // CoffeeScript String Interpolated { "scope": "punctuation.section.embedded.coffee", "foreground": "#e69f66", }, // PHP: [] { "scope": "keyword.operator.index-start.php, keyword.operator.index-end.php", "foreground": "#ffffff", }, // PHP: Array { "scope": "meta.array.php", "foreground": "#ffffff", }, // PHP: Array() { "scope": "meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php", "foreground": "#e42e70", }, // PHP: Array Construct { "scope": "support.function.construct.php", "foreground": "#e42e70", }, // PHP: Storage Type Function { "scope": "storage.type.function.php", "foreground": "#f92672dd", }, // PHP: Numeric Constant { "scope": "constant.numeric.php", "foreground": "#be84ff", }, // PHP: New { "scope": "keyword.other.new.php", "foreground": "#f6aa11", }, // PHP: :: { "scope": "support.class.php", "foreground": "#ffffff", }, // PHP: Other Property { "scope": "variable.other.property.php", "foreground": "#f6aa11", }, // PHP: Class { "scope": "storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php", "foreground": "#a6e22e", }, // PHP: Inherited Class { "scope": "meta.other.inherited-class.php", "foreground": "#a6e22e", }, // PHP: Storage Type { "scope": "storage.type.php", "foreground": "#66d9ef", }, // PHP: Function { "scope": "entity.name.function.php", "foreground": "#66d9ef", }, // PHP: Function Construct { "scope": "support.function.construct.php", "foreground": "#a6e22e", }, // PHP: Function Call { "scope": "entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php", "foreground": "#ffffff", }, // PHP: Comment { "scope": "keyword.other.phpdoc", "foreground": "#7c7865", }, // PHP: Source Emebedded { "scope": "source.php.embedded.block.html", "foreground": "#ffffff", }, // Invalid { "scope": "invalid", "foreground": "#f8f8f0","background": "#f92672", }, // Invalid deprecated { "scope": "invalid.deprecated", "foreground": "#f8f8f0","background": "#ae81ff", }, // diff.header { "scope": "meta.diff, meta.diff.header", "foreground": "#75715e", }, // diff.deleted { "scope": "markup.deleted", "foreground": "#f92672", }, // diff.inserted { "scope": "markup.inserted", "foreground": "#a6e22e", }, // diff.changed { "scope": "markup.changed", "foreground": "#e6db74", }, // diff.range { "scope": "meta.diff, meta.diff.range", "foreground": "#3bc0f0", }, // Python: storage { "scope": "storage.type.class.python, storage.type.function.python, storage.modifier.global.python", "foreground": "#a6e22e", }, // Python: import { "scope": "keyword.control.import.python, keyword.control.import.from.python", "foreground": "#f92672dd", }, // Python: Support.exception { "scope": "support.type.exception.python", "foreground": "#66d9ef", }, // Perl: variables { "scope": "punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl", "foreground": "#e42e70", }, // Perl: functions { "scope": "support.function.perl", "foreground": "#66d9ef", }, // Perl: comments { "scope": "comment.line.number-sign.perl", "foreground": "#75715e","font_style": "italic", }, // Perl: quotes { "scope": "punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl", "foreground": "#ffffff", }, // Perl: char { "scope": "constant.character.escape.perl", "foreground": "#dc322f", }, // Ruby: Constant { "scope": "constant.language.ruby, constant.numeric.ruby", "foreground": "#ae81ff", }, // Ruby: Variable definition { "scope": "punctuation.definition.variable.ruby", "foreground": "#f6aa11", }, // Ruby: Function Name { "scope": "meta.function.method.with-arguments.ruby", "foreground": "#a6e22e", }, // Ruby: Variable { "scope": "variable.language.ruby", "foreground": "#ffffff", }, // Ruby: Function { "scope": "entity.name.function.ruby", "foreground": "#f6aa11", }, // Ruby: Keyword Control { "scope": "keyword.control.ruby, keyword.control.def.ruby", "foreground": "#a6e22e","font_style": "bold", }, // Ruby: Class { "scope": "keyword.control.class.ruby, meta.class.ruby", "foreground": "#a6e22e", }, // Ruby: Class Name { "scope": "entity.name.type.class.ruby", "foreground": "#66d9ef", }, // Ruby: Keyword { "scope": "keyword.control.ruby", "foreground": "#a6e22e", }, // Ruby: Support Class { "scope": "support.class.ruby", "foreground": "#66d9ef", }, // Ruby: Special Method { "scope": "keyword.other.special-method.ruby", "foreground": "#a6e22e", }, // Ruby: Constant Other { "scope": "variable.other.constant.ruby", "foreground": "#66d9ef", }, // Ruby: :symbol { "scope": "constant.other.symbol.ruby", "foreground": "#f6f080", }, // Ruby: Punctuation Section { "scope": "punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby", "foreground": "#f92672", }, // Ruby: Special Method { "scope": "keyword.other.special-method.ruby", "foreground": "#e42e70", }, // Markdown: plain { "scope": "text.html.markdown", "foreground": "#ffffff", }, // Markup: raw inline { "scope": "text.html.markdown markup.raw.inline", "foreground": "#ec3533", }, // Markdown: linebreak { "scope": "text.html.markdown meta.dummy.line-break", "foreground": "#e0eddd", }, // Markdown: heading { "scope": "markdown.heading, markup.heading | markup.heading entity.name, markup.heading.markdown punctuation.definition.heading.markdown", "foreground": "#fd971f", }, // Markup: italic { "scope": "markup.italic", "foreground": "#e42e70","font_style": "italic", }, // Markup: bold { "scope": "markup.bold", "foreground": "#f92672","font_style": "bold", }, // Markup: underline { "scope": "markup.underline", "foreground": "#a6e22e","font_style": "underline", }, // Markup: strike { "scope": "markup.strike", "foreground": "#cc4273", }, // Markdown: Blockquote { "scope": "markup.quote, punctuation.definition.blockquote.markdown", "foreground": "#66d9ef","font_style": "italic", }, // Markup: Quote { "scope": "markup.quote", "foreground": "#66d9ef","font_style": " italic", }, // Markdown: Link { "scope": "string.other.link.title.markdown", "foreground": "#66d9ef","font_style": "underline", }, // Markup: Raw block { "scope": "markup.raw.block", "foreground": "#ae81ff", }, // Markdown: List Items Punctuation { "scope": "punctuation.definition.list_item.markdown", "foreground": "#777777", }, // Markdown: Raw Block fenced { "scope": "markup.raw.block.fenced.markdown", "foreground": "#ffffff","background": "#222", }, // Markdown: Fenced Bode Block { "scope": "punctuation.definition.fenced.markdown, variable.language.fenced.markdown", "foreground": "#636050","background": "#222222", }, // Markdown: Fenced Language { "scope": "variable.language.fenced.markdown", "foreground": "#7c7865", }, // Markdown: Separator { "scope": "meta.separator", "foreground": "#ffffff33","background": "#ffffff0f","font_style": "bold", }, // Markup: table { "scope": "markup.table", "foreground": "#b42a1d","background": "#ff3a281a", }, // LaTeX: Math Variables { "scope": "variable.other.math.tex", "foreground": "#e6db74", }, // Other: Removal { "scope": "other.package.exclude, other.remove", "foreground": "#d3201f", }, // Shell: builtin { "scope": "support.function.builtin.shell", "foreground": "#a6e22e", }, // Shell: variable { "scope": "variable.other.normal.shell", "foreground": "#66d9ef", }, // Shell: DOTFILES { "scope": "source.shell", "foreground": "#ffffff", }, // Shell: meta scope in loop { "scope": "meta.scope.for-in-loop.shell, variable.other.loop.shell", "foreground": "#fd971f", }, // Shell: Function name { "scope": "entity.name.function.shell", "foreground": "#a6e22e", }, // Shell: Quotation Marks { "scope": "punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell", "foreground": "#ffffff", }, // Shell: Meta Block { "scope": "meta.scope.case-block.shell, meta.scope.case-body.shell", "foreground": "#fd971f", }, // Shell: [] { "scope": "punctuation.definition.logical-expression.shell", "foreground": "#ffffff", }, // Shell: Comment { "scope": "comment.line.number-sign.shell", "foreground": "#7c7865","font_style": "italic", }, // Makefile: Comment { "scope": "comment.line.number-sign.makefile", "foreground": "#7c7865", }, // Makefile: Comment punctuation { "scope": "punctuation.definition.comment.makefile", "foreground": "#7c7865", }, // Makefile: Variables { "scope": "variable.other.makefile", "foreground": "#f92672", }, // Makefile: Function name { "scope": "entity.name.function.makefile", "foreground": "#a6e22e", }, // Makefile: Function { "scope": "meta.function.makefile", "foreground": "#66d9ef", }, // GitGutter deleted { "scope": "markup.deleted.git_gutter", "foreground": "#F92672", }, // GitGutter inserted { "scope": "markup.inserted.git_gutter", "foreground": "#A6E22E", }, // GitGutter changed { "scope": "markup.changed.git_gutter", "foreground": "#FC951E", }, // GitGutter ignored { "scope": "markup.ignored.git_gutter", "foreground": "#565656", }, // GitGutter untracked { "scope": "markup.untracked.git_gutter", "foreground": "#565656", }, // Nginx path { "scope": "string.other.path.nginx", "foreground": "#fc951e", }, { "scope": "orgagenda.week.0", "foreground": "#550000", }, { "scope": "orgagenda.week.1", "foreground": "#007700", }, { "scope": "orgagenda.week.2", "foreground": "#770077", }, { "scope": "orgagenda.week.3", "foreground": "#0000ff", }, { "scope": "orgagenda.week.4", "foreground": "#999900", }, { "scope": "orgagenda.week.5", "foreground": "#007777", }, { "scope": "orgagenda.week.6", "foreground": "#aa5522", }, { "scope": "orgagenda.week.7", "foreground": "#cc99cc", }, { "scope": "orgagenda.week.8", "foreground": "#225522", }, { "scope": "orgagenda.week.9", "foreground": "#623456", }, ] } ================================================ FILE: OrgExtended.sublime-commands ================================================ [ // Give the user access to our settings in the preferences menu { "caption": "Preferences: OrgExtended Settings – Default", "command": "open_file", "args": { "file": "${packages}/OrgExtended/OrgExtended.sublime-settings" } }, { "caption": "Preferences: OrgExtended Settings – User", "command": "open_file", "args": { "file": "${packages}/User/OrgExtended.sublime-settings" } }, {"caption": "TableNext", "command":"table_editor_next_field"}, {"caption": "Org New File", "command": "org_new_file" }, {"caption": "Org Jump In File", "command": "org_jump_in_file" }, {"caption": "Org Tab Cycling", "command": "org_tab_cycling" }, {"caption": "Org Global Tab Cycling", "command": "org_global_tab_cycling" }, {"caption": "Org Fold All", "command": "org_fold_all" }, {"caption": "Org Unfold All", "command": "org_unfold_all" }, {"caption": "Org Fold Contents", "command": "org_fold_contents" }, {"caption": "Org Copy", "command": "org_copy" }, {"caption": "Org Refile", "command": "org_refile" }, {"caption": "Org Refile To EOF", "command": "org_refile_to_file" }, {"caption": "Org Refile File and Heading", "command": "org_refile_to_file_and_headline"}, {"caption": "Org Archive Subtree", "command": "org_archive_subtree" }, {"caption": "Org Archive All Done", "command": "org_archive_all_done" }, {"caption": "Org Open Refile", "command": "org_open_refile" }, {"caption": "Org Capture", "command": "org_capture" }, {"caption": "Org Rebuild Db", "command": "org_rebuild_db" }, {"caption": "Org Up", "command": "org_up" }, {"caption": "Org Down", "command": "org_down" }, {"caption": "Org Remove All Folds", "command": "org_remove_all_folds" }, {"caption": "Org Change Todo", "command": "org_todo_change" }, {"caption": "Org Change Priority", "command": "org_priority_change" }, {"caption": "Org Change Indent", "command": "org_change_indent" }, {"caption": "Org Change DeIndent", "command": "org_change_de_indent" }, {"caption": "Org Reload File", "command": "org_reload_file" }, {"caption": "Org Fold Thing", "command": "org_fold_thing" }, {"caption": "Org Fold Others", "command": "org_fold_all_but_me" }, {"caption": "Org Move Heading Up", "command": "org_move_heading_up" }, {"caption": "Org Move Heading Down", "command": "org_move_heading_down" }, {"caption": "Org Open Link", "command": "org_open_link" }, {"caption": "Org Fold All Links", "command": "org_fold_all_links" }, {"caption": "Org Show Images", "command": "org_show_images" }, {"caption": "Org Hide Images", "command": "org_hide_images" }, {"caption": "Org Show Image", "command": "org_show_image" }, {"caption": "Org Hide Image", "command": "org_hide_image" }, {"caption": "Org Link To File", "command": "org_link_to_file" }, {"caption": "Org Jump To Backlink", "command": "org_jump_to_backlinks" }, {"caption": "Org Show Backlinks", "command": "org_show_backlinks" }, {"caption": "Org Search Links", "command": "org_search_links" }, {"caption": "Org Insert Heading Sibling", "command": "org_insert_heading_sibling" }, {"caption": "Org Insert Heading Child", "command": "org_insert_heading_child" }, {"caption": "Org Insert Date Inactive", "command": "org_insert_date_inactive" }, {"caption": "Org Insert Date Active", "command": "org_insert_date_active" }, {"caption": "Org Insert Today Inactive", "command": "org_insert_today_inactive" }, {"caption": "Org Insert Today Active", "command": "org_insert_today_active" }, {"caption": "Org Insert Now Inactive", "command": "org_insert_now_inactive" }, {"caption": "Org Insert Now Active", "command": "org_insert_now_active" }, {"caption": "Org Insert Created Property", "command": "org_insert_created_property" }, {"caption": "Org Insert Drawer", "command": "org_insert_drawer" }, {"caption": "Org Insert Property Drawer", "command": "org_insert_property_drawer" }, {"caption": "Org Insert Property", "command": "org_insert_property" }, {"caption": "Org Set Today", "command": "org_set_today" }, {"caption": "Org Clock In", "command": "org_clock_in" }, {"caption": "Org Clock Out", "command": "org_clock_out" }, {"caption": "Org Clear Clock", "command": "org_clear_clock" }, {"caption": "Org Recalculate Clock", "command": "org_recalculate_clock" }, {"caption": "Org Jump To Clock", "command": "org_jump_to_clock" }, {"caption": "Org Update Active Clock", "command": "org_update_clock" }, {"caption": "Org Todo View", "command": "org_todo_view" }, {"caption": "Org Filtered Todo View", "command": "org_tag_filtered_todo_view" }, {"caption": "Org Exec Dynamic Block", "command": "org_execute_dynamic_block" }, {"caption": "Org Exec Source Block", "command": "org_execute_source_block" }, {"caption": "Org Exec All Source Blocks", "command": "org_execute_all_source_blocks"}, {"caption": "Org Exec Inline Source Block","command": "org_execute_inline_source_block"}, {"caption": "Org Tangle File", "command": "org_tangle_file" }, {"caption": "Org Checkbox Toggle", "command": "org_toggle_checkbox" }, {"caption": "Org Recalc Checkbox", "command": "org_recalc_checkbox_summary" }, {"caption": "Org Recalc All Checkbox", "command": "org_recalc_all_checkbox_summaries" }, {"caption": "Org Add Checkbox Summary", "command": "org_insert_checkbox_summary" }, {"caption": "Org Jump To CustomId", "command": "org_jump_to_custom_id" }, {"caption": "Org Jump To Today", "command": "org_jump_to_today" }, {"caption": "Org Insert Tag", "command": "org_insert_tag" }, {"caption": "Org Remove Tag", "command": "org_remove_tag" }, {"caption": "Org Remove All Tags", "command": "org_remove_all_tags" }, {"caption": "Org Fix Tags", "command": "org_fix_tags" }, {"caption": "Org Closed", "command": "org_insert_closed" }, {"caption": "Org Insert CustomId", "command": "org_insert_custom_id" }, {"caption": "Org Schedule", "command": "org_schedule" }, {"caption": "Org Deadline", "command": "org_deadline" }, {"caption": "Org Timestamp", "command": "org_active_timestamp" }, {"caption": "Org Create Link", "command": "org_create_link" }, {"caption": "Org Link To Today", "command": "org_link_to_today" }, {"caption": "Org Update Numbered List", "command": "org_update_numbered_list" }, {"caption": "Org Append Numbered List", "command": "org_append_numbered_list" }, {"caption": "Org Select Subtree", "command": "org_select_subtree" }, {"caption": "Org Select Entity", "command": "org_select_entity" }, {"caption": "Org Select Href", "command": "org_select_link_href" }, {"caption": "Org Copy Subtree", "command": "org_copy_subtree" }, {"caption": "Org Copy Entity", "command": "org_copy_entity" }, {"caption": "Org Copy Href", "command": "org_copy_link_href" }, {"caption": "Org Sort List", "command": "org_sort_list" }, {"caption": "Org Create Heading Id", "command": "org_create_heading_id" }, {"caption": "Org Insert Effort", "command": "org_insert_effort" }, {"caption": "Org Insert Archive Tag", "command": "org_insert_archive_tag" }, {"caption": "Org Execute Call", "command": "org_execute_call_comment" }, // Agenda {"caption": "Org Agenda Goto", "command": "org_agenda_go_to" }, {"caption": "Org Agenda Goto Split", "command": "org_agenda_go_to_split" }, {"caption": "Org Agenda Change Todo", "command": "org_agenda_change_todo" }, {"caption": "Org Agenda Change Priority", "command": "org_agenda_change_priority" }, {"caption": "Org Agenda ClockIn", "command": "org_agenda_clock_in" }, {"caption": "Org Agenda ClockOut", "command": "org_agenda_clock_out" }, {"caption": "Org Agenda Insert Tag", "command": "org_agenda_insert_tag" }, {"caption": "Org Agenda Insert Effort", "command": "org_agenda_insert_effort" }, {"caption": "Org Agenda Insert Assign", "command": "org_agenda_assign" }, {"caption": "Org Agenda Insert Id", "command": "org_agenda_id" }, {"caption": "Org Agenda Day View", "command": "org_agenda_day_view" }, {"caption": "Org Agenda Custom View", "command": "org_agenda_custom_view" }, {"caption": "Org Agenda Rebuild Notices", "command": "org_rebuild_notifications" }, {"caption": "Org Agenda Choose View", "command": "org_agenda_choose_custom_view"}, {"caption": "Org Agenda Goto Next Day", "command": "org_agenda_goto_next_day" }, {"caption": "Org Agenda Goto Prev Day", "command": "org_agenda_goto_prev_day" }, // Date Picker {"caption": "Org Date Picker", "command": "org_date_picker" }, {"caption": "Org Date Next Day", "command": "org_date_picker_next_day" }, {"caption": "Org Date Prev Day", "command": "org_date_picker_prev_day" }, // Export {"caption": "Org Export File As Reveal Js","command": "org_export_file_reveal_js" }, {"caption": "Org Export File As Html", "command": "org_export_file_org_html" }, {"caption": "Org Export Subtree As Html", "command": "org_export_subtree_as_org_html" }, {"caption": "Org Export File As Pdf", "command": "org_export_file_as_pdf" }, {"caption": "Org Export File As Latex", "command": "org_export_file_as_latex" }, {"caption": "Org Export File As Dnd", "command": "org_export_file_as_dnd_pdf" }, {"caption": "Org Pandoc File To Html", "command": "org_export_file_as_html" }, {"caption": "Org Pandoc Subtree To Html", "command": "org_export_subtree_as_html" }, // Table Management {"caption": "Org Import Csv", "command": "org_import_table_from_csv" }, {"caption": "Org Convert Region To Table", "command": "org_convert_selection_to_table" }, {"caption": "Org Insert Blank Table", "command": "org_insert_blank_table" }, {"caption": "Org Clear Table Highlights", "command": "org_clear_table_regions" }, {"caption": "Org Highlight Formula", "command": "org_highlight_formula" }, {"caption": "Org Eval Cell", "command": "org_fill_in_formula_from_cell" }, {"caption": "Org Show Table Rows", "command": "org_show_table_rows" }, {"caption": "Org Hide Table Rows", "command": "org_hide_table_rows" }, {"caption": "Org Plot Table", "command": "org_plot_table" }, {"caption": "Org Execute All Tables", "command": "org_execute_all_tables" }, {"caption": "Org Execute Formula", "command": "org_execute_formula" }, {"caption": "Org Edit Table Formula", "command": "org_edit_formula_for_cell" }, {"caption": "Org Clear Table Cell", "command": "org_clear_cell" }, {"caption": "Org Table Exec Below", "command": "org_exec_on_column" }, {"caption": "Org Insert Rnd Table Row", "command": "org_insert_random_row_from_table" }, // Internal Mechanics {"caption": "Org Internal Keymap Gen", "command": "org_create_keymap_doc" }, {"caption": "Org Download Highligh Js", "command": "org_download_highligh_js" }, {"caption": "Org Select Color Scheme", "command": "org_select_existing_color_scheme" }, {"caption": "Org Create Color Scheme From Active", "command": "org_create_color_scheme_from_active" }, // Resources {"caption": "Org Show Worklog", "command": "org_build_dev_docs" }, {"caption": "Org Show TestFile", "command": "org_show_testfile" }, {"caption": "Org Show Table Tests", "command": "org_show_table_tests" }, {"caption": "Org Show Source Tests", "command": "org_show_source_block_tests" }, // Day Page {"caption": "Org Day Page Create", "command": "org_day_page_create" }, {"caption": "Org Day Page Previous", "command": "org_day_page_previous" }, {"caption": "Org Day Page Next", "command": "org_day_page_next" }, // Internal Maintenance Commands //{"caption": "Org Output Table Docs", "command": "org_doc_table" }, //{"caption": "Org Internal Syntax Gen", "command": "org_regen_syntax_template" }, //{"caption": "Org Test Thing", "command": "org_show_item" }, //{"caption": "Org Test Durations", "command": "org_test_duration" }, //{"caption": "Org Test PLists", "command": "org_plist_test" }, //{"caption": "Org Test Template", "command": "org_test_template" }, // Beancount {"caption": "Org Beancount Create", "command": "beancount_new_file" }, {"caption": "Org Beancount Transaction", "command": "beancount_new_transaction" }, // Trello: // Trello commands allow you to 2 way sync with a trello board. It does however require // that you have the Trello package installed as I parasitically use that package. {"caption": "Org Trello Sync Board", "command": "org_trello_sync_board" }, // Timesheet System {"caption": "Org Timesheet Table", "command": "org_insert_timesheet" }, {"caption": "Org Choose Timesheet Table", "command": "org_choose_timesheet" }, {"caption": "Org Timesheet Mermaid Gantt", "command": "org_generate_mermaid_gantt_chart" }, {"caption": "Org Timesheet Google Gantt", "command": "org_generate_google_gantt_chart" }, ] ================================================ FILE: OrgExtended.sublime-keymap ================================================ [ { "keys": ["ctrl+alt+x"], "command": "org_capture" }, { "keys": ["ctrl+up"], "command": "org_up" , "context": [{ "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }]}, { "keys": ["ctrl+down"], "command": "org_down" , "context": [{ "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }]}, { "keys": ["tab"], "command": "org_tab_cycling", "context": [{ "key": "eol_selector", "operator": "equal", "operand": "text.orgmode" }]} ] ================================================ FILE: OrgExtended.sublime-project ================================================ { "folders": [ { "path": "." } ] } ================================================ FILE: OrgExtended.sublime-settings ================================================ { // The color scheme to use for the capture buffer // Right now I only have a light and dark scheme. In the future // I hope to allow your color scheme to impact the scheme and to provide // a means of extending your scheme with the org colors "color_scheme": "Packages/OrgExtended/OrgExtended.sublime-color-scheme", // Turn on TableEditor for orgmode "enable_table_editor": true, "table_editor_syntax": "EmacsOrgMode", // We turn on the autocompletions feature // So we can show filenames in links "auto_complete": true, "auto_complete_selector": "text.orgmode", //"auto_complete_commit_on_tab": true, "auto_complete_use_index": true, // Where should tags start in a headline? // Tags will get inserted at this column "tagColumn" : 80, // Files which should be loaded outside Sublime when a file link is followed "file_exclude_patterns": [ "*.pdf", "*.doc", "*.docx", "*.docm", ], // ============================================================ // ORG DIRS: // Where are your org files? "orgDirs": [ "c:\\Users\\ian\\notes" ], // Specific files to add vs whole directories //"orgFiles": [ //], // Directories to exclude from parsing org files //"orgExcludeDirs": [], // Files to be excluded from org parsing //"orgExcludeFiles": [], // The Org DB will not load a file without one of these file extensions. // It assumes we are somehow erroneously trying to load something wrong. // If you create your own #+ARCHIVE: entries make sure the extensions are in here. "validOrgExtensions": [ ".org", ".org_archive"], // Startup is equivalent to #+STARTUP: showall in a file // but has an effect on all org files. This controls what mode // the org files show as globally. Valid values are: // - showall - everything but drawers is shown // - showeverything - even drawers are shown. // - contents - like a table of contents, contents of headings is hidden but all headings shown // - overview - only top level headings are shown. // - noinlineimages - do not show images inline // - inlineimages - show inline images in file // #+STARTUP: inlineimages // #+STARTUP: noinlineimages "startup": ["showall", "noinlineimages"], // override for logdone. Will force CLOSED: entries even if it is not in your startup. //"logdone": true, // Used in the tag selector for the font to use in the popup //"input_font_face": "Arial", // List of priorities we can insert / change to // NOTE: only the letters (below) can be highlighted at the moment // I haven't found a good way to modify the grammer dynamically. //"priorities": ["A","B","C","D","E"] // Globally where should things be archived? // So the following will expand to myfile.org_archive // NOTE: org allows for datetree/ and a few other options // we probably only support a subset of those // properly "archive": "%s_archive::* Archive", // When looking for images in org files, where might those images be located? // The first path in this list is where generated images will be placed. // If this list is empty a subdir of images under the first entry in orgDirs will be used. "imageSearchPath": [], "resolver.jira.url":"http://sandbox.onjira.com/browse/%s", "resolver.jira.pattern":"^(jira|j):(?P.+)$", //email "resolver.email.url":"mailto:%s", "resolver.email.pattern":"^(?Pemail|mailto):(?P[^/]+)(/(?P.+))?$", //prompt "resolver.prompt.pattern":"^(cmd:|prompt:)(?P.+)$", //file: Only these extensions will be opened in sublime when in a link others will be opened externally. "resolver.local_file.force_into_sublime":"'*.txt', '*.org', '*.py', '*.rb', '*.html', '*.css', '*.js', '*.php', '*.c', '*.cpp', '*.h', '*.png', '*.jpg', '*.gif', '*.cs'", //"resolver.local_file.pattern":"^(file:)?(?P.+?)(?::(?P\\d+)(?::(?P\\d+))?)?$", // ============================================================ // CAPTURE // The quick capture buffer gets this name "captureBufferName": "*capture*", // What file format should we write out as. This should be a python encoding value // CAN BE: // - utf-8 // - utf-16 // - utf-32 // SEE: https://docs.python.org/3.3/library/codecs.html#standard-encodings "captureWriteFormat": "utf-8", // Captures go into this file for refiling later. "refile": "D:\\Build\\notes\\refile.org", // Org Capture templates $0 is where the cursor ends up. "captureTemplates": [ // OLD DO NOTE USE TEMPLATE TYPE //{ // "name": "Todo", // "template": // "* TODO $0\n :PROPERTIES:\n:CREATED: [{datetime}]\n:END:\n " //}, // PREFER THE SNIPPET TYPE { "name": "Todo", "type": "entry", "snippet": "todo_heading", "target": ["file","{refile}"], }, { "name": "Note", "type": "entry", "snippet": "note_heading", "target": ["file","{refile}"], }, { "name": "Capture", "type": "entry", "snippet": "capture_heading", "target": ["file","{refile}"], }, { "name": "Meeting", // types: // entry - An Org mode node, with a headline. Will be filed as the child of the target entry or as a top-level entry // item - A plain list item, placed in the first plain list at the target location // checkitem - A checkbox item. This only differs from the plain list item by the default template // table-line - A new line in the first table at the target location. Where exactly the line will be inserted depends on the properties :prepend and :table-line-pos (see below) // plain - Text to be inserted as it is. "type": "entry", // targets: // ------------- // SUPPORTED: // file - text appened at end of file. // id - text appened to existing org id in db // file+headline - unique headline in file ["file+headline","filename","headline"] // file+olp - full path to headline // file+regexp - heading is a match to the regexp // clock - insert under current item being clocked. // file+datetree - NOT YET SUPPORTED This target creates a heading in a date tree for today’s date. If the optional outline path is given, the tree will be built under the node it is pointing to // function - NOT YET SUPPORTED generic function to find location for you // BUILD IN SYMBOLS: // {date} - current date // {time} - current time // {file} - current filename // {daypage}. - todays daypage (if setup) "target": ["file","{refile}"], // "target": ["file+headline","{daypage}","Headline Text"], // "target": ["file+olp" ,"{refile}" ,"Heading 1", "Heading 2", ...], // We have: // - todo_heading - make a todo heading at target // - note_heading - make a note heading at target // - meeting_heading - make a meeting heading at target // - plain_template - just put cursor at target // You can add your own in the orgsnippets folder in Users. "snippet": "meeting_heading", // This can be panel or direct // Panel will open up a panel that copies its contents to your target when // the panel loses focus. Direct will open up the actual file at your traget // during the capture "openas": "panel", // NONE OF THESE ARE CURRENTLY SUPPORTED // HOPEFULLY IN THE FUTURE WE WILL SUPPORT THEM //"template": "* MEETING $0\n :PROPERTIES:\n:CREATED: [{datetime}]\n:END:\n " // prepend - Normally new captured information will be appended at the target location (last child, last table line, last list item, …). Setting this property changes that. // immediate-finish - When set, do not offer to edit the information, just file it away immediately. This makes sense if the template only needs information that can be added automatically. // empty-lines - Set this to the number of lines to insert before and after the new item. Default 0, and the only other common value is 1. // clock-in - Start the clock in this item. // clock-keep - Keep the clock running when filing the captured entry. // clock-resume - If starting the capture interrupted a clock, restart that clock when finished with the capture. Note that clock-keep has precedence over clock-resume. When setting both to non-nil, the current clock will run and the previous one will not be resumed. // time-prompt - Prompt for a date/time to be used for date/week trees and when filling the template. Without this property, capture uses the current date and time. Even if this property has not been set, you can force the same behavior by calling org-capture with a C-1 prefix argument. // tree-type - When week, make a week tree instead of the month tree, i.e., place the headings for each day under a heading with the current ISO week. // unnarrowed - Do not narrow the target buffer, simply show the full buffer. Default is to narrow it so that you only see the new material. // table-line-pos - Specification of the location in the table where the new line should be inserted. It should be a string like ‘II-3’ meaning that the new line should become the third line before the second horizontal separator line. // kill-buffer - If the target file was not yet visited when capture was invoked, kill the buffer again after capture is completed. // no-save - Do not save the target file after finishing the capture. // THESE ARE IMPLEMENTED: // These are python date strings and allow you to control the header // format of your datetree // "year-format": "%Y", - The root of your datetree * 2021 // "month-format": "%Y-%m %B", - The month section ** 2021-11 November // "day-format", "%Y-%m-%d %A", - The day section *** 2021-11-27 Saturday "properties": [], } ], // ============================================================ // AGENDA // What does the composite agenda view show? // You can add your own views but that is done through code. // Right now I ONLY have this one composite view. "AgendaCustomViews": { "Default": ["Calendar", "Week", "Day", "Blocked Projects", "Next Tasks", "Loose Tasks"], "Todos": ["Todos"], "Notes": ["Notes"], "Flags": ["Todos : tagfilter |TAG1 |OTHERTAGS", "Todos : tagfilter OTHERTAGS"], }, // By default our first day of the week is Sunday // But some people prefer the first day to be monday // Set first day to Monday "firstDayOfWeek": "Sunday", // Configure the agenda header format //"agendaHeaderFormat": "%A \t%d %B %Y", // Include files outside of orgDirs in the agenda // (open files etc) "agendaIncludeFilesOutsideOrgDir": false, // Day view starts at 6am and ends at 7pm "agendaDayStartTime": 6, "agendaDayEndTime": 19, // What defines a project? // nested_todo TODO with sub TODO's. // tag Heading with a :PROJECT: tag // property Heading with a :PROJECT: True property "agendaProjectIs": "nested_todo", // If you would like to only see the work week // set num days to 5 and the firstDayOfWeek above // to Monday "agendaWeekViewNumDays": 7, // Do you want todo views to pop up the filter box when they pop up or // only after you ask for it. This is an input panel at the bottom of the view // that lets you filter out todos that do not match a regex as you type it. "agendaTodoFilterByDefault": false, // Do you want the system to delete clocking entries smaller than 1 minute // or keep them? "clockingSubMinuteClocks": true, // We follow the same sort of syntax as the normal orgmode for todos. // I don't have smart syntax highlighting on these. The grammar file gives // me some basic highlighting, but only for this set. I am hoping in the future I can figure // out some way to make this extensible. "todoStates": ["TODO","NEXT", "BLOCKED","WAITING","FLAG", "CLEANUP", "IN-PROGRESS", "DOING","|", "CANCELLED","REASSIGNED", "DONE","MEETING","PHONE","NOTE", "FIXED"], // ============================================================ // NOTIFICATION THREAD // This is the template used to notify outside of sublime on org notifications //"ExternalNotificationCommand": ["C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe", "-ExecutionPolicy", "Unrestricted", ".\\balloontip.ps1", "\"{todo}\"" , "\"{time}\""] // When notice thread is polling, how far off does event need to be? "notifyHoursBefore": 0, "notifyMinsBefore": 15, // How often to check if an event is up? (in minutes) "noticePeriod": 1, // ============================================================ // Pandoc export uses these to determine the style and the location of pandoc executable // "PandocPath": "C:\Program Files\Pandoc\pandoc.exe", // "PandocStyle": "blocky", // Turning this on allows you to write table functions and symbol // extensions in: Packages/User/orgtable/myfunction.py // // These can be used in the TBLFM expressions on tables. // These are turned OFF by default and can be enabled // by you when you want to add your own extensions. //"enableTableExtensions": true, // By default extensions are lazy loaded the first time you encounter a table // when writing an extension this can become tedious fast as it means you have to // reload sublime to test your changes. Turn this on and sublime will forcibly reload // extensions every time it goes to execute them. //"forceLoadExternalExtensions": true, // Turning this on will turn on a lot of additional logging to help diagnose problems // during debugging. Do not enable unless you really want that. // You will need to restart sublime to get this. // "enableDebugLogging": true, // This will cause org extended to aggressively re-fold a buffer marked as #+STARTUP: content when you refocus the buffer // Some people may find this jarring so it is hidden behind an option for now. //"onFocusRespectStartupFolds": true, // ============================================================ // DAY PAGE // Path where we would like day pages created //"dayPagePath": "PATH", // // The name of your new day page snippet (without the file extention!) //"dayPageSnippet": "filename", // // How should we name day pages? NOTE: This format is how we find old day pages // This means if you change this we may not be able to find old content. //"dayPageNameFormat": "%a_%Y_%m_%d", // // Do you want to use one page per day or one page per week? // This only impacts the creation of a page not existing pages. // set to "week" if you would like one page per week. //"dayPageMode": "day", // // When in week mode what day should be the official day for your // logs? //"dayPageModeWeekDay": "Monday", // // Close out the previous day with a #+FILETAGS: ARCHIVE tag when // a new day page is created //"dayPageArchiveOld": true, // // Copy tasks in a TODO state from the previous day to a new day page. //"dayPageCopyOpenTasks": true, // ============================================================ // Source Block Handler Paths // We do not automatically locate these at the moment. //"nodejsPath": "C:\\Program Files\\nodejs\\node.exe", //"bashPath": "C:\\Windows\\System32\\wsl.exe", //"graphviz": "C:\\Path\\To\GraphvizExes", //"plantuml": "C:\\Path\\To\\Plantuml.jar", //"ditaa": "C:\\Path\\To\\Ditaa.jar", //"mermaid": "C:\\Path\\To\\mmdc", //"gnuplot": "C:\Program Files\gnuplot\bin\gnuplot.exe" //"perlPath": "", // For the plantuml source blocks, where is planuml found? "plantuml": "D:\\Build\\.imacs\\plantuml.jar", "mermaid": "C:/Users/ihdav/node_modules/.bin/mmdc", // These source block handlers are built in to org mode. If you want to replace them with your own // version: // 1. write a handler in Packages/User/orgsrc folder // 2. remove them from your list in your settings file. "builtinSourceBlockHandlers": ["plantuml", "graphviz", "ditaa", "mermaid", "powershell", "python", "gnuplot", "cmd", "sh", "javascript", "perl", "csharp"], // These are source block aliases for languages listed in the builtinSourceBlockHandlers "builtinSourceBlockAliases": { "bash": "sh", "bat": "cmd", "js": "javascript" }, // These are the default state for all source execution. You can change the defaults by changing this plist // Only exports curently supports default = code at the moment. It's a bit of a hack to avoid conflicts // with the htmlDefaultSkipSrc option. "orgBabelDefaultHeaderArgs": ":session none :results replace :exports default :cache no :noweb no", // During Html export some language types we skip exporting source by default unless the user // has explicitly overriden the export. This option lets you control which languages we do that for. "htmlDefaultSkipSrc": ["plantuml","graphviz","ditaa","gnuplot"], // Should we execute our source blocks on export? "htmlExecuteSourceOnExport": true, // Include roam tag in description when inserting file link "insertRoamTagToFileLink": true, // LaTeX path for Org Export File As Pdf // "latex2Pdf": "C:\\texlive\\2021\\bin\\win32\\pdflatex.exe", // // If you need to control the language mapping you can do so here // using this table. A quick example is below where we are mapping to [5.2]Lua // rather than 5.0 Lua which is the default. // // LateX SRC_BLOC - LaTex Listing package language matching // "latexListingPackageLang": { // "python": "Python", // "lua": "[5.2]Lua", // }, // ============================================================ // BACKLINKS // // Turn this off if you do not want the system to try to auto // update backlinks for you in the backlinks display "backlinksUpdate": true, } ================================================ FILE: OrgExtended.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html file_extensions: - org - org_archive # Generic parent scope of the file scope: text.orgmode version: 2 variables: datetime: "<\\d{4}-\\d{2}-\\d{2}(?:\\s*\\w{3})?\\s*(\\d{2}\\:\\d{2}(-\\d{2}\\:\\d{2})?)?\\s*([+]*\\d[wdmy])?>" unscheddatetime: "\\[\\d{4}-\\d{2}-\\d{2}(?:\\s*\\w{3})?\\s*(\\d{2}\\:\\d{2})?\\s*([+]*\\d[wdmy])?\\]" tags: "(^|):[\\w\\d:]+:" priority: '\s*\[((\#A)|(\#B)|(\#C)|(\#D)|(\#E)|(\#[a-zA-Z0-9]+))\]\s+' state: (TODO)|(BLOCKED)|(WAITING)|(CANCELLED)|(DONE)|(MEETING)|(PHONE)|(NOTE)|(FLAG)|(CLEANUP)|(IN-PROGRESS)|(DOING)|(NEXT)|(REASSIGNED)|(FIXED) beginmrk: BEGIN_SRC|begin_src endmrk: END_SRC|end_src beginsrc: '(\s*\#\+({{beginmrk}})\s+)' endsrc: '(\s*\#\+({{endmrk}})\s*)' contexts: # The prototype context is prepended to all contexts but those setting # meta_include_prototype: false. #prototype: #- include: comments header-matches: - match: $ pop: true - match: ({{state}}\s+)?({{priority}})?[^\[\]:\n]*(\[\d*[/%]\d*\])?({{tags}})? captures: 2: variable.parameter orgmode.state.todo 3: variable.parameter orgmode.state.blocked 4: variable.parameter orgmode.state.waiting 5: variable.parameter orgmode.state.cancelled 6: variable.parameter orgmode.state.done 7: variable.parameter orgmode.state.meeting 8: variable.parameter orgmode.state.phone 9: variable.parameter orgmode.state.note 10: variable.parameter orgmode.state.flag 11: variable.parameter orgmode.state.cleanup 12: variable.parameter orgmode.state.inprogress 13: variable.parameter orgmode.state.doing 14: variable.parameter orgmode.state.next 15: variable.parameter orgmode.state.reassigned 16: variable.parameter orgmode.state.fixed 17: string.quoted orgmode.priority 18: string.quoted orgmode.priority.value 19: string.quoted orgmode.priority.value.a 20: string.quoted orgmode.priority.value.b 21: string.quoted orgmode.priority.value.c 22: string.quoted orgmode.priority.value.d 23: string.quoted orgmode.priority.value.e 24: string.quoted orgmode.priority.value.general 25: string.quoted orgmode.checkbox.summary 26: entity.name.tag.orgmode orgmode.tags.header main: # The main context is the initial starting point of our syntax. # Include other contexts from here (or specify them directly). #- include: keywords #- include: numbers #- include: strings # --- # Todo investigate what this actually is? - match: ^\s*\-\-\- [^\n]* scope: comment orgmode.page # ~~~~~ # Todo investigate what this is? - match: ^\s*[~]+ [^\n]* scope: comment orgmode.break # Generic headline, TODO: Make multiple of these so we can color them # and sub captures so we can hide the extraneous stars # embed_scope: entity.name.function.orgmode orgmode.headline - match: ^\s*[*]\s+ push: - meta_scope: entity.name.class.orgmode orgmode.headline - include: header-matches - match: ^\s*([*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.function.orgmode orgmode.headline2 - include: header-matches - match: ^\s*([*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.other.attribute-name.orgmode orgmode.headline3 - include: header-matches - match: ^\s*([*][*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.section.orgmode orgmode.headline4 - include: header-matches - match: ^\s*([*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.type.orgmode orgmode.headline5 - include: header-matches - match: ^\s*([*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline6 push: - meta_scope: entity.name.filename orgmode.headline6 - include: header-matches - match: ^\s*([*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline7 push: - meta_scope: entity.name.filename orgmode.headline7 - include: header-matches - match: ^\s*([*][*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline8 push: - meta_scope: entity.name.filename orgmode.headline8 - include: header-matches - match: ^\s*([*][*][*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline9 push: - meta_scope: entity.name.filename orgmode.headline9 - include: header-matches - match: ^\s*(\|.+\|) captures: 1: markup.raw.block orgmode.table.block scope: orgmode.table # DEADLINE: - match: "(DEADLINE:)\\s+({{datetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.datetime scope: orgmode.deadline # SCHEDULED: - match: "(SCHEDULED:)\\s+({{datetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.datetime scope: orgmode.scheduled # CLOSED: [DATETIME] - match: "(CLOSED:)\\s+({{unscheddatetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.unscheddatetime scope: orgmode.closed # numbered list - match: "^\\s*([0-9]+[.)])\\s+(([^:]+\\s+)(::))?" captures: 1: constant.numeric 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.numberedlist # bullet list - match: "^\\s*(\\-) (([^:]+\\s+)(::))?" captures: 1: constant.character 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.tack.minus # bullet list - match: "^\\s*(\\+) (([^:]+\\s+)(::))?" captures: 1: constant.character 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.tack.plus # To follow up: -> and => - match: "^\\s*(\\-\\>|\\=\\>) " scope: orgmode.follow_up # [-] Checkbox - match: (\[[ ]\])\s? scope: string orgmode.checkbox - match: (\[([xX])\])\s? scope: orgmode.checkbox.checked captures: 1: string 2: keyword orgmode.checkbox.checked - match: (\[([\-])\])\s? scope: orgmode.checkbox.blocked captures: 1: string 2: constant.other orgmode.checkbox.blocked # [#/#] Checkbox summary - match: (\[\d*[/%]\d*\]) scope: string orgmode.checkbox.summary # [[link]] - match: \[(\[([^\]]+)\])\] captures: 1: orgmode.link.textblock 2: comment orgmode.link.text.href scope: markup.underline.link orgmode.link # [[link][name]] - match: \[(\[([^\]]+)\])(\[([^\]]+)\])\] captures: 1: orgmode.link.hrefblock 2: comment orgmode.link.href 3: orgmode.link.textblock 4: markup.bold orgmode.link.text scope: markup.underline.link orgmode.link - match: http[s]?://[^ \t]+ scope: orgmode.link.href - match: \b([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})\b scope: orgmode.email # {{{results(=hello=)}}} - match: '\{\{\{results\(([^)]+)\)\}\}\}' scope: comment orgmode.results.inline captures: 1: keyword orgmode.results.value # {numerical_value} - match: \{(\d+)\} scope: orgmode.link.internal.number # {{headline}} - match: \{\{(.+?)\}\} scope: orgmode.link.internal.headline # :TAG: - match: "(^|\\s):[\\w\\d:]+:" scope: entity.name.tag.orgmode orgmode.tags # [code] block, not sure what these are. - match: \[code\]\s* push: code - match: ^\s*Traceback \(most recent call last\):\s*$ push: pythonstack - match: (^|\s)\*[^*]+\*(^|\s) scope: markup.bold orgmode.bold - match: (^|\s)(/[^/]+/)($|\s) scope: markup.italic orgmode.italics - match: \b(_[^_]+_)\b scope: markup.underline orgmode.underline - match: (^|\s)\+[^\+]+\+(^|\s) scope: markup.underline orgmode.strikethrough - match: (^|\s)~[^~]+~(^|\s) scope: orgmode.code - match: (^|\s)=[^=]+=(^|\s) scope: orgmode.verbatim - match: '(<<)([^>]+)(>>)' captures: 1: orgmode.target.bracket 2: comment orgmode.link.text.href orgmode.target 3: orgmode.target.bracket scope: markup.underline.link - match: '(\s*\#\+(BEGIN_CENTER|begin_center)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_CENTER|end_center)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_VERSE|begin_verse)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_VERSE|end_verse)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_QUOTE|begin_quote)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_QUOTE|end_quote)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_NOTES|begin_notes)\s*)' captures: 1: constant.other orgmode.fence embed: scope:text.orgmode escape: '(\s*\#\+(END_NOTES|end_notes)\s*)' embed_scope: markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence - match: '(\s*\#\+(BEGIN_EXAMPLE|begin_example)\s*)' captures: 1: constant.other orgmode.fence embed: scope:text.orgmode escape: '(\s*\#\+(END_EXAMPLE|end_example)\s*)' embed_scope: markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence - match: '{{beginsrc}}((python)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.python escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(python))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.python scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((cpp)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.c++ escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(cpp))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.c++ scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((C)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.c escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(C))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.c scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((perl)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.perl escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(perl))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.perl scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((ini)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.ini escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(ini))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.ini scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((bash|sh)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.shell.bash escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(bash|sh))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.shell.bash scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((lua)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.lua escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(lua))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.lua scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((javascript|js)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.js escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(javascript|js))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.js scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((json)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.json escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(json))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.json scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((java)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.java escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(java))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.java scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((php)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.php escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(php))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.php scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((xml)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.xml escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(xml))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.xml scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((csharp|cs)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.cs escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(csharp|cs))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.cs scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((powershell)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.powershell escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(powershell))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.powershell scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((plantuml)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.wsd escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(plantuml))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.wsd scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((ditaa)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.ditaa escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(ditaa))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.ditaa scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((graphviz)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.dot escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(graphviz))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.dot scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((lisp)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.lisp escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(lisp))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.lisp scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((emacs-lisp)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.lisp escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(emacs-lisp))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.lisp scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((yaml)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.yaml escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(yaml))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.yaml scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((rust)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.rust escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(rust))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.rust scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((sql)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.sql escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(sql))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.sql scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((r(\s|$))\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.r escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(r(\s|$)))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.r scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((html)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.html.basic escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(html))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.html.basic scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((go)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.go escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(go))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.go scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((ledger)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.ledger escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(ledger))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.ledger scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((beancount)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.beancount escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(beancount))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.beancount scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((make)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.makefile escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(make))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.makefile scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((makefile)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.makefile escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(makefile))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.makefile scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((typescript|ts)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.ts escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(typescript|ts))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.ts scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((clojure)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.clojure escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(clojure))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.clojure scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((bat|cmd)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.dosbatch escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(bat|cmd))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.dosbatch scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((org)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.orgmode escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(org))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.orgmode scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((pascal)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.pascal escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(pascal))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.pascal scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((actionscript)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.actionscript.2 escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(actionscript))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.actionscript.2 scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((applescript)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.applescript escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(applescript))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.applescript scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((dtd)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.xml.dtd escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(dtd))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.xml.dtd scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((haskell)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.haskell escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(haskell))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.haskell scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}(((markdown|md)(\s|$))\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.html.markdown escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_((markdown|md)(\s|$)))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.html.markdown scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((groovy)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.groovy escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(groovy))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.groovy scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((regexp)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.regexp escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(regexp))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.regexp scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((ruby)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.ruby escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(ruby))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.ruby scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((restructuredtext)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.restructuredtext escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(restructuredtext))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.restructuredtext scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((xsl)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:text.xml.xsl escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(xsl))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:text.xml.xsl scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((scala)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.scala escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(scala))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.scala scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((hex)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.hex escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(hex))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.hex scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((erlang)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.erlang escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(erlang))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.erlang scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((diff)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.diff escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(diff))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.diff scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((d(\s|$))\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.d(\s|$) escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(d(\s|$)))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.d(\s|$) scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((css)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.css escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(css))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.css scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((cmake)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.cmake escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(cmake))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.cmake scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((asp)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.asp escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(asp))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.asp scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((gnuplot)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.gnuplot escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(gnuplot))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.gnuplot scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((mermaid)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.mermaid escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(mermaid))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.mermaid scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((painless)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.java escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(painless))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.java scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline - match: '{{beginsrc}}((awk)\s*)' captures: 1: constant.other orgmode.fence.sourceblock 2: orgmode.fence.sourceblock 3: keyword orgmode.fence.language 4: orgmode.fence.sourceblock embed: scope:source.awk escape: '{{endsrc}}' embed_scope: orgmode.sourceblock.content markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence.sourceblock - match: '(src_(awk))(\[[^\]]+\])?(\{)' captures: 1: keyword orgmode.fence.language 3: markup.raw.block comment 4: constant.other embed: scope:source.awk scope: orgmode.sourceblock.inline escape: '(\})' escape_captures: 1: constant.other embed_scope: markup.raw.block orgmode.raw.block orgmode.sourceblock.content.inline # #+SOMETHING: # But not a dynamic block # Use negative look ahead to avoid matching begin and end dynamic blocks - match: '^\s*(\#\+(?!(TBLFM|tblfm|BEGIN|END|begin|end))([a-zA-Z][a-zA-Z0-9_-]+)(\s*\[[a-zA-Z0-9_-]+\]\s*)?\:)\s*(.*)' scope: orgmode.controltag captures: 1: keyword orgmode.controltag.tag 5: comment orgmode.controltag.text # #+TBLFM: # But not a dynamic block # Use negative look ahead to avoid matching begin and end dynamic blocks - match: '^\s*(\#\+(TBLFM|tblfm))\:\s*(.*)' scope: orgmode.table orgmode.controltag orgmode.tblfm captures: 1: keyword orgmode.controltag.tag 3: comment orgmode.controltag.text # #+BEGIN: NAME dynamic block support - match: '((\s*\#\+BEGIN:|\#\+begin:)\s+([a-zA-Z0-9]+)\s+(.*)?\s*)' captures: 1: constant.other orgmode.fence.dynamicblock 2: orgmode.fence.dynamicblock.begin 3: keyword orgmode.fence.dynamicblock.name 4: variable.parameter orgmode.fence.dynamicblock.params embed: scope:text.orgmode escape: '(^\s*\#\+END:\s*|\#\+end:\s*)' embed_scope: markup.raw.block orgmode.raw.block.dynamicblock escape_captures: 1: constant.other orgmode.fence.dynamicblock.end code: - meta_scope: text - match: \s*\[/code\] pop: true pythonstack: - meta_scope: orgmode.python.traceback - match: "^\\s*\\w+: .+$" pop: true ================================================ FILE: OrgExtended.sublime-syntax-template ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html file_extensions: - org - org_archive # Generic parent scope of the file scope: text.orgmode version: 2 variables: datetime: "<\\d{4}-\\d{2}-\\d{2}(?:\\s*\\w{3})?\\s*(\\d{2}\\:\\d{2}(-\\d{2}\\:\\d{2})?)?\\s*([+]*\\d[wdmy])?>" unscheddatetime: "\\[\\d{4}-\\d{2}-\\d{2}(?:\\s*\\w{3})?\\s*(\\d{2}\\:\\d{2})?\\s*([+]*\\d[wdmy])?\\]" tags: "(^|):[\\w\\d:]+:" priority: '\s*\[((\#A)|(\#B)|(\#C)|(\#D)|(\#E)|(\#[a-zA-Z0-9]+))\]\s+' state: (TODO)|(BLOCKED)|(WAITING)|(CANCELLED)|(DONE)|(MEETING)|(PHONE)|(NOTE)|(FLAG)|(CLEANUP)|(IN-PROGRESS)|(DOING)|(NEXT)|(REASSIGNED)|(FIXED) beginmrk: BEGIN_SRC|begin_src endmrk: END_SRC|end_src beginsrc: '(\s*\#\+({{beginmrk}})\s+)' endsrc: '(\s*\#\+({{endmrk}})\s*)' contexts: # The prototype context is prepended to all contexts but those setting # meta_include_prototype: false. #prototype: #- include: comments header-matches: - match: $ pop: true - match: ({{state}}\s+)?({{priority}})?[^\[\]:\n]*(\[\d*[/%]\d*\])?({{tags}})? captures: 2: variable.parameter orgmode.state.todo 3: variable.parameter orgmode.state.blocked 4: variable.parameter orgmode.state.waiting 5: variable.parameter orgmode.state.cancelled 6: variable.parameter orgmode.state.done 7: variable.parameter orgmode.state.meeting 8: variable.parameter orgmode.state.phone 9: variable.parameter orgmode.state.note 10: variable.parameter orgmode.state.flag 11: variable.parameter orgmode.state.cleanup 12: variable.parameter orgmode.state.inprogress 13: variable.parameter orgmode.state.doing 14: variable.parameter orgmode.state.next 15: variable.parameter orgmode.state.reassigned 16: variable.parameter orgmode.state.fixed 17: string.quoted orgmode.priority 18: string.quoted orgmode.priority.value 19: string.quoted orgmode.priority.value.a 20: string.quoted orgmode.priority.value.b 21: string.quoted orgmode.priority.value.c 22: string.quoted orgmode.priority.value.d 23: string.quoted orgmode.priority.value.e 24: string.quoted orgmode.priority.value.general 25: string.quoted orgmode.checkbox.summary 26: entity.name.tag.orgmode orgmode.tags.header main: # The main context is the initial starting point of our syntax. # Include other contexts from here (or specify them directly). #- include: keywords #- include: numbers #- include: strings # --- # Todo investigate what this actually is? - match: ^\s*\-\-\- [^\n]* scope: comment orgmode.page # ~~~~~ # Todo investigate what this is? - match: ^\s*[~]+ [^\n]* scope: comment orgmode.break # Generic headline, TODO: Make multiple of these so we can color them # and sub captures so we can hide the extraneous stars # embed_scope: entity.name.function.orgmode orgmode.headline - match: ^\s*[*]\s+ push: - meta_scope: entity.name.class.orgmode orgmode.headline - include: header-matches - match: ^\s*([*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.function.orgmode orgmode.headline2 - include: header-matches - match: ^\s*([*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.other.attribute-name.orgmode orgmode.headline3 - include: header-matches - match: ^\s*([*][*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.section.orgmode orgmode.headline4 - include: header-matches - match: ^\s*([*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble push: - meta_scope: entity.name.type.orgmode orgmode.headline5 - include: header-matches - match: ^\s*([*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline6 push: - meta_scope: entity.name.filename orgmode.headline6 - include: header-matches - match: ^\s*([*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline7 push: - meta_scope: entity.name.filename orgmode.headline7 - include: header-matches - match: ^\s*([*][*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline8 push: - meta_scope: entity.name.filename orgmode.headline8 - include: header-matches - match: ^\s*([*][*][*][*][*][*][*][*])[*]\s+ captures: 1: comment orgmode.preamble scope: orgmode.headline9 push: - meta_scope: entity.name.filename orgmode.headline9 - include: header-matches - match: ^\s*(\|.+\|) captures: 1: markup.raw.block orgmode.table.block scope: orgmode.table # DEADLINE: - match: "(DEADLINE:)\\s+({{datetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.datetime scope: orgmode.deadline # SCHEDULED: - match: "(SCHEDULED:)\\s+({{datetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.datetime scope: orgmode.scheduled # CLOSED: [DATETIME] - match: "(CLOSED:)\\s+({{unscheddatetime}})" captures: 1: keyword orgmode.statekeyword 2: markup.italic orgmode.unscheddatetime scope: orgmode.closed # numbered list - match: "^\\s*([0-9]+[.)])\\s+(([^:]+\\s+)(::))?" captures: 1: constant.numeric 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.numberedlist # bullet list - match: "^\\s*(\\-) (([^:]+\\s+)(::))?" captures: 1: constant.character 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.tack.minus # bullet list - match: "^\\s*(\\+) (([^:]+\\s+)(::))?" captures: 1: constant.character 3: keyword orgmode.definition 4: punctuation orgmode.definition.marker scope: orgmode.tack.plus # To follow up: -> and => - match: "^\\s*(\\-\\>|\\=\\>) " scope: orgmode.follow_up # [-] Checkbox - match: (\[[ ]\])\s? scope: string orgmode.checkbox - match: (\[([xX])\])\s? scope: orgmode.checkbox.checked captures: 1: string 2: keyword orgmode.checkbox.checked - match: (\[([\-])\])\s? scope: orgmode.checkbox.blocked captures: 1: string 2: constant.other orgmode.checkbox.blocked # [#/#] Checkbox summary - match: (\[\d*[/%]\d*\]) scope: string orgmode.checkbox.summary # [[link]] - match: \[(\[([^\]]+)\])\] captures: 1: orgmode.link.textblock 2: comment orgmode.link.text.href scope: markup.underline.link orgmode.link # [[link][name]] - match: \[(\[([^\]]+)\])(\[([^\]]+)\])\] captures: 1: orgmode.link.hrefblock 2: comment orgmode.link.href 3: orgmode.link.textblock 4: markup.bold orgmode.link.text scope: markup.underline.link orgmode.link - match: http[s]?://[^ \t]+ scope: orgmode.link.href - match: \b([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})\b scope: orgmode.email # {{{results(=hello=)}}} - match: '\{\{\{results\(([^)]+)\)\}\}\}' scope: comment orgmode.results.inline captures: 1: keyword orgmode.results.value # {numerical_value} - match: \{(\d+)\} scope: orgmode.link.internal.number # {{headline}} - match: \{\{(.+?)\}\} scope: orgmode.link.internal.headline # :TAG: - match: "(^|\\s):[\\w\\d:]+:" scope: entity.name.tag.orgmode orgmode.tags # [code] block, not sure what these are. - match: \[code\]\s* push: code - match: ^\s*Traceback \(most recent call last\):\s*$ push: pythonstack - match: (^|\s)\*[^*]+\*(^|\s) scope: markup.bold orgmode.bold - match: (^|\s)(/[^/]+/)($|\s) scope: markup.italic orgmode.italics - match: \b(_[^_]+_)\b scope: markup.underline orgmode.underline - match: (^|\s)\+[^\+]+\+(^|\s) scope: markup.underline orgmode.strikethrough - match: (^|\s)~[^~]+~(^|\s) scope: orgmode.code - match: (^|\s)=[^=]+=(^|\s) scope: orgmode.verbatim - match: '(<<)([^>]+)(>>)' captures: 1: orgmode.target.bracket 2: comment orgmode.link.text.href orgmode.target 3: orgmode.target.bracket scope: markup.underline.link - match: '(\s*\#\+(BEGIN_CENTER|begin_center)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_CENTER|end_center)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_VERSE|begin_verse)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_VERSE|end_verse)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_QUOTE|begin_quote)\s*)' captures: 1: orgmode.fence push: - meta_scope: constant.other orgmode.raw.block - meta_content_scope: markup.raw.block orgmode.raw.block - match: '(\s*\#\+(END_QUOTE|end_quote)\s*)' captures: 1: orgmode.fence pop: true - match: '(\s*\#\+(BEGIN_NOTES|begin_notes)\s*)' captures: 1: constant.other orgmode.fence embed: scope:text.orgmode escape: '(\s*\#\+(END_NOTES|end_notes)\s*)' embed_scope: markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence - match: '(\s*\#\+(BEGIN_EXAMPLE|begin_example)\s*)' captures: 1: constant.other orgmode.fence embed: scope:text.orgmode escape: '(\s*\#\+(END_EXAMPLE|end_example)\s*)' embed_scope: markup.raw.block orgmode.raw.block escape_captures: 1: constant.other orgmode.fence {{INSERT_LANGUAGES_HERE}} # #+SOMETHING: # But not a dynamic block # Use negative look ahead to avoid matching begin and end dynamic blocks - match: '^\s*(\#\+(?!(TBLFM|tblfm|BEGIN|END|begin|end))([a-zA-Z][a-zA-Z0-9_-]+)(\s*\[[a-zA-Z0-9_-]+\]\s*)?\:)\s*(.*)' scope: orgmode.controltag captures: 1: keyword orgmode.controltag.tag 5: comment orgmode.controltag.text # #+TBLFM: # But not a dynamic block # Use negative look ahead to avoid matching begin and end dynamic blocks - match: '^\s*(\#\+(TBLFM|tblfm))\:\s*(.*)' scope: orgmode.table orgmode.controltag orgmode.tblfm captures: 1: keyword orgmode.controltag.tag 3: comment orgmode.controltag.text # #+BEGIN: NAME dynamic block support - match: '((\s*\#\+BEGIN:|\#\+begin:)\s+([a-zA-Z0-9]+)\s+(.*)?\s*)' captures: 1: constant.other orgmode.fence.dynamicblock 2: orgmode.fence.dynamicblock.begin 3: keyword orgmode.fence.dynamicblock.name 4: variable.parameter orgmode.fence.dynamicblock.params embed: scope:text.orgmode escape: '(^\s*\#\+END:\s*|\#\+end:\s*)' embed_scope: markup.raw.block orgmode.raw.block.dynamicblock escape_captures: 1: constant.other orgmode.fence.dynamicblock.end code: - meta_scope: text - match: \s*\[/code\] pop: true pythonstack: - meta_scope: orgmode.python.traceback - match: "^\\s*\\w+: .+$" pop: true ================================================ FILE: README.md ================================================ # Org Extended ![Org](https://orgmode.org/resources/img/org-mode-unicorn.svg) OrgMode is a lifestyle. While I like sublime, living without Org Mode has been something that has driven me back to Emacs over and over again. I finally decided that I might take a stab at building a usable orgmode plugin for sublime. ![Start](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/orgstart.gif) NOTE: To get setup, please jump down the Setup link below. When people show off org, they often just show off some folding and the ability to tab cycle a headings tree. This often leads people to compare org with Markdown. Org IS a markup and document interchange format like markdown, but it is also much more. ![Folding](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/orgstartfolding.gif) Fundamentally org mode is *2* very /different/ things and fairly hard to describe: 1. Org Files - A text based document markup language similar to markdown. 2. Org Mode - A wide variety of tools for operating on and working with collections of these files. 3. Org Extensions - I know I said 2 but Org Mode has a wide variety of tools built around the mode and api's extending it in many creative ways. Although not org mode itself most people refer to these tools when they think of org mode. Org Mode can and has been used for a large variety of things: + A Personal Wiki + Professional Notes + Time Tracking and Billing + Documentation + Research Papers - Dynamic Documents + Literate Programming + Personal Agenda + Project Planning + As a blogging tool + Website content management + A means of planning and managing a budget with ledger mode + As a process and memory aid for IT professionals + As a self documenting configuration file for emacs itself (and other things). + Many many more things I use org to manage my agenda: ![Agenda](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/agenda_day.gif) Or to help me manipulate tables of data: ![Tables](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/table_hacking.gif) Or build document diagrams: ![Diagrams](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/creating_diagrams.gif) Or build presentations with revealjs, html or pdfs with latex: ![Presentations](https://raw.githubusercontent.com/ihdavids/orgextended_docs/master/images/revealjs.gif) What makes Org Mode so versatile is the deceptive simplicity of the format the flexibility of the simple markup and the depth of the tools and API's provided around that format. At times I have wondered why I shouldn't just use markdown? It is a much more widely popular markup system. There is no reason markdown could not be extended to become exactly what Org Mode has become, but markdown is not quite as flexible with its meta data and has not had the same degree of *cult* following so has yet to evolve into something like Org. I hope to go beyond simply the file format and bring some of the actual Mode to Sublime. I simply cannot build the entire thing, but I hope we can build something unique and amazing in sublime, in its own right. # This Plugin - [Starter Tutorial](https://github.com/ihdavids/orgextended_docs/blob/master/learning_todos.org) - Learning about todos - [Basic Structure](https://github.com/ihdavids/orgextended_docs/blob/master/orgextended.org) - Basic file structure - [Setup](https://github.com/ihdavids/orgextended_docs/blob/master/setup.org) - Sublime Setup - [Editing](https://github.com/ihdavids/orgextended_docs/blob/master/editing.org) - Editing your org file - [Lists](https://github.com/ihdavids/orgextended_docs/blob/master/lists.org) - Supported lists in an org file - [Folding](https://github.com/ihdavids/orgextended_docs/blob/master/folding.org) - Jumping from the full view to a folded representation. - [Links](https://github.com/ihdavids/orgextended_docs/blob/master/links.org) - Jumping within and without. - [Navigation](https://github.com/ihdavids/orgextended_docs/blob/master/navigation.org) - Powerful ways of navigating your org files. - [Capture, Refile, Archive](https://github.com/ihdavids/orgextended_docs/blob/master/capture.org) - Save ideas fast. - [Exporting](https://github.com/ihdavids/orgextended_docs/blob/master/exporting.org) - Converting from org to other things. - [Properties and Drawers](https://github.com/ihdavids/orgextended_docs/blob/master/properties.org) - Metadata within a heading - [Scheduling](https://github.com/ihdavids/orgextended_docs/blob/master/dates.org) - Dates and times - [Time Tracking](https://github.com/ihdavids/orgextended_docs/blob/master/clocking.org) - Clocking and clock reports - [Dynamic Blocks](https://github.com/ihdavids/orgextended_docs/blob/master/dynamicblocks.org) - Run arbitrary code - [Living Documents](https://github.com/ihdavids/orgextended_docs/blob/master/babel.org) - Babel - Literate Programming, Reproducible Research and Living Documents - [Tables](https://github.com/ihdavids/orgextended_docs/blob/master/tables.org) - Spreadsheets in your documents. - [Diagrams](https://github.com/ihdavids/orgextended_docs/blob/master/diagrams.org) - Adding diagrams to your documents. - [Agenda](https://github.com/ihdavids/orgextended_docs/blob/master/agenda.org) - Keeping track of your day. - [Key Bindings](https://github.com/ihdavids/orgextended_docs/blob/master/keybindings.org) - A quick reference of some of the default keybindings. The full documentation for this plugin can be found at: [Docs](https://github.com/ihdavids/orgextended_docs) # Thank You I have shamelessly built this plugin on the backs of some excellent plugins and libraries. - The original orgmode plugin - This work was exceptional, OrgExtended is a tribute to that work and consumes some of it. - sublime_ZK - The inline image preview is entirely due to the Markdown ZK plugin. [ZK](https://github.com/renerocksai/sublime_zk) Thank you renerocksai for pointing out that phantoms can be used for image preview. - Table Edit - For now this excellent plugin is a dependency and the basis by which we offer Org style table editing. In a future version we may look to consume the package and own table editing to facilitate expressions and some of the more advanced org table tools, but for now, thank you for making this excellent plugin! - pymitter - a great little event library for python. - highlightjs - a wonderful highlighting library for html. - pandoc - a great command line tool for converting formats. # References To help get you started on your Org journey Here are some useful external links: - [Org Mode Site](https://orgmode.org) - Org - [The Org Manual](https://orgmode.org/manual/) - The official source of truth for all things orgmode - [Org Mode 4 Beginners](https://orgmode.org/worg/org-tutorials/org4beginners.html) - An introduction - [David O'Tools Introduction](https://orgmode.org/worg/org-tutorials/orgtutorial_dto.html) - Yet another intro - [The Many Uses of Org Mode](https://thoughtbot.com/blog/the-many-uses-of-org-mode) - [More Uses](https://kitchingroup.cheme.cmu.edu/blog/2014/08/08/What-we-are-using-org-mode-for/) - [Your Life In Plain Text](http://doc.norang.ca/org-mode.html) - A wonderful reference on one mans journey to use orgmode to improve his life ================================================ FILE: Symbol List.tmPreferences ================================================ name Symbol List scope text.orgmode orgmode.page, text.orgmode orgmode.break, text.orgmode orgmode.headline, text.orgmode orgmode.headline2, text.orgmode orgmode.headline3, text.orgmode orgmode.headline4, text.orgmode orgmode.headline5, text.orgmode orgmode.headline6 settings showInSymbolList 1 symbolTransformation s/\s*\**\s*\z//g; #Search for * s/(?<=\*)\*/ /g; #replace * with two spaces, except first s/^\*( *)\s+(.*)/$1$2/; #replace first found with a space uuid a5b8a9bb-75fa-41bf-a15c-3832eb894331 ================================================ FILE: asettings.py ================================================ import sublime import sublime_plugin import datetime import os import logging import shutil import OrgExtended.orgutil.template as temp log = logging.getLogger(__name__) defaultTodoStates = ["TODO", "NEXT", "BLOCKED","WAITING","FLAG", "CLEANUP", "IN-PROGRESS", "DOING", "|", "REASSIGNED", "CANCELLED", "DONE","MEETING","PHONE","NOTE", "FIXED"] weekdayNames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] class ASettings: def __init__(self, settingsName): self.settings = sublime.load_settings(settingsName + '.sublime-settings') def Get(self, name, defaultVal): val = self.settings.get(name) if(val == None): val = defaultVal return val configFilename = "OrgExtended" def setup_user_settings(): # This is old and I should remove it! # We don't need this mechanism anymore! filename = configFilename + ".sublime-settings" user_settings_path = os.path.join( sublime.packages_path(), "User", filename) if not os.path.exists(user_settings_path): default_settings_path = os.path.join( sublime.packages_path(), "OrgExtended", filename) if os.path.exists(default_settings_path): shutil.copyfile(default_settings_path, user_settings_path) def setup_mousemap(): filename = "Default.sublime-mousemap" user_settings_path = os.path.join( sublime.packages_path(), "User", filename) mousemap = """ [ { "button": "button1", "count": 1, "modifiers": ["alt"], "press_command": "drag_select", // In the future we may vector this to a more generic handler "command": "org_mouse_handler", } ] """ if not os.path.exists(user_settings_path): with open(user_settings_path,"w") as o: o.write(mousemap) o.write("\n") class OrgSetupMouseMapCommand(sublime_plugin.TextCommand): def run(self, edit, event=None): setup_mousemap() # Singleton access _sets = None def Load(): global configFilename global _sets _sets = ASettings(configFilename) def Get(name, defaultValue, formatDictionary = None): global _sets if(_sets == None): log.warning("SETTINGS IS NULL? IS THIS BEING CALLED BEFORE PLUGIN START?") Load() rv = _sets.Get(name, defaultValue) formatDict = { "date": str(datetime.date.today()), "time": datetime.datetime.now().strftime("%H:%M:%S"), "datetime": str(datetime.datetime.now().strftime("%Y-%m-%d %a %H:%M")), } if(formatDictionary != None): formatDict.update(formatDictionary) if(str == type(rv)): formatter = temp.TemplateFormatter(Get) rv = formatter.format(rv, **formatDict) if(list == type(rv)): formatter = temp.TemplateFormatter(Get) rv = [ (formatter.format(r, **formatDict) if str == type(r) else r) for r in rv ] return rv def RepresentsInt(s): try: int(s) return True except ValueError: return False def GetInt(name, defaultValue): v = Get(name, defaultValue) try: i = int(v) return i except: return defaultValue def GetWeekdayIndexByName(name): try: weekdayIndex = weekdayNames.index(name) except: weekdayIndex = 6 return weekdayIndex # Will return a date or an index as an integer where 0 means Sunday # and so on in the week. def GetDateAsIndex(name, defaultValue): global daysOfWeek val = Get(name, defaultValue) if(RepresentsInt(val)): return int(val) % 7 val = val.lower() for i in range(0,len(daysOfWeek)): if daysOfWeek[i] in val: return i return 0 # ================================================================================ class OrgTestTemplateCommand(sublime_plugin.TextCommand): def run(self, edit, onDone=None): v = temp.ExpandTemplate(self.view, "DATE: {date} TIME: {time} DT: {datetime} FILE: {file.lower:call}") print(str(v)) formatDict = { "aaa": str(datetime.date.today()),} formatter = temp.TemplateFormatter(Get) rv = formatter.format("{aaa} {archive}", **formatDict) print(str(rv)) ================================================ FILE: balloontip.ps1 ================================================ Add-Type -AssemblyName System.Windows.Forms $global:balloon = New-Object System.Windows.Forms.NotifyIcon $path = (Get-Process -id $pid).Path #$path = "C:\Program Files\Sublime Text 3\sublime_text.exe" $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) $balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning $balloon.BalloonTipText = $Args[0] $balloon.BalloonTipTitle = "REMINDER: @ " + $Args[1] $balloon.Visible = $true $balloon.ShowBalloonTip(5000) ================================================ FILE: beancount.py ================================================ import sublime import sublime_plugin import datetime class BeancountNewTransactionCommand(sublime_plugin.TextCommand): def run(self, edit): ai = sublime.active_window().active_view().settings().get('auto_indent') self.view.settings().set('auto_indent',False) snipName = "Packages/Beancount/snipets/transaction.sublime-snippet" # OTHER VARIABLES: # TM_FULLNAME - Users full name # TM_FILENAME - File name of the file being edited # TM_CURRENT_WORD - Word under cursor when snippet was triggered # TM_SELECTED_TEXT - Selected text when snippet was triggered # TM_CURRENT_LINE - Line of snippet when snippet was triggered # For NeoVintageous Users FORCE insert mode during snippet insertion for ease of use. self.view.run_command('_enter_insert_mode', {"count": 1, "mode": "mode_internal_normal"}) self.view.run_command("insert_snippet", { "name" : snipName , "MONTH": datetime.datetime.now().strftime("%m") , "YEAR": datetime.datetime.now().strftime("%Y") , "DAY": datetime.datetime.now().strftime("%d") , "DATE": str(datetime.date.today()) , "TIME": datetime.datetime.now().strftime("%H:%M:%S") , "CLIPBOARD": sublime.get_clipboard() , "SELECTION": self.view.substr(self.view.sel()[0]) , "FILENAME": self.view.file_name() , "DEFAULT_CURRENCY": "CAD" }) sublime.active_window().active_view().settings().set('auto_indent',ai) class BeancountNewFileCommand(sublime_plugin.TextCommand): def run(self, edit): win = sublime.active_window() win.run_command('new_file') panel = win.active_view() panel.set_syntax_file("Packages/OrgExtended/OrgBeancount.sublime-syntax") ================================================ FILE: dependencies.json ================================================ { "*": { "*": [ "pathlib", "pyyaml", "dateutil", "requests", "regex", "websocket", "six" ] } } ================================================ FILE: htmlstyles/blocky.css ================================================ /* * I add this to html files generated with pandoc. */ html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { color: #444; background-color: #ddd; font-size: 12px; line-height: 1.7; padding: 1em; margin: auto; max-width: 42em; /*background: #fefefe;*/ font-family: 'Montserrat', sans-serif; } a { /*#0645cd;*/ color: #1e74ac; text-decoration: underline; text-decoration-style: dotted; font-weight: bold; } a:visited { color: #0b0090; } a:hover { color: #06e; } a:active { color: #faa700; } a:focus { outline: thin dotted; } *::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #000; } *::selection { background: rgba(255, 255, 0, 0.3); color: #000; } a::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } a::selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } p { margin: 1em 0; } img { max-width: 100%; } h1, h2, h3, h4, h5, h6 { color: #1e747c; line-height: 125%; margin-top: 2em; font-weight: normal; font-family: 'Bebas Neue', cursive; border-left-color: #1e747c; border-left-style: solid; border-left-width: 4px; padding-left: 12px; } h4, h5, h6 { color:aaa; font-weight: bold; } h1 { font-size: 2.5em; } h2 { font-size: 2em; } h3 { font-size: 1.5em; } h4 { font-size: 1.2em; } h5 { font-size: 1em; } h6 { font-size: 0.9em; } blockquote { color: #765037; margin: 0; padding-left: 2em; border-left: 0.3em #474356 solid; } hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa; border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; } pre, code, kbd, samp { color: #66402f; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; background: #ccc; } pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } b, strong { font-weight: bold; } dfn { font-style: italic; } ins { background: #ff9; color: #000; text-decoration: none; } mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul, ol { margin: 1em 0; padding: 0 0 0 2em; } li p:last-child { margin-bottom: 0; } ul ul, ol ol { margin: .3em 0; } dl { margin-bottom: 1em; } dt { font-weight: bold; margin-bottom: .8em; } dd { margin: 0 0 .8em 2em; } dd:last-child { margin-bottom: 0; } img { border: 0; -ms-interpolation-mode: bicubic; /*vertical-align: middle;*/ } figure { display: block; text-align: center; margin: 1em 0; } figure img { border: none; margin: 0 auto; } figcaption { font-size: 0.8em; font-style: italic; margin: 0 0 .8em; } table { margin-bottom: 2em; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; border-top: 1px solid #ddd; border-spacing: 0; border-collapse: collapse; } table th { padding: .2em 1em; background-color: #bbb; border-top: 1px solid #ddd; border-left: 1px solid #aaa; } table td { padding: .2em 1em; border-top: 1px dotted #aaa; border-left: 1px solid #ddd; vertical-align: top; } .author { font-size: 1.2em; text-align: center; } @media only screen and (min-width: 480px) { body { font-size: 14px; } } @media only screen and (min-width: 768px) { body { font-size: 16px; } } @media print { * { background: transparent !important; color: black !important; filter: none !important; -ms-filter: none !important; } body { font-size: 12pt; max-width: 100%; } a, a:visited { text-decoration: underline; } hr { height: 1px; border: 0; border-bottom: 1px solid black; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } @page :left { margin: 15mm 20mm 15mm 10mm; } @page :right { margin: 15mm 10mm 15mm 20mm; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } ================================================ FILE: htmlstyles/blocky_heading.html ================================================ ================================================ FILE: htmlstyles/blocky_inheader.html ================================================ ================================================ FILE: htmlstyles/funky.css ================================================ /* * I add this to html files generated with pandoc. */ html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { color: #000; background-color: #fff; font-size: 12px; line-height: 1.7; padding: 1em; margin: auto; max-width: 42em; /*background: #fefefe;*/ font-family: 'Oswald', sans-serif; } a { /*#0645cd;*/ color: #1e74ac; text-decoration: underline; text-decoration-style: dotted; font-weight: bold; } a:visited { color: #0b0090; } a:hover { color: #06e; } a:active { color: #faa700; } a:focus { outline: thin dotted; } *::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #000; } *::selection { background: rgba(255, 255, 0, 0.3); color: #000; } a::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } a::selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } p { margin: 1em 0; } img { max-width: 100%; } h1, h2, h3, h4, h5, h6, h7 { color: #40320d; line-height: 125%; margin-top: 2em; font-weight: normal; font-family: 'Amatic SC', cursive; padding-left: 12px; text-shadow: 2px 2px 5px; } h4, h5, h6 { color:aaa; font-weight: bold; } h1 { font-size: 2.5em; } h2 { font-size: 2em; } h3 { font-size: 1.5em; } h4 { font-size: 1.2em; } h5 { font-size: 1em; } h6 { font-size: 0.9em; } blockquote { color: #765037; margin: 0; padding-left: 2em; border-left: 0.3em #474356 solid; } hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa; border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; } pre, code, kbd, samp { color: #66402f; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; background: #ccc; border-radius: 25px; box-shadow: 5px 5px 10px #888888; } pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } b, strong { font-weight: bold; } dfn { font-style: italic; } ins { background: #ff9; color: #000; text-decoration: none; } mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul, ol { margin: 1em 0; padding: 0 0 0 2em; } li p:last-child { margin-bottom: 0; } ul ul, ol ol { margin: .3em 0; } dl { margin-bottom: 1em; } dt { font-weight: bold; margin-bottom: .8em; } dd { margin: 0 0 .8em 2em; } dd:last-child { margin-bottom: 0; } img { border: 0; -ms-interpolation-mode: bicubic; /*vertical-align: middle;*/ } figure { display: block; text-align: center; margin: 1em 0; } figure img { border: none; margin: 0 auto; } figcaption { font-size: 0.8em; font-style: italic; margin: 0 0 .8em; } table { margin-bottom: 2em; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; border-top: 1px solid #ddd; border-spacing: 0; border-collapse: collapse; } table th { padding: .2em 1em; background-color: #bbb; border-top: 1px solid #ddd; border-left: 1px solid #aaa; } table td { padding: .2em 1em; border-top: 1px dotted #aaa; border-left: 1px solid #ddd; vertical-align: top; } .author { font-size: 1.2em; text-align: center; } .node-body { padding: 0 18px; max-height: 0; overflow: hidden; transition: max-height 0.2s ease-out; } .active, .collapsible:hover { background-color: #fff; } .collapsible:after { font-size: 22px; float: right; margin-right: 20px; } .active:after { font-size: 22px; margin-right: 20px; } @media only screen and (min-width: 480px) { body { font-size: 14px; } } @media only screen and (min-width: 768px) { body { font-size: 16px; } } @media print { * { background: transparent !important; color: black !important; filter: none !important; -ms-filter: none !important; } body { font-size: 12pt; max-width: 100%; } a, a:visited { text-decoration: underline; } hr { height: 1px; border: 0; border-bottom: 1px solid black; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } @page :left { margin: 15mm 20mm 15mm 10mm; } @page :right { margin: 15mm 10mm 15mm 20mm; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } ================================================ FILE: htmlstyles/funky_inheader.html ================================================ ================================================ FILE: htmlstyles/plain.css ================================================ /* * I add this to html files generated with pandoc. */ html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { color: #444; background-color: #fff; font-size: 12px; line-height: 1.7; padding: 1em; margin: auto; max-width: 42em; /*background: #fefefe;*/ /*font-family: 'Montserrat', sans-serif;*/ font-family: 'Open Sans', sans-serif; } a { /*#0645cd;*/ color: #1e74ac; text-decoration: underline; text-decoration-style: dotted; font-weight: bold; } a:visited { color: #0b0090; } a:hover { color: #06e; } a:active { color: #faa700; } a:focus { outline: thin dotted; } *::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #000; } *::selection { background: rgba(255, 255, 0, 0.3); color: #000; } a::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } a::selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } p { margin: 1em 0; } img { max-width: 100%; } h1, h2, h3, h4, h5, h6 { color: #111111; line-height: 125%; margin-top: 2em; font-weight: normal; font-family: 'Open Sans'; border-left-color: #fcfcfc; border-left-style: solid; border-left-width: 4px; padding-left: 12px; } h4, h5, h6 { color:222; font-weight: bold; } h1 { font-size: 2.5em; } h2 { font-size: 2em; } h3 { font-size: 1.5em; } h4 { font-size: 1.2em; } h5 { font-size: 1em; } h6 { font-size: 0.9em; } blockquote { color: #765037; margin: 0; padding-left: 2em; border-left: 0.3em #474356 solid; } hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa; border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; } pre, code, kbd, samp { color: #66402f; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; background: #ccc; } pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } b, strong { font-weight: bold; } dfn { font-style: italic; } ins { background: #ff9; color: #000; text-decoration: none; } mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul, ol { margin: 1em 0; padding: 0 0 0 2em; } li p:last-child { margin-bottom: 0; } ul ul, ol ol { margin: .3em 0; } dl { margin-bottom: 1em; } dt { font-weight: bold; margin-bottom: .8em; } dd { margin: 0 0 .8em 2em; } dd:last-child { margin-bottom: 0; } img { border: 0; -ms-interpolation-mode: bicubic; /*vertical-align: middle;*/ } figure { display: block; text-align: center; margin: 1em 0; } figure img { border: none; margin: 0 auto; } figcaption { font-size: 0.8em; font-style: italic; margin: 0 0 .8em; } table { margin-bottom: 2em; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; border-top: 1px solid #ddd; border-spacing: 0; border-collapse: collapse; } table th { padding: .2em 1em; background-color: #bbb; border-top: 1px solid #ddd; border-left: 1px solid #aaa; } table td { padding: .2em 1em; border-top: 1px dotted #aaa; border-left: 1px solid #ddd; vertical-align: top; } .active, .collapsible:hover { background-color: #fff; } .author { font-size: 1.2em; text-align: center; } @media only screen and (min-width: 480px) { body { font-size: 14px; } } @media only screen and (min-width: 768px) { body { font-size: 16px; } } @media print { * { background: transparent !important; color: black !important; filter: none !important; -ms-filter: none !important; } body { font-size: 12pt; max-width: 100%; } a, a:visited { text-decoration: underline; } hr { height: 1px; border: 0; border-bottom: 1px solid black; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } @page :left { margin: 15mm 20mm 15mm 10mm; } @page :right { margin: 15mm 10mm 15mm 20mm; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } ================================================ FILE: htmlstyles/plain_heading.html ================================================ ================================================ FILE: htmlstyles/plain_inheader.html ================================================ ================================================ FILE: htmlstyles/refined.css ================================================ /* * I add this to html files generated with pandoc. */ html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { color: #fff; background-color: #555; font-size: 12px; line-height: 1.7; padding: 1em; margin: auto; max-width: 42em; /*background: #fefefe;*/ font-family: 'Raleway', sans-serif; } .node-body.h2 { border-top-style: solid; border-top-color: #595959; #background-image: linear-gradient(to top right, #555 , #555, #555, #555, #444); } a { /*#0645cd;*/ color: #1e74ac; text-decoration: underline; text-decoration-style: dotted; font-weight: bold; } a:visited { color: #0b0090; } a:hover { color: #06e; } a:active { color: #faa700; } a:focus { outline: thin dotted; } *::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #000; } *::selection { background: rgba(255, 255, 0, 0.3); color: #000; } a::-moz-selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } a::selection { background: rgba(255, 255, 0, 0.3); color: #0645ad; } p { margin: 1em 0; } img { max-width: 100%; } h2 { font-family: 'Julius Sans One', sans-serif; color: #ffffff; line-height: 100%; margin-top: 2em; font-weight: normal; padding-left: 12px; } h3, h4, h5, h6, h7 { color: #c7af2a; /*line-height: 100%;*/ margin-top: 2em; font-weight: normal; font-family: 'Open Sans Condensed', sans serif; /*padding-left: 12px;*/ /*text-shadow: 2px 2px 5px;*/ } h4, h5, h6 { color:aaa; font-weight: bold; } h1 { font-size: 2.5em; } h2 { font-size: 2em; } h3 { font-size: 1.5em; } h4 { font-size: 1.2em; } h5 { font-size: 1em; } h6 { font-size: 0.9em; } blockquote { color: #765037; margin: 0; padding-left: 2em; border-left: 0.3em #474356 solid; } hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa; border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; } pre, code, kbd, samp { color: #66402f; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; background: #ccc; border-radius: 25px; } #box-shadow: 5px 5px 10px #888888; pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } b, strong { font-weight: bold; } dfn { font-style: italic; } ins { background: #ff9; color: #000; text-decoration: none; } mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul, ol { margin: 1em 0; padding: 0 0 0 2em; } li p:last-child { margin-bottom: 0; } ul ul, ol ol { margin: .3em 0; } dl { margin-bottom: 1em; } dt { font-weight: bold; margin-bottom: .8em; } dd { margin: 0 0 .8em 2em; } dd:last-child { margin-bottom: 0; } img { border: 0; -ms-interpolation-mode: bicubic; /*vertical-align: middle;*/ } figure { display: block; text-align: center; margin: 1em 0; } figure img { border: none; margin: 0 auto; } figcaption { font-size: 0.8em; font-style: italic; margin: 0 0 .8em; } table { margin-bottom: 2em; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; border-top: 1px solid #ddd; border-spacing: 0; border-collapse: collapse; } table th { padding: .2em 1em; background-color: #bbb; border-top: 1px solid #ddd; border-left: 1px solid #aaa; } table td { padding: .2em 1em; border-top: 1px dotted #aaa; border-left: 1px solid #ddd; vertical-align: top; } .table-number { color:#ccc; font-weight: bold; } caption.t-above { caption-side: top; } caption.t-bottom { caption-side: bottom; } .figure-number { color:aaa; font-weight: bold; } .figure { font-style: italic; } .author { font-size: 1.2em; text-align: center; } .node-body { padding: 0 18px; max-height: 0; margin-left: 0; padding-left: 0; margin-right: 0; padding-right: 0; overflow: hidden; transition: max-height 0.2s ease-out; } .active, .collapsible:hover { background-color: #555; } .collapsible:after { font-size: 22px; float: right; margin-right: 20px; } .active:after { font-size: 22px; margin-right: 20px; } @media only screen and (min-width: 480px) { body { font-size: 14px; } } @media only screen and (min-width: 768px) { body { font-size: 16px; } } @media print { * { background: transparent !important; color: black !important; filter: none !important; -ms-filter: none !important; } body { font-size: 12pt; max-width: 100%; } a, a:visited { text-decoration: underline; } hr { height: 1px; border: 0; border-bottom: 1px solid black; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } /* @page :left { margin: 15mm 20mm 15mm 10mm; } */ @page :right { margin: 15mm 10mm 15mm 20mm; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } ================================================ FILE: htmlstyles/refined_inheader.html ================================================ ================================================ FILE: languagelist.yaml ================================================ - language: python - language: cpp source: c++ - language: C source: c - language: perl - language: ini - language: bash source: shell.bash match: bash|sh - language: lua - language: js match: javascript|js - language: json - language: java - language: php - language: xml text: xml - language: csharp source: cs match: csharp|cs - language: powershell - language: plantuml source: wsd - language: ditaa - language: graphviz source: dot - language: lisp source: lisp - language: emacs-lisp source: lisp - language: yaml - language: rust - language: sql - language: r(\s|$) source: r - language: html text: html.basic - language: go - language: ledger - language: beancount - language: make source: makefile - language: makefile source: makefile - language: typescript match: typescript|ts source: ts - language: clojure - language: bat|cmd source: dosbatch - language: org text: orgmode - language: pascal - language: actionscript source: actionscript.2 - language: applescript - language: dtd source: xml.dtd - language: haskell - language: (markdown|md)(\s|$) text: html.markdown - language: groovy - language: regexp source: regexp - language: ruby - language: restructuredtext text: restructuredtext - language: xsl text: xml.xsl - language: scala - language: hex - language: erlang - language: diff - language: d(\s|$) - language: css - language: cmake - language: asp - language: gnuplot - language: mermaid - language: awk - language: painless source: java ================================================ FILE: messages/1.0.1.org ================================================ * 1.0.1 - Improving link handling for local files. - Fixes some bugs around generating local file links. ================================================ FILE: messages/1.0.10.org ================================================ * 1.0.10 ** Snippets - Added link insertion snippet #+BEGIN_QUOTE _Org.sublime-color-scheme #+END_QUOTE It will then add a couple of key scopes such as: - orgmode.preamble :: which is used to make the leading stars invisible on a subheading - orgmode.state.* :: These are used to give the core built in states some color This also adds a comment block in the color scheme file that tries to help new users understand what their options are. Note this is based off your active color scheme. This will ALSO change the active OrgExtended color scheme to be this new color scheme to let you see how it is going to pan out. This may, or may NOT work out well for you! NOTE: This is a preview feature. It is still under active development and will change / improve as I mature it. I felt it might be beneficial to some to release it at this point. PLEASE only use this feature if you feel confident with your ability to manipulate sublime color schemes. I have yet to document the feature or test it on a wide variety of color schemes. Ultimately I would like to include the orgagenda and orgdatepicker schemes into this one scheme. To do that I need some more creative programmatic means of generating a starting color palette from a pre-existing one. That will take a bit. However, in the interim I am happily using a generated Guna color scheme on my personal machine. ================================================ FILE: messages/1.0.7.org ================================================ * 1.0.7 ** Color Scheme Generator - Date picker syntax extended to work with generic color schemes - Agenda picker syntax extended to work with generic color schemes - Color scheme generator has time delay to try to avoid popup errors when generating and switching color schemes. - Color scheme generator will generate some of the key agenda colors. - Color scheme generator will output a comment block for the date picker describing additional scopes. ================================================ FILE: messages/1.0.8.org ================================================ * 1.0.8 ** Folding - Fixed a bug where buffers that are lacking a filename can still be folded. ** Clocking new setting: - clockingSubMinuteClocks: true will now keep clocking entries that are smaller than a minute ** Movement - Fixed move heading up / move heading down. This now does the same as org-move-subtree-up and org-move-subtree-down. - Moves headings within siblings at the same level of the tree. ================================================ FILE: messages/1.0.9.org ================================================ * 1.0.9 ** Editing - Org Select Subtree This will select the full subtree of the active heading. - alt+o m s - m s (neovintageous normal mode) - Org Select Entity This will select just the current node - alt+o m e (mark entity) - m e (neovintageous normal mode) - Org Copy Subtree This will copy the entire subtree to the clipboard. - alt+o y s (yank entity) - y s (neovintageous normal mode) - Org Copy Entity This will copy the current node to the clipboard. - alt+o y e (yank entity) - y e (neovintageous normal mode) ** Folding - Fixed link tab cycling. ** Color Scheme Generator - The generator is now able to handle simple tmTheme files. NOTE: it converts them to sublime-color-scheme files in the output folder. - Added Org Select Color Scheme menu item to switch Org between color schemes you have already generated. NOTE: same caveats hold about having org files open when switching. Sublime does not automatically switch existing views. ** NeoVintageous - For ST4 users - neovintageous has upgraded to python 3.8 this means that my hacks to push register 0 with the values of the system clipboard aren't working until I upgrade OrgExtended. I will attempt to make that a priority for those that care. ================================================ FILE: messages/1.1.0.org ================================================ * 1.1.0 ** Scheduling - Support active timestamps vs SCHEDULED SCHEDULED is when you want to start on a task while tasks with a timestamp are scheduled at a point in time. #+BEGIN_EXAMPLE ** TODO Heading SCHEDULED: <-- This will appear in the agenda until you close the task ** TODO HEADING <-- This will appear in the agenda but only at the date specified #+END_EXAMPLE - BREAKING CHANGE Before I would only show tasks, these are items with an open TODO state. Now, by default anything that has an active timestamp or is scheduled will show up in the agenda UNLESS you set that view to :onlytasks as a parameter. #+BEGIN_EXAMPLE ** HEADING <-- This will now appear in the agenda where before it would not #+END_EXAMPLE #+BEGIN_SRC js "AgendaCustomViews": { "Default": ["Calendar", "Week", "Day : onlytasks", "Blocked Projects", "Next Tasks", "Loose Tasks"], "Todos": ["Todos"], } #+END_SRC Note the onlytasks parameter, that will filter out non tasks from the Day view in my default agenda view. - DEADLINE is still not supported but support should be comming in a future release. ================================================ FILE: messages/1.1.1.org ================================================ * 1.1.1 ** Scheduling - DEADLINE works in the agenda. Very minimal visualization at this time. Will show Warning, Due and Overdue messages on the right hand side of the day view. - DEADLINE: <........ -3d> basic warning cookies work - Fixed a bug with new SCHEDULED: behaviour in week view. - Removed visualization in the CalendarView for SCHEDULED and DEADLINE while I figure out the best way to visualize that, that is not super ugly. ** Editing - New Link Editing Commands Org Copy Href will copy the href out of a link onto the clipboard currently not bound to a keybinding. Org Select Href will select the href in a link, even if it is folded. currently not bound to a keybinding ================================================ FILE: messages/1.1.10.org ================================================ * 1.1.10 None of the new commands are bound to a keybinding. ** Blank Table Insert - "Org Insert Blank Table" - This will insert a blank WxH blank table at point. ** Csv Import - "Org Import Csv" - Still in its infancy - Added Org Import Cvs command. Will import a csv file into a table. ** Convert Region To Table - "Org Convert Region To Table" - Only works with commas at the moment. - Tries to convert a region to a table, will improve with time. ================================================ FILE: messages/1.1.11.org ================================================ * 1.1.11 ** Table Editing - Incorporated Table Edit keybindings allowing for column and row movement, navigation, inserting and deleting rows and columns and hline insertion with some key bindings. - Improved separator auto detection during import and region conversion. ================================================ FILE: messages/1.1.12.org ================================================ * 1.1.12 ** Tables REALLY preliminary table formula preview. It's buggy! The example below runs, but not much else will. [[https://orgmode.org/worg/org-tutorials/org-spreadsheet-intro.html][Spreadsheets In Org]] I am undecided if I will continue with attempting to use the python ast for my expression support or simply roll my own parser as my limited knowledge of the ast module has me at a loss of how to change the default grammar. (If anyone has input and knowledge here that would be beneficial) | a | b | c | d | e | |---+---+---+---+---| | a | b | 5 | 1 | 2 | | 1 | 1 | 1 | 1 | 1 | #+TBLFM: @3$5=vmean($1..$5)+sin(@3$1)::$4=$3+5 Things that work: - Evaluation of rows and columns with basic arithmetic - vmean, vmax, vmin and a handful of other functions - the basic range syntax seen above. - respecting the header in column expressions Things that do NOT work: - Automatically updating your expressions when you resize the table - Filling in a cell with an expression and having it automatically be moved to tablefmt - Cell highlighting when editing expressions. - calc style output formatting (semi colon) - Negative or other fancier ranges - Named fields - Visualizing columns - Horizontal separators are currently considered in cell indexes (this will be fixed) Right now evaluating a table is bound to the execute DWIM binding. ================================================ FILE: messages/1.1.13.org ================================================ * 1.1.13 ** Spreadsheets Preview V2 WARNING: Super experimental, use at your own risk. [[https://orgmode.org/worg/org-tutorials/org-spreadsheet-intro.html][Spreadsheets In Org]] - Horizontal rules are now respected in row ids - Cell highlight can help with understanding formulas - Fixed a couple of bugs with cell indexing - Calling execute on a cell with := will introduce a new formula into the TBLFM and evaluate the table. - = Should add a column expression | a | b | c | d | e | |---+---+---+---+------| | a | b | 5 | 4 | :=$1 | | 1 | 1 | 1 | 1 | 1 | #+TBLFM: @3$5=vmean($1..$4)+sin(@3$1)::$4=$3+5::@2$5=$1 Still very poorly tested but improving. Things that work: - Evaluation of rows and columns with basic arithmetic - vmean, vmax, vmin and a handful of other functions - the basic range syntax seen above. - respecting the header in column expressions - filling in a cell with an expression and having it automatically be moved to tablefmt - cell highlighting when editing expressions. - horizontal separators are now respected as non cells. Things that do NOT work: - Automatically updating your expressions when you resize the table - calc style output formatting (semi colon) - Negative or other fancier ranges - Named fields - Visualizing columns Right now evaluating a table is bound to the execute DWIM binding. NOTE: This feature will never be completely compatible with ORG. Org supports the ability to execute arbitrary lisp expressions on table cells. We aren't going that far. That said, I really appreciate the basics of the spreadsheet feature in org and we should be able to support most of the basics with our own flair. ================================================ FILE: messages/1.1.14.org ================================================ * 1.1.14 ** Spreadsheet Preview V3 - Column cell formula insertion was broken, this is now fixed. - TBLFM expressions on their own lines would cause exceptions - Added non standard row insertion using >= syntax. While testing this found a bug in row expressions | a | b | c | d | e | |---+---+---+----+--------------------| | a | b | 5 | 10 | >=@3 | | 1 | 1 | 1 | 6 | 3.0914709848078967 | #+TBLFM: @3$5=vmean($1..$4)+sin(@3$1)::$4=$3+5::@2=@3 - Still using a hacked up version of simple_eval and python ast for the expression parser. Decided using functions rather than names for the expression differences made sense. Even though this is a bit of a misuse of the parser I think I will stick with this approach, it's simple it's functional and will allow me to support the other variable modifiers in the end. - Right now the parser is pretty locked down. - I will probably never support arbitrary lisp like spreadsheets like emacs can. (As much as it would be fun to build a lisp parser here, it's kind of missing the rest of emacs and the massive function library) - Cleaned up some asserts that happened when editing a table. The highligher didn't like targets changing on the fly. - That said, I may support more and more of the calc library and even allow some user made extensions eventually. - My eventual goal is to flesh out my babel hack to a more full featured version with all the power that comes along with that. Without TRAMP, remote sessions etc. some of the power of bable is muted a little bit. (But who knows, maybe TRAMP is possible in sublime...) That said, we need powerfull spreadsheet support as an input source before really going to town on bable is possible. *** New Cell Identifiers With the refactor on how I am handling cells I can now support the > and relative cell identifiers -1 is one to the left or one up from the current target being calculated. It is a relative identifier. > means last column while >> means last but one. | a | b | c | d | e | |---+---+---+----+--------------------| | a | b | 5 | 10 | >=@3 | | 1 | 1 | 1 | 6 | 3.0914709848078967 | #+TBLFM: @>$5=vmean($1..$4)+sin(@-1$-1)::$4=$#+5::@2=@3 - In addition we have index symbols $# is the current column and @# is the current row | idx | Index Gen | |-----+---------------| | 1 | Testing Index | | 2 | Generation | #+TBLFM: $1=@#-1 - Constants defined in your file can also be used in expressions #+CONSTANTS: hello=world a=b | x | y | | world | b | #+TBLFM:@2$2=$a::@2$1=$hello Things that work: - Evaluation of rows and columns with basic arithmetic - vmean, vmax, vmin and a handful of other functions - the basic range syntax seen above. - respecting the header in column expressions - filling in a cell with an expression and having it automatically be moved to tablefmt - cell highlighting when editing expressions. - horizontal separators are now respected as non cells. - Negative (relative) or arrow cell indexes - Index symbol $# and @# Things that do NOT work: - Automatically updating your expressions when you resize the table - calc style output formatting (semi colon) - Advanced tabled features / Named fields - box range targets - Visualizing columns - gnu plot support - hline symbols - more functions - remote() references to other named tables. ================================================ FILE: messages/1.1.15.org ================================================ * 1.1.15 ** Spreadsheets Preview V4 - Fixed a bug with row ranges not expanding properly - Fixed an issue with tables at the last row of the file. - Added random(a,b) - integer random range - Added randomf() - 0.0..1.0 random range - Range targets are now supported: | a | b | c | d | |----------+----------+----------+----------| | 0.506666 | 0.995246 | 0.5519 | 0.061723 | | 0.065874 | 0.993011 | 0.241133 | 0.410426 | #+TBLFM:@2$1..@3$4=randomf() - Removed some extraneous trace information. | a | b | c | d | e | |---+---+---+---+----| | 3 | 4 | 5 | 6 | 7 | | 2 | 4 | 6 | 8 | 10 | #+TBLFM:@2=$#+2::@3=$#*2 ================================================ FILE: messages/1.1.16.org ================================================ * 1.1.16 ** Spreadsheet Preview V5 - Moving cells around, adding and deleting cells is now starting to try to keep formulas intact now! - Deleting the target or source of a cell will result in the formula having and $INVALID or @INVALID tag which is not currently handled properly. This will be improved going forward! ================================================ FILE: messages/1.1.17.org ================================================ * 1.1.17 *** Spreadsheets Preview V6 :PROPERTIES: :testval: 5 :END: - Invalid cell references now are not assserting in the obvious cases. - Invalid cell references now generate a status message during the highligh phase to let you know you have invalid cell references: - Fixed a bug with column lookup where it would return curcol sometimes rather than fixed reference. | a | b | c | d | e | | 1 | 1 | 1 | 1 | 1 | | 2 | 2 | 2 | 2 | 2 | #+TBLFM:@INVALID=@2+1 - Removed a bunch of silly debugging prints that were left around from 1.1.16 release! - SOME support for formatting suffix in formulas: - N - Will treat empty cells as 0 - %.#f - Will output # decimal places like a printf | a | b | c | d | e | | 1 | 1 | | 1 | 1 | | 0.476 | 0.476 | 0.0 | 0.476 | 0.476 | #+TBLFM:@3=@2/2.1;N%.3f - Additional functions: - floor - ceil - round - trunc - Properties can be referenced in an equation: $PROP_ (See property in node above) #+NAME: TestName | a | b | c | d | e | | 5 | 10 | 15 | 20 | 25 | #+TBLFM:@2=$PROP_testval*$# #+CONSTANTS: pi=3.1415926 | a | b | c | d | e | | 3.1 | 6.3 | 9.4 | 12.6 | 15.7 | #+TBLFM:@2=$pi*$#;%.1f - Remote table references here we are grabbing a value from the tabled named TestName above: | a | b | c | d | e | | 10 | 10 | 10 | 10 | 10 | #+TBLFM:@2=remote('TestName',@2$2) CURRENT FUNCTIONS: - vmean - vmedian - vmax - vmin - vsum - tan - cos - sin - exp - floor - ceil - round - trunc - randomf - random Things that work: - Evaluation of rows and columns with basic arithmetic - vmean, vmax, vmin and a handful of other functions - the basic range syntax seen above. - respecting the header in column expressions - filling in a cell with an expression and having it automatically be moved to tablefmt - cell highlighting when editing expressions. - horizontal separators are now respected as non cells. - Negative (relative) or arrow cell indexes - Index symbol $# and @# - Automatically updating your expressions when you resize the table - box range targets - basic printf style formatting after semi colon for floating point types: $2=$1/2.0;%.1f - Properties and constants (defined in a CONSTANTS comment) can be used in formulas - remote() references to other named tables. Things that do NOT work: - Extended calc style output formatting (semi colon) - Advanced tabled features / Named fields - Visualizing columns - gnu plot support - hline symbols - more functions ================================================ FILE: messages/1.1.18.org ================================================ * 1.1.18 ** Spreadsheets - A crude stab at a table visualization - "Org Show Table Rows" - will show a set of phantoms that ID the rows and columns to help when authoring formulas - "Org Hide Table Rows" - will hide the phantoms. - Fixed positive relative offsets, they were not working: | a | b | c | d | e | f | | 4 | 5 | 6 | 7 | 8 | 9 | | 1 | 2 | 3 | 4 | 5 | 6 | #+TBLFM:@2= @+1+3 Things that work: - Evaluation of rows and columns with basic arithmetic - vmean, vmax, vmin and a handful of other functions - the basic range syntax seen above. - respecting the header in column expressions - filling in a cell with an expression and having it automatically be moved to tablefmt - cell highlighting when editing expressions. - horizontal separators are now respected as non cells. - Negative (relative) or arrow cell indexes - Index symbol $# and @# - Automatically updating your expressions when you resize the table - box range targets - basic printf style formatting after semi colon for floating point types: $2=$1/2.0;%.1f - Properties and constants (defined in a CONSTANTS comment) can be used in formulas - remote() references to other named tables. - Visualizing columns and rows Things that do NOT work: - Extended calc style output formatting (semi colon) - Advanced tabled features / Named fields - gnu plot support - more functions ================================================ FILE: messages/1.1.19.org ================================================ * 1.1.19 ** Spreadsheets Preview V7 - Added the ability to add your own functions Create a file with the name of your function in: #+BEGIN_EXAMPLE Packages/User/orgtable/.py #+END_EXAMPLE Here I have created a file called nowstr.py: #+BEGIN_SRC python def Execute(): import sublime import datetime return str(datetime.datetime.now()) #+END_SRC The module will be run dynamically so your imports are best to put in the function as seen above. If your function takes cells they should be parameters to Execute. In my example I am returning the current datetime as a string: | 2021-03-03 12:42:03.720657 | b | c | d | e | | 2021-03-03 12:42:03.738691 | | | | | #+TBLFM:$1=nowstr() I will have further examples in the documentation going forward. - Fixed a couple of asserts found when navigating tables. This feature is considered an advanced feature and is disabled by default in your settings file. #+BEGIN_EXAMPLE "enableTableExtensions": true, #+END_EXAMPLE *** Data Time methods Added a bunch of the datetime methods | A | |----------------------------| | 2021-03-03 19:56:44.294403 | | 2021 | | 3 | | 3 | | 2021-03-03 | | 19:56:44.375228 | | 19 | | 56 | | 44 | | 2 | | 62 | #+TBLFM:@2$1=now()::@3$1=year(now())::@4$1=month(now())::@5$1=day(now())::@6$1=date(now())::@7$1=time(now())::@10$1=second(now())::@9$1=minute(now())::@8$1=hour(now())::@11$1=weekday(now())::@12$1=yearday(now()) ** Checkboxes :PROPERTIES: :COOKIE_DATA: recursive :END: Recursive todo summary data. NOTE: this counts ALL checkboxes as if they are part of the parent checkbox not just leaves. This can be set using the COOKIE_DATA property above or using the global setting: #+BEGIN_EXAMPLE "checkboxSummaryRecursive": true, #+END_EXAMPLE - [-] Testing parent [3/6] - [x] A - [-] B - [ ] C - [x] D - [x] E - [ ] F Supporting this was a request from: [[https://github.com/ihdavids/orgextended/issues/13][Checkbox summaries]] ================================================ FILE: messages/1.1.2.org ================================================ * 1.1.2 - Added OrgDeadlineCommand OrgScheduleCommand OrgActiveTimestampCommand to add SCHEDULE, DEADLINE and active timestamps using the quick picker. ================================================ FILE: messages/1.1.20.org ================================================ * 1.1.20 ** Editing - Heading and Child heading insertion now ignores whitespace at the end of a node ** Extensions - Improved extension reloading on modification. Before it would force reload to often now we track and reload only when we have to. This should improve table performance a little. This is in prep for the advanced table features including automatic cell calculations on # fields. - Extension folders renamed for consistency: - src folder renamed to orgsrc - resolver folder renamed to orgresolver - dynamic folder renamed to orgdynamic - table extensions were already in orgtable ** Spreadsheets Preview V7 - Fixed small issue with syntax coloring ** Syntax - Added lisp coloring for source blocks marked with lisp or emacs-lisp as the language. Also added the following language identifiers to src blocks: - yaml - rust - sql - r - html - go - ledger - make|makefile - typescript|ts ================================================ FILE: messages/1.1.21.org ================================================ * 1.1.21 ** Db - orgFiles was not working, this has been fixed. [[https://github.com/ihdavids/orgextended/issues/16][orgFiles does not work]] - Files with a BOM. I can't easily handle BOMs but I now do try to detect it and swap encodings if I fail to load the file as utf-8. - Notifications fix. The notification system was asserting on SCHEDULED: where date did not have a time. ** Spreadsheets Preview V8 - Fix for floating point values. - VERY early support for gnuplot To use: - install gnuplot - Set your gnuplot path: #+BEGIN_EXAMPLE "gnuplot": "", #+END_EXAMPLE - Run "Org Plot Table" with cursor on the table - Right now I am just dumping an image and using the inline image show option in the future I may change that. #+PLOT: title:"Citas" ind:1 deps:(3 4) with:lines set:grid | Sede | Max | H-index | top | |-----------+--------+---------+-------| | Sao Paolo | 71.00 | 11.50 | 13.5 | | Stockholm | 134.19 | 14.33 | 16.33 | | Leeds | 165.77 | 19.68 | 21.68 | | Morelia | 257.56 | 17.67 | 19.67 | | Chile | 257.72 | 21.39 | 23.39 | #+TBLFM:$4=$3+2.0 ================================================ FILE: messages/1.1.22.org ================================================ * 1.1.22 ** Configuration - Added directory globbing support to orgDirs #+BEGIN_EXAMPLE "c:\\Users\\ihdav\\notes\\**\\test\\" #+END_EXAMPLE This will find valid org extensions in all test sub folders of the path. CAUTION: This will slow down sublime start times with overly large search space! ** Spreadsheet Preview V9 - GPU Plot support extended: file option now allows for several output formats: - file.txt - dumb option in gnu plot. - file.html - canvas option in gnu plot. - file.jpg - jpeg option in gnu plot. - file.png - png option in gnu plot. - file.svg - svg option in gnu plot. - file.ps - postscript option in gnu plot. - file.gif - gif option in gnu plot. - GPU Plot - Added include:header to include header row in data (you have to account for it in your plot) - Added using statement to allow you to write your own full using statement rather than just the style: - Improved quoting, spaces in fields are accounted for and quoted. - Improved indent of RESULTS block. #+PLOT: title:"Citas" include:header ind:1 deps:(2 3 4) set:"key autotitle columnheader" unset:xtics set:"auto x" set:"boxwidth 0.25" using:"using 2:xtic(1), for [i=3:4] '' using i" set:"style data histogram" set:"xtics nomirror rotate by -45 scale 0" set:"style histogram rowstacked" set:"style fill solid border -1" file:plot.png | Sede | Max | H-index | top | |-----------+--------+---------+-------| | Sao Paolo | 71.00 | 11.50 | 13.5 | | Stockholm | 134.19 | 14.33 | 16.33 | | Leeds | 165.77 | 19.68 | 21.68 | | Morelia | 257.56 | 17.67 | 19.67 | | Chile | 257.72 | 21.39 | 23.39 | #+TBLFM:$4=$3+2.0 #+RESULTS: [[file:C:/Users/ihdav/AppData/Roaming/Sublime Text/Packages/OrgExtended/messages/plot.png]] ** Source Blocks - PlantUml info in docs. - Added auto image preview mode when creating images using diagram methods. *** New Source Block type - GraphViz support. - Only dot engine is currently supported. - To use add graphviz path to settings file: #+BEGIN_EXAMPLE "graphviz": "C:\fullpath\dot.exe" #+END_EXAMPLE Create a source block like so and execute it #+BEGIN_SRC graphviz :file graphviz.png digraph G { a -> b; a -> c; c -> d } #+END_SRC ================================================ FILE: messages/1.1.23.org ================================================ * 1.1.23 ** Configuration - orgDirs - in 1.1.22 we added support for directory globbing. We have added a little more error handling in 1.1.23 to detect single stars rather than double stars and to not throw in those cases. #+BEGIN_EXAMPLE D:\mypath\**\ - This is supported D:\mypath\*\ - This is NOT supported #+END_EXAMPLE ** Source Blocks - Improved handling of unsaved files when executing source blocks. NOTE: Sublime WILL save the file for you if it has already been saved, or error out. [[https://github.com/ihdavids/orgextended_docs/issues/5][PlantUml Example Request]] *** GraphViz Blocks - added engine (neato, dot, etc) - added fmt (jpg, ps, png) #+BEGIN_SRC graphviz :fmt jpg :engine neato :file graphviz.jpg digraph G { a -> b; a -> c; c -> d } #+END_SRC *** Ditaa Src Blocks To use: Add the path to ditaa.jar from sourceforge in your settings file: #+BEGIN_EXAMPLE "ditaa": "/ditaa.jar", #+END_EXAMPLE Create a source block with your diagram. (Nope, we don't have an artist mode for sublime yet) #+BEGIN_SRC ditaa :file ditaa.png +--------+ +----------+ | Hello | ----> | Hello2 | +--------+ +----------+ #+END_SRC Execute the block and you should now have a diagram! ================================================ FILE: messages/1.1.24.org ================================================ * 1.1.24 ** PlantUml - Fixed bug with working directory that was causing problems when executing as a package. ================================================ FILE: messages/1.1.25.org ================================================ * 1.1.25 ** Source Block Diagrams - Non existent subdirs are auto-created - Execute block works on any line inside the source block as well as on the fence. - Evaluating a block on the last line of the file was not inserting the RESULTS tag. - Repeated re-evaluation kept adding newlines at the end. - When evaluating source with a diagram the cursor could move, this is now fixes. #+BEGIN_SRC graphviz :file thisdirdoesnotexist/graphviz.png digraph G { a -> b; a -> c; c -> d; } #+END_SRC #+RESULTS: [[file:thisdirdoesnotexist\graphviz.png]] ** Customization - Support single directory wildcards: #+BEGIN_EXAMPLE "orgDirs": "C:\Mypath\*\SubFolder" #+END_EXAMPLE Will match a single folder wildcard like so: - C:\Mypath\foo\SubFolder\x.org - C:\Mypath\bar\SubFolder\y.org - C:\Mypath\baz\SubFolder\z.org Again, this can increase your startup time dramatically. Please use with caution! ** Spreadsheet Preview V10 - boxes mode seems to work. #+PLOT: title:"Box" ind:2 deps:(3 4) with:boxes file:plot.png | Sede | Max | H-index | top | |-----------+--------+---------+-------| | Sao Paolo | 71.00 | 11.50 | 13.5 | | Stockholm | 134.19 | 14.33 | 16.33 | | Leeds | 165.77 | 19.68 | 21.68 | | Morelia | 257.56 | 17.67 | 19.67 | | Chile | 257.72 | 21.39 | 23.39 | #+TBLFM:$4=$3+2.0 *** Start of Advanced Table Features - Auto computed cells now mostly work. Careful with these in big tables. They only auto compute when you use tab or shift tab to move between cells, arrow keys do not recompute - Row names seem to work work. - Above and Below names seem to work - Symbol rows seem to work | | a | b | c | |---+-------+-------+----------| | # | 0.38 | 0.1 | 0.46 | | # | 0.38 | 0.1 | 0.86 | | # | 0.03 | 0.6 | 0.01 | | * | 0.02 | 0.0 | 0.06 | | ^ | hello | world | namedRow | | * | | 0.3 | | | | | | | | _ | below | | | | # | 3.5 | 0.7 | | | # | 4.5 | 0.9 | | | # | 4.0 | 0.8 | | | # | 2.0 | 0.4 | | | $ | max=5 | | | #+TBLFM:$hello=rand()*$world;%.2f::$namedRow=rand();%.2f::$3=rand();%.1f::$below=$3*$max ** HTML Export Fixed issue with 0 blank lines at the top of the file. The comment gathering code was not being initialized properly. ================================================ FILE: messages/1.1.26.org ================================================ #+COLUMNS: %ITEM(Task) %Effort(Effort) %TODO(Todo) %DEADLINE(Deadline) %ALLTAGS(Tags) %TIMESTAMP(Time) %TIMESTAMP_IA(Inactive) %PRIORITY(Priority) * 1.1.26 :a: ** Configuration - improvements to orgdir globbing / error handling / parsing thanks to Anti-Distinctlyminty ** DONE Source Blocks :PROPERTIES: :EFFORT: 2d :END: New languages colored in source blocks: - clojure - bat|cmd - org - pascal - actionscript - applescript - dtd - haskell - markdown|md - groovy - regexp - ruby - restructuredtext - xsl - scala - hex - erlang - diff - d - css - cmake - asp - json - r ** Folding - Block folding inside a block was driving me nuts I have changed it so you can only fold a dynamic block or a source block from its header If this bothers you, we can make this configurable, just let me know. ** Properties DEADLINE: <2021-03-09 Tue 20:55> :PROPERTIES: :EFFORT: 2d :END: - New Command: "Org Create Heading Id" This will add a UUID ID to the current heading. - Db handling of ids reworked a little to support jumping to an ID or a CUSTOM_ID - New Command: "Org Insert Effort" Must be org duration format. Will insert an effort property defaultEffortEstimateUnit - setting (defaults to d) can be used to set the default effort unit ** Spreadsheets Preview V11 :tag: :PROPERTIES: :EFFORT: 4h :END: <2021-03-09 Tue 14:53> - remote function can now take a custom id or id as per: [[https://lists.gnu.org/archive/html/emacs-orgmode/2010-01/msg00420.html][Remote Table References]] - Nodes now have a table property that lists the position of the first table in the node. - It doesn't really work well because the existing table system requires a view, which means that we have to load the file which cannot easily be done during the execution of a formula. This means you can get odd tab swaps if you have a remote reference and the file is not opened. I will have to think about another way of handling this in the future. ** [#B] ColumnView Dynamic Block :PROPERTIES: :EFFORT: 1d :END: [2021-03-09 Tue 11:00] Part of the reason for the tags, priorities and effort markers in these release notes is to show the new column view dynamic block. It is still in its infancy. It has none of the summary functionality of the real column view. It also only has a limited set of handlers. It can access properties and has the following built in handlers: - ALLTAGS All tags, including inherited ones. - CLOSED When was this entry closed? - DEADLINE The deadline timestamp. - FILE The filename the entry is located in. - ITEM The headline of the entry. - PRIORITY The priority of the entry, a string with a single letter. - SCHEDULED The scheduling timestamp. - TAGS The tags defined directly in the headline. - TIMESTAMP The first keyword-less timestamp in the entry. - TIMESTAMP_IA The first inactive timestamp in the entry. - TODO The TODO keyword of the entry. Parameters that work: - hlines - maxdepth - id (local, global, ID value, file:) - indent - skip-empty-rows - exclude-tags Parameters that do not yet work: - match #+BEGIN: columnview :hlines nil :id global :indent t :maxdepth 2 :skip-empty-rows t :exclude-tags (ExcludeMe) | Task | Effort | Todo | Deadline | Tags | Time | Inactive | Priority | | 1.1.26 | | | | a | | | | | ..Source Blocks | 2d | DONE | | a | | | | | ..Folding | | | | a | | | | | ..Properties | 2d | | 2021-03-09 Tue 20:55 | a | | | | | ..Spreadsheets Preview V11 | 4h | | | a tag | 2021-03-09 Tue 14:53 | | | | ..ColumnView Dynamic Block | 1d | | | a | | 2021-03-09 Tue 11:00 | B | #+END: I am slowly driving towards being able to do this: [[https://www.youtube.com/watch?v=5ViUBaarsbw][Gantt Charts in Org Mode]] I don't have column mode yet, but we will get something like it eventually. *** ColumnView Beyond Max Depth ** Excluded Because Of Tag :ExcludeMe: * Empty ================================================ FILE: messages/1.1.27.org ================================================ * 1.1.27 ** Archiving - Fixed a bug where ARCHIVE_TIME was missing a colon at the front when inserted. - Switched archiving to save as utf-8 by default to avoid some of the unicode problems I have been running into. ** Editing - Org Insert Now Active - Inserts right now as an active datetime - Org Insert Now Inactive - Inserts right now as an inactive datetime - Org Insert Date Active - Pops up the date picker to insert an active datetime - Org Insert Date Inactive - Pops up the date picker to insert an inactive datetime - Dynamic Block Snippet: #+BEGIN_EXAMPLE | <2021-03-09 Tue 22:25> | 5d | <2021-03-15 Mon 22:25> | 5d | 50 | 20% | 10.0 | #+TBLFM:@2$2=date($-1)-1::@2$4=date(@2$1)+duration($-1)::@2$5=$3 if True else 5::@2$9=$-2*$-1 ** Columnview - Empty properties still make a row in the column view (allowing you to setup additional rows for calculations) - Table format blocks can live after the end marker on a dynamic block. This is not org standard but it lets us build formulas for generated tables which can be really handy on clock tables and columnviews (building timesheets and project plans) - Org syntax is turned on inside a dynamic block now allowing tables to be highlighted inside the block. #+COLUMNS: %ITEM(Task) %Effort(Effort) %TESTING(Testing) #+BEGIN: columnview | Task | Effort | Testing | | 1.1.27 | | | | Archiving | | | | Editing | | | | Spreadsheet Preview V11 | | | | Columnview | | | #+END: #+TBLFM:@2$9=5 ================================================ FILE: messages/1.1.28.org ================================================ * 1.1.28 ** Dynamicblocks - Params structure is now a PList class and has: - Get(name,default) :: Returns the parameter as a string value - GetInt(name,default) :: Returns the parameter as an int value - GetFloat(name,default) :: Returns the parameter as a float value - GetList(name,default) :: Returns the parameter as a list of strings - GetIntList(name,default) :: Returns the parameter as a list of ints Plists now support double quotes "" and () brackets delimiting parameter values. ** Image Links - Fixed an assert that could happen when backing image was removed. - Sublime will now show the non image icon as expected. - ORG_ATTR comments on image links with plists specifying image dimensions are now respected in inline sublime visualization of an image. #+BEGIN_EXAMPLE #+ORG_ATTR: :width 700 #+END_EXAMPLE ** Spreadsheets Preview V12 Mostly quality of life improvements in this release. - Table cache works across files properly now. - Turned off highlight updates during formula execution it was costing us during the update needlessly. - Improved function table, symbol table and constants table construction. They are now lazy loaded and reused as much as possible for all tables reducing the costs associated with highlighting cells and navigation. - In the interest of supporting only pay for what you use. Dynamic table extensions (user added functions) are reloaded ONCE when the tables are first constructed, if you are developing a function for table handling you can now turn on: #+BEGIN_EXAMPLE "forceLoadExternalExtensions": True #+END_EXAMPLE In your settings to dynamically reload your extension all the time. This reduces the cost of building the function table. - Added abs function | a | d | | |------+---+----| | 0.50 | 2 | 51 | | 0.46 | 3 | 56 | | 0.19 | 4 | 2 | | 0.02 | 5 | 3 | | 0.49 | 6 | 4 | | 0.64 | 7 | 5 | #+TBLFM:$1=rand();%.2f::$2=abs(-@#)::$3=remote("my-table-test",$2) - Improved remote() function, it no longer requires you to open a view / tab although the file has to have been parsed so should be in your orgDirs / orgFile list. - Added the ability to add dynamic symbols as well as functions. To use add a python file in your User folder like so: #+BEGIN_EXAMPLE .../Packages/User/orgtable/mysymbols.py #+END_EXAMPLE And add the symbols you would like exposed for use in your tables. #+BEGIN_SRC python def AddSymbols(symbolTable): symbolTable['pi'] = 3.14159268 symbolTable['c'] = 299792458 #+END_SRC ** Source Blocks - gnuplot language added to syntax, to use install the GNU Plot package. ** Folding - "Org Fold Others" - New command that folds all other headings but the immediate part of the tree you are on. ================================================ FILE: messages/1.1.29.org ================================================ * 1.1.29 Core Idea: Add GNU Plot Script Blocks - [x] Add a syntax for gnu plot script blocks if one does not already exist - [x] Add a src handler to execute these script blocks. ** Spreadsheets Preview V13 - Fixed a bug with TBLFM appearing after a END marker on dynamic blocks - Fixed a bug with if statements and equals signs in TBLFM blocks - Fixed a bug with tables where it would look up the properties on the root node of the file. this would cause an assert. ** GNU Plot Script Block We now have a GNU Plot script block and source handler. We have a very limited set of source hanlders. Here is some gnu plot code that draws a sine wave if executed and gnuplot can be found in your settings file. The requirements are the same as those for table plotting. #+BEGIN_SRC gnuplot :file gantt-table.png # We don't need a key (or legend) for this simple graph. set key off # Set the title for the graph. set title "Sine against Phase" # We want the graph to cover a full sine wave. set xrange [0:6.28] # Set the label for the X axis. set xlabel "Phase (radians)" # Draw a horizontal centreline. set xzeroaxis # Pure sine wave amplitude ranges from +1 to -1. set yrange [-1:1] # No tick-marks are needed for the Y-axis . unset ytics # Plot the curve. plot sin(x) #+END_SRC #+RESULTS: [[file:gantt-table.png]] - Params for src blocks have been converted to use the new PList system added in 1.1.28 - Source Blocks now have a PreProcessSourceFile() method that allows for injection of file and other paramters into the source block. - GNU Plot is the first module to start implementing the data source mechanism: The following example generates a graphed line line by feeding the data in my-table into gnu plot using babel like mechanics. NOTE: Babel is in its infancy in our system. We have source handlers for python, powershell, gnuplot, ditaa, plantuml, graphviz and that is it. ONLY GNU Plot can read from tables at this time. This will change. #+NAME: my-table | 1 | 2 | | 2 | 3 | | 3 | 4 | #+BEGIN_SRC gnuplot :var DATA=my-table :file my-table.png plot "$DATA" using 1:2 with lines title "hello" #+END_SRC #+RESULTS: [[file:my-table.png]] ** Powershell Block Execute Bug - this was using the OrgExtended package dir as it's cwd which was causing problems when running as a package. FIXED. ================================================ FILE: messages/1.1.3.org ================================================ * 1.1.3 - Fixing regression in 1.1.2 New shared keybinding command was being instantiated improperly ================================================ FILE: messages/1.1.30.org ================================================ * 1.1.30 Core Idea: Testing pass on tables to ensure what is there is relatively usable. ** Spreadsheet Preview V14 - added: - bool(cell) - int(cell) - float(cell) to convert string cells to boolean, ints and floats explicitly if desired - added highlight(cell,color,text) which highlights a cell a specific color for you - added passed(test) that will highlight a target cell green or red and write PASSED or FAILED into the cell. We are using this for unit testing at the moment. - added unit tests org file for tables. - Execute table now restores the cursor after the evaluation of the table improving usability. - Fixed assert when cursor was on a formula during table formula execution due to call to table_editor_align requiring the cursor be in the table - Fixed a bug with <= not evaluating properly next to a cell name ($1<=$2 would fail) - Added Org Execute All Tables - scans the whole file for tables and executes all of them. - Improved all date functions handling of datestrings - Fixed double digit row index parsing, @10$2 was failing to parse properly sometimes. - Fixed a bug with vmedian where it would sometimes not compute the median! - More docs including a little view of the new highlight in action in a unit test capture: (at the bottom of the tables doc) [[https://github.com/ihdavids/orgextended_docs/blob/master/tables.org][Tables]] - New documentation on adding the emacs constants.el to your table experience in docs [[https://github.com/ihdavids/orgextended_docs/blob/master/mathconstants.org][Math Constants]] ** GNU Plot - Calling "Org Plot Table" on the #+PLOT: header rather than the table would cause problems. ================================================ FILE: messages/1.1.4.org ================================================ * 1.1.4 ** Editing - Changed default keybinding. Capture is now Alt+o z to mirror neovintageous mode with Z (it also did not work before due to other Alt+o c ... commands) ** Stability - Removed legacy automatic copy of settings files to User folder now that we are using the new dual pane settings mechanic. This was causing an assert on startup for users on ST3. - Active timestamps with ranges were not showing up in the agenda properly. This was due to how the timestamps were querried. Should now be fixed. - Closed Scheduled timestamps would show up in the week view even after the scheduled date. this was a byproduct of the new scheduled behaviour and has been fixed. When closed the items will show up ONLY for the date they were scheduled. (They do not reflect) the date at which they were closed. In the future I hope to make that happen. NOTE: they do not show up in the day view at the moment. I will work to improve that in a future release. - Toggling a task to done with a recurring timestamp will set the LAST_REPEAT and LOGBOOK entries properly now and will update the base timestamp. ================================================ FILE: messages/1.1.5.org ================================================ * 1.1.5 ** Stability and Performance - Fixed some issues in the agenda with old SCHEDULED: values We would search forward in time forever trying to find a match in the agenda. This could make org files with REALLY old SCHEDULED tasks that were not closed take a long time to render in the agenda. I have now capped it. 4 Months is the default: This goes for deadlines, active timestamps and scheduled values. In addition I have enabled some caching for following repeat rules which should improve overall performance here. #+BEGIN_EXAMPLE agendaMaxScheduledIterations: 120 #+END_EXAMPLE - Working to improve handling of dates without times in the agenda. This could cause some assertions in some of the new scheduled and deadline handling systems I believe I have all the asserts now but I am working on ensuring intuitive behaviour. - Fixed display of plain (no time) DEADLINES, they now show the due date properly - Fixed closing of plain (no time) DEADLINES, they would assert before when trying to update the time. ================================================ FILE: messages/1.1.6.org ================================================ * 1.1.6 - Added keybindings utility function to help author docs. - Bug found with active timestamps not recurring properly datetime conversion was not working properly ================================================ FILE: messages/1.1.7.org ================================================ * 1.1.7 ** Editing - Request: [[https://github.com/ihdavids/orgextended/issues/13][Checkboxes in Headings]] - Checkbox summaries at the END of a heading but before tags are now supported and will be updated when a checkbox is toggled: *** TODO [#A] Heading with summary [33%] :TAG: - [ ] A - [ ] B - [x] C - [x] D ** Agenda - Request: [[https://github.com/ihdavids/orgextended/issues/10][Agenda Items Not Showing]] - Org Agenda will reload all open buffers to pick up agenda items in unsaved buffers ================================================ FILE: messages/1.1.8.org ================================================ * 1.1.8 ** Editing - DWIM editing of numbered lists has improved slightly Fixed some bugs with lists at the end of a buffer or with a blank line above the list. - DWIM editing of standard unordered lists (not checkbox) is now supported properly. - Indent and DeIndent somewhat work on lists (tabs vs spaces are still a little problematic) ================================================ FILE: messages/1.1.9.org ================================================ * 1.1.9 ** Editing *** Improved DWIM Additions to Numbered lists A numbered list preceded by a normal list was confusing DWIM extension. The system was putting the new entry above the unordered list. #+BEGIN_EXAMPLE - This would disrupt DWIM editing of the list below - DWIM was finding this list and thinking it was part - of the numbered list. 1. I am extending this list 2. This is the list I am extending #+END_EXAMPLE The same thing could happen for example blocks or src blocks. *** Improved Alternate Additions to Lists - Ctrl+Shift+Enter is an extended insert For numbered lists it will extend the list vs insert where you are. - This should now work for all the list types. *** Org Sort List - Works when cursor is on list types. - Will sort the list aphabetically ** Agenda - Loose Tasks View was sometimes not detecting top level loose tasks ================================================ FILE: messages/1.2.0.org ================================================ * 1.2.0 Core Idea: I am considering the spreadsheet feature out of preview now. most of the core org features with spreadsheets are now supported. While there are a ton of functions yet to support to have calc equivalence I believe what we have is a pretty good line in the sand to say we have something some usable. ** Spreadsheets Beta More core functions - tanh - cosh - sinh - atanh - acosh - asinh - atan - acos - asin - degrees - radians - sqrt - pow - log - log10 - log2 Added unit tests for these functions. ** Editing - New Command: "Org Insert Archive Tag" will add the :ARCHIVE: Tag to a node. Not currently bound to a key. - ARCHIVE tag gets filtered out by default in agenda. This means archived TODO's do not accidentally show up if you have a FILETAG on your archive file. - Fixed a bug with moving headings up and down when the heading is at the end of the file. ** Tags - FILETAGS comment is now respected properly as an inheritied tag on a heading. ** Notifications - Notifications system now respects the ARCHIVE tag. ================================================ FILE: messages/1.2.1.org ================================================ * 1.2.1 Just like 1.2.0 was focused on supporting tables 1.3.0 has a focus on better babel support. Core Idea for 1.2.1: Input - More language handlers supporting table and list data sources. This is a fairly simple first step into the world of babel. The GNU Plot handler paved the way for this we are just adding the same support to the other handlers. Right now we only really have python and powershell handlers anyways. As this matures we will document how to add your own language handlers as well as extend the list of supported languages. There is still more to do with input. This gets us 30% of the way to handling input sources. We still have to improve our plist handle spaces a little better and then handle the various ways that variables can be set for handlers vs the local mechanism. We also need to handle source blocks being the source of data for other source blocks. We are going to hold off on that until we have a slightly better handle on the various execution types for source blocks. ** PlantUML - Thanks to Antidistinctlyminty for improving file handling in the plantuml source block handler. The module not respects the :file tag properly. This was actually fixed in the 1.2.0 release but went unmentioned. ** Lists - fixed a bug with unordered list sorting including source blocks. ** Source Block Output Formatting - In preparation for working on output formatting in a future release (for babel) we have tweaked the output formatting to respect indents a little better when executing source blocks. ** Python Python now supports tables as data sources. True babel execution would auto format the output or provide controls over how we handle the output but... these are our first steps here. #+NAME: p-data | a | b | c | d | e | |---+---+---+---+---| | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | #+BEGIN_SRC python :var DATA=p-data print(str(DATA)) #+END_SRC #+RESULTS: [['a', 'b', 'c', 'd', 'e'], [1, 2, 3, 4, 5], [6, 7, 8, 9, 0]] Basic variables are also somewhat operational. #+BEGIN_SRC python :var DATA=5 print(str(DATA)) #+END_SRC #+RESULTS: 5 ** Powershell #+BEGIN_SRC powershell :var DATA=p-data $DATA | % {"$_"} #+END_SRC #+RESULTS: a b c d e 1 2 3 4 5 6 7 8 9 0 ** List Data Sources Within a File. Source blocks are also getting list as as data sources: Notice that the indented item is excluded this is normal org behaviour with lists. #+NAME: l-data - b - a - a - c #+BEGIN_SRC python :var DATA=l-data print(str(DATA)) #+END_SRC #+RESULTS: ['b', 'a', 'c'] #+BEGIN_SRC powershell :var DATA=l-data ,$DATA #+END_SRC #+RESULTS: b a c ** Numbered List Data Sources Within a File. Numbered lists are also now potential data sources: #+NAME: n-data 1. b 2. a 3. c 4. 4 #+BEGIN_SRC python :var DATA=n-data print(str(DATA)) #+END_SRC #+RESULTS: ['b', 'a', 'c'] #+BEGIN_SRC powershell :var DATA=n-data ,$DATA #+END_SRC #+RESULTS: b a c ================================================ FILE: messages/1.2.10.org ================================================ * 1.2.10 Dateutil seems to have vanished on package control. This was causing some people to have problems installing. I have been forced (for now) to embed dateutil into orgextended so we can continue chugging along. My hope is that in doing this it will fix the ST3 issues we have been seeing. ================================================ FILE: messages/1.2.11.org ================================================ * 1.2.11 - Trying to get dateutil to operate well as a package inside OrgExtended. Had some problems with six.py's location. - I believe this will fix it. ================================================ FILE: messages/1.2.12.org ================================================ * 1.2.12 - Thankfully the problem with dateutil has been discovered by wbond. we should now be able to install again once dateutil clears. I have removed the dependency on an internal dateutil. ================================================ FILE: messages/1.2.13.org ================================================ * 1.2.13 - Fixed a fairly major regression with capture templates. 1. Capture snippets now live in Packages\User\orgsnippets folder (for consistency with other extension types) 2. A bug was fixed which would fail to find a snippet in some cases. ================================================ FILE: messages/1.2.14.org ================================================ * 1.2.14 ** Color Scheme Generator - FIXED: Improved color scheme generator. It did not handle comments so Solarized Dark as throwing. [[https://github.com/ihdavids/orgextended/issues/29][Issue]] ** Max Header Depth In Syntax Coloring - This has been extended to 10 as per request from antidistinctiminty (Was 7 previously) ================================================ FILE: messages/1.2.15.org ================================================ * 1.2.15 :PROPERTIES: :header-args: :noweb-ref includeme :END: 1.2.15 introduces the start of noweb like macro support to our babel offering. The contents of source blocks can be dynamically included from remote blocks. (Much like a macro the code is pasted into the block) References can be done by parameters or by name. The noweb-ref parameter allows you to define the target of a reference much like a name would. Since the source of a noweb reference can be named in a parameter this means that property parameters can apply to a set of source blocks that each has a part of the full snippet. In this case snippets will be pasted in the order they appear in your file. #+BEGIN_SRC python print("Hello World") #+END_SRC #+BEGIN_SRC python print("And again!") #+END_SRC #+BEGIN_SRC python print("Even More!") #+END_SRC #+BEGIN_SRC python :noweb yes <> <> <> #+END_SRC #+RESULTS: : Hello World : And again! : Even More! : By-Name : By-Results: 5 * By-Name Source Block In the example above we are referencing the blocks by a name in the parameter field. Here we are referencing the source block by the name of the block. #+NAME: by-name #+BEGIN_SRC python print("By-Name") #+END_SRC If you use () in your reference you are requesting the results of the block be pasted rather than the block itself. This can be useful but can easily get complicated if abused. So use with restraint. #+NAME: by-results #+BEGIN_SRC python :var x=5 :results raw print("print('By-Results: " + str(x) + "')") #+END_SRC ================================================ FILE: messages/1.2.16.org ================================================ * 1.2.16 ** Source Blocks - Improved noweb error reporting and handling - Added "builtinSourceBlockHandlers" setting allowing users to override one of the built in source handlers with their own. ** Cmd Source Block Support Batch files do not support arrays so we play some games. VAR_width and VAR_height are defined to help with iteration and array like variables are defined a value at a time VARNAME[r#,c#] #+NAME: table-source | a | b | c | d | e | | 1 | 2 | 3 | 4 | 6 | #+BEGIN_SRC cmd :var x=5 :var DATA=table-source setLocal enableDelayedExpansion echo Hello World %x% FOR /L %%r IN (1,1,%DATA_height%) DO ( FOR /L %%c IN (1,1,%DATA_width%) DO ( echo|set /p dummy=!DATA[%%r,%%c]! ) echo . ) #+END_SRC #+RESULTS: : Hello World 5 : 'a''b''c''d''e'. : 12346. *** Cmd Return Values Value execution is kind of funny. Batch files can reach out and touch a parent parameter var. The return value is the first. Set it like so: #+BEGIN_SRC cmd :results value echo "hi" set "%~1=5" #+END_SRC #+RESULTS: : 5 ================================================ FILE: messages/1.2.17.org ================================================ * 1.2.17 More source block handlers! ** Alias Support in Source Blocks bat = cmd js = javascript ** SH source blocks kind on windows with WSL (assuming you have WSL setup) This is not yet tested on any other platform! #+NAME: in-table | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | #+BEGIN_SRC bash :var DATA=in-table echo "$DATA" #+END_SRC #+RESULTS: : a b c d e : 1 2 3 4 5 Not yet sure if value types work like this in emacs. I may need to adjust this. #+BEGIN_SRC sh :results value return 5 #+END_SRC #+RESULTS: : 5 ** Javascript source blocks require node.js Set nodejsPath in your settings file. #+BEGIN_SRC javascript :var x=5 console.log('Hello world ' + x); #+END_SRC #+RESULTS: : Hello world 5 #+BEGIN_SRC js :var DATA=in-table :results table console.log(DATA); #+END_SRC #+RESULTS: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | ================================================ FILE: messages/1.2.18.org ================================================ * 1.2.18 ** Syntax Highlighting Beancount is now supported for syntax highlighting in source blocks ** Html Exporter - Fixed issue with exporting unordered lists. - Org Export Subtree as Html now handles HTML_STYLE properly - Org Export Subtree as Html will export _subtree.html rather than as a temp file. - "htmlExportPartialCheckboxChecked": False - Will export partial checkboxes as unchecked vs checked. ================================================ FILE: messages/1.2.19.org ================================================ * 1.2.19 ** Html Exporter - Exporter now exports as utf-8 to avoid problems with unicode characters. - Fixed a type in the postamble handling - The exporter can handle "* NOTE :" malformed headings and not crash. - The collapse system had problems computing the correct max-height on startup and nodes would not fold properly. - Added plain style to htmlstyles ================================================ FILE: messages/1.2.2.org ================================================ * 1.2.2 - Improving Babel Input ** Worklog - "Org Show Worklog" will generate our worklog to a new buffer ** Babel PList Params Quotes work for variables in plists #+BEGIN_SRC python :var x="hello world" print(x) #+END_SRC #+RESULTS: hello world ** Property Parameters All of the following are now possible sources of variables In a parameter block, including the local fence variable This required fixing the properties parser to understand multiple semi colons in a variable list. :PROPERTIES: :header-args: :var g=global :header-args:python: :var x=5 :var: v=10 :END: #+PROPERTY: header-args: :var y=11 #+PROPERTY: header-args:python: :var z=12 #+BEGIN_SRC python :var p=42 print(v) print(x) print(y) print(z) print(p) print(g) #+END_SRC #+RESULTS: 10 5 11 12 42 global ** Output As Table I have started working on output handling. Right now things are pretty manual. Things that work: :results table - This will try to format your output as a table :results verbatim - This will output things in verbatim format :file - The presence of a file parameter will cause the system to output a link to the file. This does not work for script output yet only for ditaa, plantuml and graphviz modules that naturally want to output to a file. Things that do not work: :file - for script blocks, that is comming :results - auto detection of tables :results - value a bunch of other stuff... #+NAME: in-table | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | #+BEGIN_SRC powershell :var DATA=in-table $DATA | %{"$_"} #+END_SRC #+RESULTS: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | #+BEGIN_SRC python :var DATA=in-table :results table print(str(DATA)) #+END_SRC #+RESULTS: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | #+BEGIN_SRC python :results verbatim print("Hello World This Is Tablular?") #+END_SRC #+RESULTS: : Hello World This Is Tablular? #+BEGIN_SRC plantuml :file out.png a -> b b -> c #+END_SRC #+RESULTS: [[file:out.png]] ================================================ FILE: messages/1.2.20.org ================================================ * 1.2.20 ** Html Exporter Continuing the Babel adventure we add support for :exports [code,results,both,none] NOTE: this means that the default parameters for babel header args are now more important Before we would default to exporting both code and results, now, due to the defaults set in our settings we only export code. This is in complaince with org mode defaults. If you would like to change that add the key to your settings file and set the defaults as you need: #+BEGIN_SRC python :exports both print("hi") #+END_SRC #+RESULTS: : hi #+BEGIN_EXAMPLE "orgBabelDefaultHeaderArgs": ":session none :results replace :exports code :cache no :noweb no", #+END_EXAMPLE *** Skip Source Some source formats it is handy to always skip the source and only include results. We have added a list of formats where this overrides the defaults (listed above) for convenience: #+BEGIN_EXAMPLE "htmlDefaultSkipSrc": ["plantuml","graphviz","ditaa","gnuplot"], #+END_EXAMPLE Remove this list if you would like to always have explicit control with the exports keyword. *** Source Block Execution on Export This is now turned on by default. If you would like to disable it: #+BEGIN_EXAMPLE "htmlExecuteSourceOnExport": false, #+END_EXAMPLE ================================================ FILE: messages/1.2.21.org ================================================ * 1.2.21 ** Html Exporter - Exporting source blocks that do not have handlers was generating an error. ** Early Preview of Latex Exporter - An early perview of a new latex exporter. - Many of the basic org data types work already. - Thanks to FleurDePassion for his time in helping work on this. ** Links To Files in OrgDirs New command: quick panel based insertion of links to files #+BEGIN_EXAMPLE "Org Link To File" #+END_EXAMPLE This was requested by: [[https://github.com/ihdavids/orgextended/issues/30][Autocompletion of Links]] In addition to the quick insert autocompletion during link insertion also tries to help with mapping to local files if possible. You can turn off autocomplete in the settings file if you are finding it annoying. ** Home Directory orgDirs Thanks to waynezhang for implementing this. We now support ~ in orgDirs in your settings file. ================================================ FILE: messages/1.2.22.org ================================================ * 1.2.22 ** Table Bug Fixing a remote indexing bug. If the local table does not have enough columns to match your remote index the remote target would get capped to the local width: Note the a in the second table, it should have been a b, this is because we are trying to access column 2 remotely but our local table only has 1 column. The temporary fix was to add another column. #+NAME: hiya | a | b | c | | 1 | 2 | | | a | #+TBLFM:@1$1=remote('hiya',@1$2) After the fix this now reads b ** Link Insertion - Thanks to waynezhang link insertion using "Link To File" or the autocomplete method now inserts relative paths relative to the current file. - The title of the link reflects the #+TITLE: field in the file is present. - "linkFindUseRoamTags": False will turn off visualization of ROAM_TAGS in quick panel if desired. (NOTE they do not appear in the search unless you have them in the file) ** Capture - Somehow the snippets folder was not renamed orgsnippets when I normalized my extension folder names. This means that while my local snippets were working none of the default ones that come with the package were working. Hopefully this has been fixed. ** Day Page - I am moving the day page feature forward a little bit. - Do not forget to set the "dayPagePath" setting if using this feature - "Org Day Page Create" is really going to be more of a goto today. It will create the day page or open it. - Create also now uses a snippet that is keyed off of: This should be the filename of a snippet file that lives in your orgsnippets folder. (without the .sublime-snippet extension) #+BEGIN_EXAMPLE "dayPageSnippet": "dayPageSnippet", #+END_EXAMPLE This snippet will get expanded into the file on creation as a means of authoring a new day. Symbols exist to help in your snippet authoring the list of symbols is similar to the capture templates. Two new symbols exist for use in your snippet: ORG_FILENAME is the filename without the org extension and ORG_AUTHOR is your username. - Day Page Filenames are now configurable They use the python strftime syntax for defining the filename: Note changing this with pre-existing content will likely have consequences when searching old files. #+BEGIN_EXAMPLE "dayPageNameFormat": "%a_%Y_%m_%d", #+END_EXAMPLE - New Commands: Lets you cycle through your day pages in sequence. #+BEGIN_EXAMPLE Org Day Page Next Org Day Page Previous #+END_EXAMPLE ** Latex Exporter - NAME now exports a label like it should - LATEX_HEADER tag should now add to the latex preamble - LATEX_CLASS_OPTIONS now adds an option next to the documentclass - surrounding an expression with dollar signs will export properly in latex - Slightly improved spacing in latex documents - Fixed a bug with the segment parser and secments right at the start of a line - Better stripping of html attributes - Added first try at SetupFile tag. ================================================ FILE: messages/1.2.23.org ================================================ * 1.2.23 ** Day Page - Bugfix - Create was subject to a timing problem that would stop it from expanding the snippet. This has been fixed. ** Latex Preview - We continue to move the latex exporter forward with some basic image support - Results have the results header stripped properly now A first stab at :exports keyword (not really well tested yet) - More keywords that should be removed are stripped out. ================================================ FILE: messages/1.2.24.org ================================================ * 1.2.24 ** Day Page - Fixed small exception with create - Fixed inserting templates when moving back and forth to current day page a disturbing leftover from a previous debugging session. ** Latex - Improved output parsing in list contents - Images have some ATTRS_LATEX support - table of contenst is included ================================================ FILE: messages/1.2.25.org ================================================ * 1.2.25 ** Latex Preview - more #+OPTIONS: controls date:nil toc:nil toc:2 author:nil title:nil - Table export supports some ATTR_LATEX options: :environment bmatrix :mode math ** Hide Images - This was removing indent for some reason which was disconcerting. ================================================ FILE: messages/1.2.26.org ================================================ * 1.2.26 ** Bugfix: Do What I Mean Insert Ctrl + Enter is a DWIM insert Sadly I broke it when I renamed the orgsnippets folder ================================================ FILE: messages/1.2.27.org ================================================ * 1.2.27 ** LaTeX Exporter - LATEX: and @@ @@ support in the latex exporter. - Something went wrong with 1.2.26, People are downloading 1.1.13 instead... I don't know why. Pushing another version in the hopes this fixes it. ================================================ FILE: messages/1.2.28.org ================================================ * 1.2.28 ** Backlinks Experimentation Org Roam is a very powerful package. I am nowhere near supporting the power pretty views and flexibility of that package. That said, I am experimenting with the backlinks feature. This release has an experimental version of the org-roam backlinks view. These are links that are referencing your current document in your orgDirs not links that this document references. - Org Jump To Backlinks - is a new quick menu command that shows the links referencing your current file and lets you jump to them. - Org Show Backlinks - is a new command that pops up a panel with the backlinks to the file you are currently looking at. This is an experimental feature. It automatically tries to keep the backlinks display visible but this is somewhat challenging with the existing sublime API. You can turn this off if it is causing you problems: Turn off the attempts to update the backlinks display using the following option in your settings file: #+BEGIN_EXAMPLE "backlinksUpdate": false, #+END_EXAMPLE ** Mermaid Source Blocks - Syntax is supported if you install the mermaid package - Can be executed to generate diagrams if setup. Setting it up is a bit of a pain: 1. npm install @mermaid-js/mermaid-cli 2. NOTE it gets installed into a node_modules folder. This is REQUIRED! 3. Set the mermaid variable in your settings to point to mmdc in the node_modules\.bin\mmdc path 4. Ensure node is in your path Then execute this block: #+BEGIN_SRC mermaid :file ganttdemo.png gantt title A Gantt Diagram dateFormat YYYY-MM-DD section Section A task :a1, 2014-01-01, 30d Another task :after a1 , 20d section Another Task in sec :2014-01-12 , 12d another task : 24d #+END_SRC #+RESULTS: [[file:ganttdemo.png]] ================================================ FILE: messages/1.2.29.org ================================================ * 1.2.29 ** Links - New command "Org Search Links" searches links across all org files. ** Backlinks - Fixed a bug where folds in the backlinks buffer would get confused. ** Awk - Syntax highlighting for awk source blocks: #+BEGIN_SRC awk BEGIN {OFS="|"}; { sum+= $2}; END { print "Sum", sum} #+END_SRC ================================================ FILE: messages/1.2.3.org ================================================ * 1.2.3 Core Idea - Better output support and results controls ** Column View - Fixed a small regression introduced in plists in some of the earlier babel work. This was impacting columnview ** Test File To help new users we now have an: "Org Show Testfile" command that will quickly create a testfile for a user to play with. ** Babel Preview Output Handlers List Handler #+BEGIN_SRC python :results list print(str([1,2,3,4,5])) #+END_SRC #+RESULTS: - 1 - 2 - 3 - 4 - 5 File Handler With a List #+BEGIN_SRC python :results list :file out.py print(str([1,2,3,4,5])) #+END_SRC #+RESULTS: [[file:out.py]] ** Babel Preview Output Formatting These wrap the output in a formatting block of some sort. *** Drawer Formatter will wrap output in a drawer #+BEGIN_SRC python :results drawer verbatim:var x=5 print("Hello World") print(x) #+END_SRC #+RESULTS: :results: Hello World 5 :end: *** Code Formatter will generate a code block with the output: #+BEGIN_SRC python :results code print(str([1,2,3,4,5])) #+END_SRC #+RESULTS: #+begin_src python [1, 2, 3, 4, 5] #+end_src *** Org Mode Formatter will generate a code block specific to org #+BEGIN_SRC python :results org print("#+COMMENT: org data here") #+END_SRC #+RESULTS: #+begin_src org #+COMMENT: org data here #+end_src *** Append Prepend Silent Replace #+BEGIN_SRC python :results org append print("#+COMMENT: org data here") #+END_SRC #+RESULTS: #+begin_src org #+COMMENT: org data here #+end_src #+begin_src org #+COMMENT: org data here #+end_src #+begin_src org #+COMMENT: org data here #+end_src #+BEGIN_SRC python :results org prepend print("#+COMMENT: org data here") #+END_SRC #+RESULTS: #+begin_src org #+COMMENT: org data here #+end_src #+begin_src org #+COMMENT: org data here #+end_src #+begin_src org #+COMMENT: org data here #+end_src #+BEGIN_SRC python :results org silent print("#+COMMENT: org data here") #+END_SRC #+RESULTS: ================================================ FILE: messages/1.2.30.org ================================================ * 1.2.30 ** Auto Indentation - Not yet perfect but some simple auto indentation rules - begin blocks are automatically indended. - Headings get indentation inserted when you hit enter off them ** BEGIN_NOTES - notes block added to syntax highlighter - =20210501 <=20210531 - hasclose and other attributes were not handled properly as filter keywords, this has been fixed. ** Reveal Exporter - Tables are now actually supported ** Exporting - Tables had a bug if tabs were present in front of the table. ** Editing - New override setting: logDone - forces CLOSED entries to be inserted even if logdone is not in your #+STARTUP: tags or global "startup": "..." settings. #+BEGIN_EXAMPLE "logDone": true, #+END_EXAMPLE ** Tables Found a bug with complete relative syntax. They were always evaluating to 1,1 in the table. This has been fixed. #+BEGIN_EXAMPLE @-1$+1 #+END_EXAMPLE Known issue: ------------ Complex expansions are not working: @int($-1)$1 This would look up the row from the neighboring cell There is a workaround for now till I can improve the parser getcell(int($-1), 1, 1, 0) | | | not relative | | column 1 | relative offset grab value 1 cell to the left, ensure it is an int *** New Table Commands The following will pull the active formula for the current cell into the current cell. Facilitating editing. #+BEGIN_EXAMPLE Org Edit Table Formula #+END_EXAMPLE The following will clear the current cell #+BEGIN_EXAMPLE Org Clear Table Cell #+END_EXAMPLE The following will run a temporary formula on the cells on and below the cursor which can be handy when fixing up a table. #+BEGIN_EXAMPLE Org Table Exec Below #+END_EXAMPLE *** Babel Preview - Improved results block discovery previously results might confuse a source block as being part of the results. ================================================ FILE: messages/1.2.33.org ================================================ * 1.2.33 ** Editing - Tag insertion could not insert tags on headings with colons this has now been fixed. [[https://github.com/ihdavids/orgextended/issues/38][Issue]] *** Indenting An attempt to improve heading indentation with exiting content. We will see how this new attempt plays out. ** Syntax Highlighting - Internal syntaxes are now hidden. - Syntaxes are now marked as version 2 which may improve perf. ** Org Beancount Experiment This is a bit of a departure from org's primary purpose. I however use beancount and beancount is designed to work inside other markup languages like markdown and... orgmode! Due to how packages and syntaxes work I have not found a good way to create an amalgamated syntax without doing inside the orgmode package. So... here we are. By default we highlight .orgbeancount files. This also adds a snippet for inserting a transaction with some additional metadata. My hope is to eventually facilitate babel and beancount. ** Clocking - I was logging clock entries into the PROPERTIES drawer. this is a bit non standard. - this is now configurable and by default we are now logging into a LOGBOOK drawer which is more orgmode standard. Use the following to preserve the old behaviour: #+BEGIN_EXAMPLE "clockInPropertyBlock": true, #+END_EXAMPLE ================================================ FILE: messages/1.2.34.org ================================================ * 1.2.34 ** Active Table Cell Highlight Show cursor for current cell. Use the following option to turn this off if it is causing you problems. #+BEGIN_EXAMPLE "tableShowCursor": false, #+END_EXAMPLE ** Babel Preview - Perl is now supported. Like the other languages you have to tell the language handler where your perl interpreter can be found with: #+BEGIN_QUOTE "perlPath": " r f for refile to file. - r r for refile to file and headline ** Capture - Added new capture type: 'plain' we now support 'entry' and 'plain' Eventually I will add all the capture types but we are a bit off from that. - Added new capture type: 'item' This will add at the end of the first list found in the node - Added new capture item: 'checkitem' This will add at the end of the first checklist found in the node - Added really early attempt at 'table-line'. Not sure if this is sufficient All of the types above only work with the snippet type - Added first stab at 'file+olp+datetree' I only have the full day mode not month or week yet. The olp part will take a heading and will add something like: under that heading * 2021 ** 2021-11 November *** 2021-11-27 Saturday The target should look something like: ['file+olp+datetree',"{myfile}","Heading a","Heading b","Heading c"] We have 3 non standard properties implemented for datetree: #+BEGIN_QUOTE These are python date strings and allow you to control the header format of your datetree "year-format": "%Y", - The root of your datetree * 2021 "month-format": "%Y-%m %B", - The month section ** 2021-11 November "day-format": "%Y-%m-%d %A", - The day section *** 2021-11-27 Saturday #+END_QUOTE ================================================ FILE: messages/1.2.41.org ================================================ * 1.2.41 Thank you for the contribution Sinamore: - Some small agenda fixes from Sinamore for the agena when day of week starts on Monday it was showing the wrong week. - Datepicker had problems with date wrap around. - A bug in mouse hovering with hasattr ================================================ FILE: messages/1.2.42.org ================================================ * 1.2.42 ** Template formatter - Small enhancement to template formatting in settings file for capture templates. - Stolen from superformatter a very simple python template expansion tool. - {variable.:call} will call a function on the variable contents (such as upper()) - {variable:repeat:string to repeat for {{item}} } assuming variable is a list will output the string expanded per item in the list - {variable:if:string to output} Will output string to output if variable evaluates to true otherwise "" ** DatePicker - Fixed moving outside of the 3 month range. Highlighting today would fail and date would fail to update properly. ** DayPage New option: "dayPageCopyTasksForToday": True This will copy all todos that would target today to the current daypage. This is experimental and will likely change in the future. Iterating with olBC to get this feature to his liking. The option can scan files in memory but not in your org dir if you turn on: "dayPageIncludeFilesOutsideOrgDir": true ================================================ FILE: messages/1.2.43.org ================================================ * 1.2.43 ** Agenda Flexible Project Definition New options for defining what a project is. #+BEGIN_SRC js // nested_todo TODO with sub TODO's. // tag Heading with a :PROJECT: tag // property Heading with a :PROJECT: True property "agendaProjectIs": "nested_todo", #+END_SRC nested_todo is a todo under a todo: * TODO My Project ** TODO Task tag defines a project as a heading with a project tag: * My Project :PROJECT: ** TODO Task property defines a project as a heading with a PROJECT property: * My Project :PROPERTIES: :PROJECT: :END: ** TODO Task ** Agenda Projects 2 new agenda views: - Not Blocked Projects - Shows projects that are not in the blocked state (have a NEXT task) - Projects - Shows all projects ================================================ FILE: messages/1.2.44.org ================================================ * 1.2.44 ** FIXED Capture Supports Unicode - [[https://github.com/ihdavids/orgextended/issues/57][Fix for Capture fails silently with unicode error]] Captures that contained unicode characters would fail. This was due to the fact that the capture mechanism was not saving files with the default text encoding. There is a new option that allows you to control the format of the destination capture file: #+BEGIN_SRC js // What file format should we write out as. This should be a python encoding value // CAN BE: // - utf-8 // - utf-16 // - utf-32 // SEE: https://docs.python.org/3.3/library/codecs.html#standard-encodings "captureWriteFormat": "utf-8", #+END_SRC The default is now utf-8 ** FIXED Autocalculated Rows Fix - [[https://github.com/ihdavids/orgextended/issues/59][in tables, auto calculating rows sometimes break a column formula]] Thanks to JosefTaylor reporting that autocalculating tables sometimes get confused with table formulas. Some improvements have been made to fix this going forward. The problem was that as you edit the column you can cross over into the next cell's space while editing. This was confusing the automatic targetting for the formula since the destination cell was computed before the table was reformatted. I have added a table align before recomputing the cell. It's a little slower when tabbing around but should result in correct behaviour. | | am | I | what | | |---+----+----+---------+---| | # | 2 | 20 | 62.832 | | | # | 3 | 13 | 40.841 | | | # | 5 | 41 | 128.805 | | #+TBLFM::$4=$3*pi;N%.3f ** FEATURE Rounding Out Tag Support Added new option to control the tag column when inserting tags: #+BEGIN_SRC js // Where should tags start in a headline? // Tags will get inserted at this column "tagColumn" : 80, #+END_SRC 3 new commands (sadly t is used for timestamp so I am using m for mark...) - Org Remove Tag :: (NeoVintageous: r m) Prompt to remove a tag - Org Remove All Tags :: (NeoVintageous: r a m) Removes all tags from current headline - Org Fix Tags :: (NeoVintageous: f m) Will re-indent all tags in the file to the tag column specified ================================================ FILE: messages/1.2.45.org ================================================ * 1.2.45 ** FIXED Internal Target Highlighting - [[https://github.com/ihdavids/orgextended/issues/62][Internal Target Problem]] Thanks to flintforge for reporting that adding an unterminated << to a line would cause the rest of the document to become an internal link in the org syntax setup as it is. This is now fixed: << Internal Link >> - This should be a valid link << This is not a valid link | This | Table | Should | Be | Okay | |------+-------+--------+----+------| | 1 | 2 | 3 | 4 | 5 | ================================================ FILE: messages/1.2.46.org ================================================ * 1.2.46 ** FIXED Duplicate filenames appearing in refile listing When refiling to EOF sometimes the list would have duplicate files. This should now be fixed. ================================================ FILE: messages/1.2.47.org ================================================ * 1.2.47 ** FIXED Sometimes tasks were misidentified as being a task. - Tasks are defined as being a todo that has a parent and that parent is a project identifier. - NOTE: When I eventually support using the orgs server as an alternative to the orgdb the query language will be cleaner. Right now I am not a fan of how I chose to build these querries. ** New default state keywords added New open states: - FLAG - Personal state meaning this is waiting on processing. - CLEANUP - Personal state meaning this todo is in the cleanup phase and needs further cleanup effort. New closed states: - FIXED - same as DONE ** FIXED Agenda color scheme was not highlighting filenames with underscores ================================================ FILE: messages/1.2.48.org ================================================ * 1.2.48 ** Properties :PROPERTIES: :Created: [2022-07-20 Wed 08:49] :END: - I found myself adding a Created property to a lot of new notes. (I like timestamps on when a note has been created) So I have added a new command Org Insert Created Property that will auto insert a :Created: [TIMESTAMP] to a heading, saves me a few keystrokes. (See above for the format) ** FIXED FILETAGS Filestags with colons around them were not having the colon stripped. This was a bug introduced a while back and I did not notice. This is no longer the case: #+BEGIN_SRC org #+FILETAGS: :A:B:C: #+END_SRC Will now correctly tag all nodes with A B and C tags ** FIXED Checkbox summaries Summaries that were followed by a list of checkboxes in a second heading could miscalculate the summary including checkboxes from the next heading #+BEGIN_SRC org * A [1/2] <-- This would be miscalculated as [1/3] vs [1/2] - [ ] B - [x] C ** D - [ ] E While still facilitating nested summaries: * Heading [3/5] - [x] A - [x] B - [ ] C - [-] D [1/3] - [ ] X - [x] Y - [ ] Z - [x] E #+END_SRC ** FIXED Clocking in and out was crashing Clocking in and out on a node was throwing exceptions due to the property drawer API attempting to operate on a root node missing some API. This should now be fixed. ** New Command Org Jump To Clock This will jump to an active clock if one is running. Currently not bound to anything. ** New Todo filters *** clockedtoday clockedtoday tests if the todo has a clock value and if either start or end spans today If you are using the clocking feature this makes it easier to get a quick list of things you have worked on today. #+BEGIN_SRC js "Todays Work": ["Todos : clockedtoday"], #+END_SRC *** clockfilter clockfilter is like durationfilter in that it takes a duration specifier #+BEGIN_SRC js "This Weeks Work": ["Todos : clockfilter +7d"], #+END_SRC *** showduration This will show the amount of time in hours and minutes that you spent on a todo, in the todo view #+BEGIN_SRC js "This Weeks Work": ["Todos : clockfilter +7d : showduration"], #+END_SRC *** hide filters 3 Additional formatting options for task list views: - hidefilename - hideheading - hidestatus #+BEGIN_SRC js "This Weeks Work": ["Todos : clockfilter +7d : showduration : hidefilename"], #+END_SRC These will hide the filename, todo heading and todo status fields as desired in the listing. *** showtotalduration This option will turn on a summary of the total duration at the end of task listing of tasks that were clocked. #+BEGIN_SRC js "This Weeks Work": ["Todos : clockfilter +7d : showduration : showtotalduration"], #+END_SRC *** byproject This task pane option will group tasks by project adding a == [Project Name] == header to each project for clarity #+BEGIN_SRC js "This Weeks Work": ["Todos : clockfilter +7d : showduration : showtotalduration : byproject"], #+END_SRC ** New Agenda Views Clocked view shows anything with a clock value including non todos For example this is different than the above as the above will show anything in an open state since it uses the Todo view while the following will actually show all work done on any node. Obviously this comes with a slight performance cost as it has to scan non todo nodes, but it makes the clocking feature more useful. #+BEGIN_SRC js "This Weeks Work": ["Clocked : clockfilter +7d : showduration"], #+END_SRC ** Tweak to Composite Todo List Titles If the composite list only contains a single view, the name of the view is assigned the name of the composite view + [view name] This allows a custom view with "This Weeks Work" as the name to appear as: #+BEGIN_EXAMPLE This Weeks Work [Clocked] #+END_EXAMPLE Increasing clarity as to the type of list you are viewing ================================================ FILE: messages/1.2.49.org ================================================ * 1.2.49 ** FIXED Clocking out - When clocking in to a different file while a previous clock was running the clock value was getting written to the wrong file due to using the wrong view! - We now open the other file, add the clock out value, save it and switch back to the correct buffer ** REMINDER org_agenda_custom_view Recently I was asked about todo views. I thought I would take a moment and highlight what is already there. The org_agenda_choose_custom_view command can be handy for scanning through your todo lists, but if you are like me, it can get in the way. You can bind your own keybindings and select a particular view quickly like so: Here I am using a neovintageous style keybinding to pop up my "This Weeks Work" list when I press o l w in normal mode. (Think VIM) You can do much the same for whatever your preferences might be. #+BEGIN_SRC js { "keys": [" ","o", "l", "w"] , "command": "org_agenda_custom_view" , "args": {"toShow": "This Weeks Work"} , "context": [{"key": "vi_command_mode_aware"}] }, #+END_SRC This view is created using the view syntax like so: #+BEGIN_SRC js "AgendaCustomViews": { # My agenda is comprised of several standard views "Default": ["Calendar", "Week", "Day", "Blocked Projects", "Loose Tasks"], # Show any todos tagged as being active "Active": ["Todos : tagfilter +Active"], # Show my todos tagged as being part of my backlog. "Backlog": ["Todos : tagfilter +Backlog"], # Show anything, not just todos that have been clocked within the last 7 days. Also show their duration # and group them in projects if they are associated with a project. "This Weeks Work": ["Clocked : clockfilter +7d : showduration : showtotalduration : byproject"], }, #+END_SRC ** Agenda Task Lists - Todo lists now have a dynamic filter option. This option will provide an input box that allows you to dynamically filter the text in the todo list. - The keybinding is REALLY rough right now. - In neovintageous mode "f","f" will bring back up the input box allowing for more filtering goodness. - In normal mode alt+o f f will bring back up the input box allowing for more filtering goodness. - Escape will clear the filter - Enter will make the filter permanent allowing you to scroll through todos again. You can force this input panel to have focus and be visible when the todo list pops up with the following option: If sublime will ever support more rich panels I would love to add dynamic filtering by tag, priority and other things in there. For now I will have to add then piecemeal. #+BEGIN_SRC js "agendaTodoFilterByDefault": true, #+END_SRC *** New todo view columns Not sure I like this yet, still somewhat experimental. - showdate - will show most relevant date information (active, scheduled, dealine, closed timestamp) - showtime - will show the time info from the most relevant date information #+BEGIN_SRC js "This Weeks Work": ["Clocked : clockfilter +7d : showduration : showtotalduration : byproject : showdate : showtime"], #+END_SRC *** Better todo sorting Somewhat experimental at the moment... - Now sorts by date by default, will be looking to make this configurable going forward as well. - Sort order can be flipped globally if preferred using: #+BEGIN_SRC js "agendaTodoSortAscending": false, #+END_SRC Or locally in a list using: - sortascend - sortdescend ================================================ FILE: messages/1.2.5.org ================================================ * 1.2.5 Core Idea: Better Chaining Support ** Agenda - WeekView - Bugfix: The weekview could show things last month but in the current week erroneously. ** PlantUML - Fixed a regression in the parameter handling for plantuml. #+BEGIN_SRC plantuml :file out.png a -> b b -> c #+END_SRC #+RESULTS: [[file:out.png]] ** Handling Drawers in Chained Sources #+NAME: tbl-source | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | This source block uses the output from the table above #+NAME: python-src #+BEGIN_SRC python :results drawer table :var DATA=tbl-source print(DATA) #+END_SRC #+RESULTS: :results: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | :end: This source block uses the output from python-src as an input #+BEGIN_SRC python :results table :var DATA=python-src print(DATA) #+END_SRC #+RESULTS: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | ** Handling Lists in Chained Sources Here we have a list that acts as a source for some python that acts as a source for more python. #+NAME: lst-source 1. a 2. b 3. c #+NAME: python-lstsrc #+BEGIN_SRC python :results drawer list :var DATA=lst-source print(DATA) #+END_SRC #+RESULTS: :results: - a - b - c :end: #+BEGIN_SRC python :results list :var DATA=python-lstsrc print(DATA) #+END_SRC #+RESULTS: - a - b - c ** Numeric and Text Values Here the powershell scripts results are piped into the python script. #+NAME: ps-src #+BEGIN_SRC powershell :results value return 5 #+END_SRC #+RESULTS: : 5 #+BEGIN_SRC python :results drawer :var DATA=ps-src print(DATA) #+END_SRC #+RESULTS: :results: 5 :end: ** Silent Exec #+NAME: ps-src2 #+BEGIN_SRC powershell :results output list silent :var DATA=lst-source $DATA #+END_SRC #+BEGIN_SRC python :results drawer list :var DATA=ps-src2 print(DATA) #+END_SRC #+RESULTS: :results: - a - b - c :end: #+NAME: python-src2 #+BEGIN_SRC python :results table silent :var DATA=tbl-source print(DATA) #+END_SRC #+BEGIN_SRC python :results table :var DATA=python-src2 print(DATA) #+END_SRC #+RESULTS: | a | b | c | d | e | | 1 | 2 | 3 | 4 | 5 | ** Call Begining support for the babel call syntax. Here we define a function that can be called elsewhere in the document with different parameters. #+NAME: varfunction #+BEGIN_SRC python :var DATA=6 print(DATA) #+END_SRC #+RESULTS: : 6 #+call: varfunction(DATA=7) #+RESULTS: : 7 ** First Draft Source Block Execute in Tables This is a slight breakaway from orgmode as we do not support lisp and in orgmode this would be done with (org-sbe 'name' (key x) (key y)) This is not a syntax I can easily support properly without implementing a full lisp parser inside sublime and... I don't like that idea. So, I am using the more python friendly function call as seen below. Note this is running the varfunction above, taking the results and placing them in the table below in cell 2,1. | a | b | | 12345 | 6 | #+TBLFM:@2$1=sbe('varfunction',DATA=12345)::@2$2=sbe('varfunction') ================================================ FILE: messages/1.2.50.org ================================================ * 1.2.50 ** Agenda *** FIXED Task Lists - Some print cleanup from the sublime output window. *** FIXED Agenda View - Searchable task lists broke the agenda render. Very frustrating. *** New showeffort todo agenda option #+BEGIN_SRC js "Active": ["Todos: tagfilter +Active :showeffort"], #+END_SRC This will add the :EFFORT: property if present on a todo to the todo list view in a column *** New showid todo agenda option Will show the ID or CUSTOM_ID property of a task in the todo list #+BEGIN_SRC js "Active": ["Todos: tagfilter +Active :showid"], #+END_SRC *** New showafter todo agenda option Will show the AFTER property of a task in the todo list #+BEGIN_SRC js "Active": ["Todos: tagfilter +Active :showafter"], #+END_SRC *** New showassigned todo agenda option Will show the ASSIGNED property of a task in the todo list #+BEGIN_SRC js "Active": ["Todos: tagfilter +Active :showassigned"], #+END_SRC *** Change in TODO Tables - As I have added more columns it becomes more confusing deciphering what you are looking at. I have added headings to the table. - I may simply convert this to an org table, we will see. ** Todo Views - Org Agenda * commands now work on todo views as well as the agenda - This allows for changing priority et al directly form todo lists. - 3 new commands for todo view editing: - Add tag from view - Add property EFFORT - Add property ASSIGNED These get us closer to a pseudo column view mode using a todo table. ** Tables - Fixed some tabbing problems (mostly highlight related in some generated tables) - Problem was both a potential exception AND a table living at global scope the keybinding was going to the global scope tab binding rather than the table keybinding which was causing improper behaviour. *** Random Insertion From Remote Table Sometimes I would like to make a random selection from a remote table. There is a new command to insert at point a random selection from a remote table (by ID) NOTE the properties block with ID this lets you reference this table and make a random selection from the table. #+BEGIN_SRC org * Common Items :PROPERTIES: :ID: common-items :END: | Item Name | Type | Attuned | Source | Link | |----------------------------------+---------------+---------+--------+---------------------------------------------------------------------------| | Armblade | Weapon | Attuned | E:RLW | http://dnd5e.wikidot.com//wondrous-items:armblade | | Armor of Gleaming | Armor | - | XGE | http://dnd5e.wikidot.com//wondrous-items:armor-of-gleaming | | Bead of Nourishment | Wondrous Item | - | XGE | http://dnd5e.wikidot.com//wondrous-items:bead-of-nourishment | | Bead of Refreshment | Wondrous Item | - | XGE | http://dnd5e.wikidot.com//wondrous-items:bead-of-refreshment | | Boots of False Tracks | Wondrous Item | - | XGE | http://dnd5e.wikidot.com//wondrous-items:boots-of-false-tracks | | Bottle of Boundless Coffee | Wondrous Item | - | SCC | http://dnd5e.wikidot.com//wondrous-items:bottle-of-boundless-coffee | | Breathing Bubble | Wondrous Item | - | EGW | http://dnd5e.wikidot.com//wondrous-items:breathing-bubble | #+END_SRC ** Timechart Initial Experiment - New VERY experimental feature. Much like an agenda we have the timechart. This is a table that can be inserted anywhere from todo's. Much like a clocktable dynamic block / report. However this maps effort vs spent, who has been assigned to a task (if desired) and done tasks, more than your standard clock report. - My thought is to make it possible to dump out one of these and eventually automatically output as several gantt chart options as well. - First version is outputting to mermaid. It is not fully ready for consumption but can be experimented with for those that are adventurous. ================================================ FILE: messages/1.2.51.org ================================================ * 1.2.51 ** FIXED Date only labels were confounding some TODO reports causing an assert. - This would manifest as a blank todo list when the todo had a date but no time, this has been fixed ** Timesheet / Timechart Still an experimental feature - Org Choose Timesheet command acts like Agenda Choose View and uses the same list. - Mermaid and an Html visualiztion experiment. ** Clocking New command Org Update Active Clock Command - updates the start time in the clock info file. ** Todo view rebinds: These allow editing of task state in a todo view which is handy for planning purposes { "keys": ["t"], "command": "org_agenda_change_todo", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["s"], "command": "org_agenda_change_todo", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["e"], "command": "org_agenda_insert_effort", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["i"], "command": "org_agenda_id" , "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["t"], "command": "org_agenda_insert_tag", "context": [{ "key": "eol_selector", "operand": "source.orgagenda"}] }, { "keys": ["a"], "command": "org_agenda_assign", *** New Agenda Todo List Type Has Status - Lists all todos regardless of status or presence in a project. Useful if you want to filter you tasks by tag or property instead *** Todo table adjustable column width the column statements now take format specifiers: >12.12 (right justify 12 characters min x 12 characters max) #+BEGIN_SRC js "Recent": ["Done : -5d : hasclose : showdate >12.12 : showtime : sortdescend : showid : showeffort : showafter : showassigned"], #+END_SRC ** Tables *** FIXED Executing all tables clears all highlights - Still need better highlight management but this improves things slightly when recomputing all tables *** FIXED Table Cache - At times the table cache was getting out of sync due to invalid dirty buffer checks. This could cause the highlighting of cells in a page with multiple tables to go wonky. I believe I have fixed this now but this is a complex issue to fully track down. *** New Sum Functions - vsumifeq(a,b,range) - will sum all cells in range where a == b - vsumifgt(a,b,range) - will sum all cells in range where a > b - vsumiflt(a,b,range) - will sum all cells in range where a < b - vsumifgteq(a,b,range) - will sum all cells in range where a >= b - vsumiflteq(a,b,range) - will sum all cells in range where a <= b In the blow example I am computing the damage tally for John by adding up all damage values during combat where john has been hit #+BEGIN_SRC org ** Combat #+NAME: Combat-Action | Player | Damage | | |--------+--------+-----| | John | 15 | | |--------+--------+-----| | I Hit | Who | For | |--------+--------+-----| | Sam | John | 10 | | John | Sam | 1 | | Sam | John | 5 | #+TBLFM: @2$2=vsumifeq($2,'John',@4$3..@>$3) #+END_SRC *** Color Shortcut functions - red(cell): - green(cell): - yellow(cell): - blue(cell): - cyan(cell): - purple(cell): - orange(cell): - pink(cell): This would highlight a cell red if a players current hp is less than 10% and green otherwise: #+BEGIN_SRC org #+NAME: Player-Stats | Player | Start Health | Temp Hits | AC | Damage | Cur Hp | Initiative | |--------+--------------+-----------+----+--------+--------+------------| | | 13 | 0 | | 1 | 12 | | #+TBLFM:$6=($2+$3)-$5::%6=highlight($6,"red",$6) if((($6)/$2)*100.0)<=10.0 else highlight($6,"green",$6) #+END_SRC But it can now be rewritten as: #+BEGIN_SRC org #+NAME: Player-Stats | Player | Start Health | Temp Hits | AC | Damage | Cur Hp | Initiative | |--------+--------------+-----------+----+--------+--------+------------| | | 13 | 0 | | 1 | 12 | | #+TBLFM:$6=($2+$3)-$5::%6=red($6) if((($6)/$2)*100.0)<=10.0 else green($6) #+END_SRC *** Gradient Shortcut Better yet, avoid all the if else and use the new gradient method: - gradient(cell, progress_out_of_100, *colors) - Will choose a color sequentially out of the colors list based on the progress value: In the following example the Bridand would have a red Cur Hp and the Rabid Wolf will have a green Cur Hp value when the table is evaluated #+BEGIN_SRC org ** Monsters #+NAME: Monster-Stats | Name | Start Health | Damage | Cur Hp | AC | Initiative | |------------+--------------+--------+--------+----+------------| | Brigand | 10 | 9 | 1 | 4 | | | Rabid Wolf | 10 | 2 | 8 | 2 | | #+TBLFM:$4=$2-$3::$4=gradient($4,($4/$2)*100.0, "red","orange","yellow","cyan","green") #+END_SRC ================================================ FILE: messages/1.2.52.org ================================================ * 1.2.52 ** FIXED Html Exporter - The html exporter was crashing downloading HighlightJs with some odd SSL certificate errors. - The exporter may still have a few problems as it was converted recently. Please report any problems you may experience. [[https://github.com/ihdavids/orgextended/issues/69][Github Issue]] Thanks berteh for finding this one. ================================================ FILE: messages/1.2.53.org ================================================ * 1.2.53 ** FIXED Mermaid JS source blocks The mermaid source block handler was using an old default command line for mermaid. You should now specify mmdc.ps1 on windows: #+BEGIN_SRC js "mermaid": "C:\Users\ihdav\node_modules\.bin\mmdc.ps1", #+END_SRC On windows this will allow the following to run properly #+BEGIN_SRC mermaid :file mermaidout.png flowchart TD Start --> Stop #+END_SRC ** FIXED Org Capture - If the user had a list as their dayPagePath variable org capture would crash. Improved symbol expansion reliability a little bit. - File creation in directory that does not exists was not working. This should now be fixed ** FIXED Reveal JS Exporter Reveal js had moved on since the last time I used the exporter. Derusting is required to get it functional again. - [x] Reveal js exporter was missing Escape method of embedded source blocks Please note when using reveal exporter that if slides have to much content they will become jumbled. The layout is somewhat simplistic ================================================ FILE: messages/1.2.54.org ================================================ * 1.2.54 ** 3.8 Upgrade Package upgraded to the 3.8 runtime. TextTable plugin is still running on 3.3 but orgextended itself is now running on 3.8 for greater performance and cleanliness. NOTE: YOU WILL NEED TO RESTART SUBLIME TEXT SEVERAL TIMES TO ALLOW DEPENDENCIES TO INSTALL AND UPGRADE. I have run into some problems where the dateutil.rrule package will not update from the 3.3 version to the 3.8 version. The only solution I have found is to reinstall sublime and then reinstall OrgExtended. This forces the upgrade and allows things to work again. ** Agenda haschildtask filter Thanks to tim3z for his contribution to the agenda: - I sometimes need to filter for tasks with/without child tasks This adds the following keywords for child tasks #+BEGIN_QUOTE haschildtasks nochildtasks #+END_QUOTE ** Extended default binary formats for links Thanks to dyaso for extending the default binary formats list to include pdfs and word documents. #+BEGIN_EXAMPLE "file_exclude_patterns": [ "*.pdf", "*.doc", "*.docx", "*.docm", ], #+END_EXAMPLE ** FIX Agenda Day View Rendering Bug Fix for: [[https://github.com/ihdavids/orgextended/issues/85][Agenda does not work in ST4]] In recent builds of sublime text 4 The composite Agenda class was only able to render the first view when the tab is first opened. I am not sure why. I added a recursive command that draws on a second pass to work around the issue. This is not ideal but it at least gets things rendering again. ** FIX Todo View Not Rendering in ST4 Fix for: [[https://github.com/ihdavids/orgextended/issues/80][Org Todo View command shows an empty file, despite TODOs existing in tracked files]] This seems to have been the same issue as the Day View Rendering bug. When the tab pops up the first write attempt to the buffer seems to not be accepted until control has been returned to ST. I have made the command recursive to fix the issue. - The same problem also existed with Org Agenda Custom View which is consumed by Org Choose Custom View Overall these are all the same issue and something that has developed in modern versions of Sublime Text. I am not sure what has caused this but I suspect some of the read only features I am using are perhaps asynchronous events in some fashion and I may be racing with some internal message pump I do not fully understand vs my plugin thread. ** FIX Agenda Week View Lineup With Week Some previous changes to the week view had it a week off from the current day. This has been fixed ** FIX Color Scheme Genereator Fix for: [[https://github.com/ihdavids/orgextended/issues/83][Generated color schemas (partially) use camelCase instead of snake_case]] If you follow the [[https://github.com/ihdavids/orgextended_docs/blob/master/setup.org#color-scheme-generator][Color Scheme Generator]] instructions the generator seems to sometimes generate a: lineHighlight global vs line_highlight. This is an odd quirk that seems to manifest itself when parsing some existing color schemes. That camelCase version comes FROM the parsed version of the color scheme and I am not sure why. We now account for this and export a line_highlight variant that matches the lineHighlight version in the globals. ** FIX Agenda View Overlap Sorting Fix for: [[https://github.com/ihdavids/orgextended/issues/86][Overlapping events can appear out of order in the Agenda timeline]] Thanks to r4dian for reporting. This particular issue only seemed to happen if you moved to a previous day in the agenda. The time list was not being sorted properly resulting in times appearing out of order during the day. ** List Sort Docs There was confusion over the simplistic Org Sort List command. I added some quick docs to help demonstrate how that command works. It currently does not work on headings. Contributions welcome. [[https://github.com/ihdavids/orgextended_docs/blob/master/lists.org#sorting-lists][Org Sort List]] ** List Cookie Issues [[https://github.com/ihdavids/orgextended/issues/84][Cookies are wrongly calculated in lists with checkboxes]] List cookies: #+BEGIN_EXAMPLE - List [1/2] - [x] A - [ ] B - List2 - [ ] This should NOT be included in list 1 #+END_EXAMPLE had a problem when list types alternated from unordered lists to checked lists. This is not perfect but has been improved and should now no longer be combined. ================================================ FILE: messages/1.2.55.org ================================================ * 1.2.55 1.2.54 was a maintenance release with the goal of sorting some of the more painful reported issues people were struggling with. This release is about trying to clear the Issue list of any requested features. This is all in preparation for my next big personal feature push. I have been sort of forced to work in VSCode for the last few years and as such I have built a similar plugin to this one for VSCode (although I have not officially released it) That plugin took a slightly different route. As I was faced with the daunting task of duplicating what I had done here, I realized I had been foolish. LSP is a model I should have taken a page from, right from the get go. So While there are a ton of highlighting, editing and general movement commands built into the VSCode plugin the database and many of the auto formatting, refiling, capturing etc is done in a sort of org mode server over a rest api. It has always bugged me that this plugin is limited by the editor integration and while this brings org outside of emacs, its still locked into yet another editor. My plan is to migrate to some of the ideas I had with the VSCode version wrapping the existing DB in an abstraction so it can consume and work with the orgs server. I hope to offer a choice, either use the built in python DB in this plugin, OR choose to run the orgs server (it's written in Go) externally and get a web portal into your org files and command line capture and other CLI goodness as well as the editor integration. This will be a 2.0 offering of this plugin. orgs has other really great features. It has a JIRA integration that allows the creation of JIRA tickets from org files and syncing JIRA to an org file. It has a nice auto git sync option and some new exporters like a latex exporter that supports the DnD2Latex project, impressjs AND reveal exporter and an extensible, universal todo query language instead of the hacky thing I built into the Agenda system in this plugin. My end game here is that I would like to provide an LSP like setup for org-mode that can be used from any editor, but takes org outside of my editor in a variety of ways. This will have the benefit that: - Org is in your editor and can be ported to others without re-inventing the wheel. - Using Orgs allows for an HTML portal rendering your org files directly to your browser or phone helping with the challenge of using org on mobile. - Support the org-protocol capture mechanism - Access, refile, tag and search your orgs from your command line. - Supports integration into other tools like JIRA, Trello, Confluence, Todoist, Ad nauseum. - Supports a framework for exporting from org to other formats and importing from other formats to org. - Provides really powerful and comprehensive search tools for your data. - Is extensible enough I can integrate with beancount or other great text based finance tools with literate programming style reports, combined with the exporters offering all the invoicing, and other integrations I really appreciate. - Takes the dynamic burden of execution and refiling et al off the editor itself and pushes it squarely on a capable backend. In the past, chasing after updates in how the editor handles reloading of files has been a serious issue. - Is flexible enough, but also lightweight enough that you can use it in a ton of different creative ways. Anyways, BEFORE I get to working on the orgs integration, I really wanted to spend some time to cleanup anything that has been frustrating those people that have been on this journey with me and have been trying to use this thing. I sincerely hope you get value out of it. ** OrgCapture New File added TAGS instead of FILETAGS - OrgCapture when it creates a new file was adding TAGS: refile vs FILETAGS: :refile: ** Org Archive All Done Command Stuk asked for a command to archive all todos with a DONE status. This first version of the command is simplistic and hardcoded to DONE status but it will iterate through a buffer and archive all the DONE TODOS. [[https://github.com/ihdavids/orgextended/issues/72][Archive all DONE tasks]] ================================================ FILE: messages/1.2.56.org ================================================ * 1.2.56 ** htmlDefaultSkipSrc Not Respected BugFix htmlDefaultSkipSrc was not being respected when exporting to html. Thanks to bradleysmith who found that ditaa source blocks were exporting both the image and the source to html files even when ditaa was listed as a source skip block The plist system by its nature overrides this list if explicitly stated. Internally we did not have a way of determining if a user had explicitly set an exports mode or if we were operating in the default state. The system now has a default setting allowing this to work again. [[https://github.com/ihdavids/orgextended/issues/90][htmlDefaultSkipSrc ignores ditaa]] ================================================ FILE: messages/1.2.6.org ================================================ * 1.2.6 Core Idea: Inline Babel Blocks #+header: comments With this release we are focusing on some fringe pieces of the core babel feature set that we need to be complete. Inline babel blocks allow you to call a babel function within some other text providing even more dynamic living breathing documents. Header blocks extend the core babel features providing more real estate to add parameters to a source block. ** Links - Bugfix thanks to Anti-Distinctlyminty - on windows uses os.startfile() to launch a file link providing better support for out of sublime file links. Also some improved error notation in the contols when a link cannot resolve. ** Agenda Hover - Sometimes this would assert when the agenda was not active. ** Settings orgDirs - If someone sets their orgDirs to a string vs a list we would treat each character as an orgDir which was just plain wrong. I have augmented the db to detect that and just "do the right thing" ** Input - Additional guards against asserts in popups for the input box: [[https://github.com/ihdavids/orgextended/issues/28][Errors in Sublime Console]] Thanks to OlegBc for finding this one. ** Inline Blocks Basic inline source block syntax highlighting now works. Org has a somewhat odd inline syntax: src_python[:var x=5]{print("hello" + str(x))} {{{results(=hello5=)}}} Simple execution seems to be working: src_powershell{Write-Host "Hello World"} {{{results(=Hello World=)}}} ** PList Enhancements - Plists now have propper exclusion properties so :results output value will only have the last value since the options are considered mutually exclusive. - The unit tests have been enhanced to cover exclusivity. - Source blocks now have a global setting allowing you to control their default behaviour globally. this is inline with what you can do in emacs with: org-babel-default-header-args #+BEGIN_EXAMPLE "orgBabelDefaultHeaderArgs": ":var x=5" #+END_EXAMPLE ** HEADER comments Added support for the more generic HEADER comment blocks as seen below. #+HEADER: :var y=10 #+BEGIN_SRC python :var x=5 print(str(y) + " x " + str(x)) #+END_SRC #+RESULTS: : 10 x 5 ** Buffer Swap Respects Startup Comment I find that as I move around the buffer I tend to unfold a lot of "things" When I have a buffer set to "content" mode I like it to clean up the open folds when it can. This new setting will allow sublime to aggressively cleanup the folds to just your active subtree of the file if you turn this on. What I really want is org-narrow-to-subtree which is the ability to restrict a view to a narrowing of the buffer but in the absence of that capability this helps keep me focused on the things that matter in my file. - This is controlled by a setting: #+BEGIN_EXAMPLE "onFocusRespectStartupFolds": true, #+END_EXAMPLE ================================================ FILE: messages/1.2.7.org ================================================ * 1.2.7 Core Idea: Quality of Life This release is about stability, testing and validating the core babel feature set before I move on to noweb and tangle. ** Babel Unit Tests - Having most of the core babel features in place we have started to work towards validating the core babel feature set and putting a rough stamp of non preview on the babel feature set. - Added "Org Show Table Tests" and "Org Show Source Block Tests" which will create a file with the unit tests for these features as a means of documentation and exploration for new users. - FIXED: Issues with multiple :var statements on the fence line of a babel block. - FIXED: Exception with initial inserts with drawer formatter. ** SBE - FIXED: The Source Block Execute method had a bug that was preventing propper execution due to some of the features introduced in 1.2.6 - FIXED: cell being passed to an sbe function would sometimes not evaluate properly. ** Table Execution - New command: "Org Execute Formula" This will only execute the formula targetting the current cell vs the entire table. This can help when building a table. ** Table Highlights - Some expressions using SBE can get fairly expensive to compute. When highlighting cells the system executes formulas in the background to determine which cells the formula touches. To avoid paying that cost when moving around you can turn this off for a node in the heirarchy as follows: #+BEGIN_EXAMPLE :PROPERTIES: :NoTableHighlight: True :END: #+END_EXAMPLE I had to do this for the unit tests since our unit tests were generating diagrams as a result of the sbe calls Although an unrealistic real world case, this was slowing down the highlight to be somewhat unusable so merited the feature. ** Day Page - olegBc asked for a day page system. The project still has a little definition before we know where we need to take it. That said, I added a text command to create a day page as a first little step in that direction. ================================================ FILE: messages/1.2.8.org ================================================ * 1.2.8 - 1.2.7 was missing a source file. This fixes that. ================================================ FILE: messages/1.2.9.org ================================================ * 1.2.9 ** Babel Cache Caching will try to avoid executing a block if the source and or parameters have not changed. Caching uses a Sha1 hash of the source and parameter mix to determine if it should re-run the block. This mode is dangerous if the operation has any side effects. It does however skip execution when the operation is already present. It will keep a hash of the source and params and will only execute if the source does not change. #+BEGIN_SRC python :cache yes :var x=5 :tangle yes print("Hello world") #+END_SRC This feature is not yet well tested with source block chaining. #+RESULTS[5ce4498b4cf15deb48101207ad5673485754fd11]: : Hello world ** Never Eval A security feature of org is that you can specify that a block should never execute. This is now mostly working. #+BEGIN_SRC python :eval never print("hi") #+END_SRC ** Query Eval Query evaluation is mostly working now although the title of the query prompt is not great. #+BEGIN_SRC python :eval query :tangle yes print("Hello World") #+END_SRC #+RESULTS: : Hello World ** Tangle This release marks the begining of tangle work. Marking a source block as tangleable allows someone to export just the source code to a "detangled" file containing the source code and data from the page without the rest of the document. The resulting file will have the name of the the org file with the appropriate file extension for the source code. We get a new command with this release: - Org Tangle File #+BEGIN_SRC powershell :var y=5 :tangle yes Write-Host("Hello World") #+END_SRC ================================================ FILE: messages/gantt-demo.org ================================================ #+PROPERTY: header-args:R :session *R* #+PROPERTY: header-args :results silent #+COLUMNS: %ITEM(Task) %Effort(Effort) %START(Start) %END(End) %RESPONSIBLE(Responsible) %SPENT(Spent) %PROGRESS(Progress) %PROJECTED(Projected) %OVERUNDER(Over_Under) * Task 1 :PROPERTIES: :Effort: 1d :END: * Task 2 :PROPERTIES: :Effort: 3d :END: * Task 3 :PROPERTIES: :Effort: 4d :END: * Gantt Demo :Skip: #+NAME: gantt-table #+BEGIN: columnview :exclude-tags (Skip) | Task | Effort | Start | End | Responsible | Spent | Progress | Projected | Over_Under | |--------+--------+------------------+------------------+-------------+-------+----------+-----------+------------| | Task 1 | 1d | <2021-03-13 Sat> | <2021-03-14 Sun> | Ian | 1 | 40% | 2.50 | 1d 12h | | Task 2 | 3d | <2021-03-15 Mon> | <2021-03-18 Thu> | Joe | 2 | 10% | 20.00 | 17d | | Task 3 | 4d | <2021-03-18 Thu> | <2021-03-22 Mon> | Sam | 1 | 50% | 2.00 | 2d | | Task 4 | 7d | <2021-03-18 Thu> | <2021-03-25 Thu> | Sam | 1 | 50% | 2.00 | 5d | | Task 5 | 1d | <2021-03-18 Thu> | <2021-03-19 Fri> | Sam | 1 | 50% | 2.00 | 1d | | Task 6 | 2d | <2021-03-18 Thu> | <2021-03-20 Sat> | Sam | 1 | 35% | 2.86 | 20h 38mins | #+END: #+TBLFM:$4=date($-1)+duration($-2) if "$-1"!="" else ""::$8=$-2/$-1 if $-1 > 0 else "";%.2f::$9=duration($2) - $-1 if $-1>0 else "" #+BEGIN_SRC gnuplot :var DATA=gantt-table :file gantt-table.png OneMonth = strptime("%m","2") timeformat = "%Y-%m-%d" T(N) = timecolumn(N,timeformat) set xdata time set format x "%b\n'%y" set xtics OneMonth nomirror set xtics scale 2, 0.5 set mxtics 4 skiptorow=3 set yrange [(skiptorow-2):] reverse set ytics nomirror unset key set title "{/=15 GANTT Chart Example}" set grid x y set border 3 set style arrow 1 nohead filled size screen 0.02, 15 fixed lt 3 lw 8 plot "$DATA" using (T(3)) : ($0) : (T(4)-T(3)) : (0.0) : yticlabel(1) with vector as 1 #+END_SRC #+RESULTS: [[file:gantt-table.png]] ================================================ FILE: messages/install.org ================================================ * Initial release of Org Extended AFTER YOU INSTALL FOR THE FIRST TIME: LET IT RUN FOR ABOUT 60 SECONDS AND RESTART SUBLIME. WE INSTALL SOME DEPENDENCIES AND ARE NOT VERY GOOD ABOUT LETTING YOU KNOW THAT YOU NEED TO RESTART SUBLIME! Setup instructions can be found here: https://github.com/ihdavids/orgextended_docs/blob/master/start.org Org Mode in Emacs is an extensive lifestyle plugin. This plugin couldn't hope to duplicate the full expanse of Emacs org mode. That said, this plugin attempts to provide some of the amazing functionality found in Emacs org mode right here in sublime text! Org Mode IS: https://orgmode.org - A document interchange format - A personal wiki - A task and project management toolset - An agenda - A means of building living documents known as literate programming - The backend for blogs, webpages, and an outliner for authors. - A tool for authoring presentations. - A time tracking tool - A spreadsheet and data management tool - And much much more. This plugin is written selfishly as a means of helping me stay organized. It comes with no warranty whatsoever. It is my hope that you still find it useful. ================================================ FILE: messages.json ================================================ { "install": "messages/install.org", "1.0.0": "messages/install.org", "1.0.1": "messages/1.0.1.org", "1.0.2": "messages/1.0.2.org", "1.0.3": "messages/1.0.3.org", "1.0.4": "messages/1.0.4.org", "1.0.5": "messages/1.0.5.org", "1.0.6": "messages/1.0.6.org", "1.0.7": "messages/1.0.7.org", "1.0.8": "messages/1.0.8.org", "1.0.9": "messages/1.0.9.org", "1.0.10": "messages/1.0.10.org", "1.1.0": "messages/1.1.0.org", "1.1.1": "messages/1.1.1.org", "1.1.2": "messages/1.1.2.org", "1.1.3": "messages/1.1.3.org", "1.1.4": "messages/1.1.4.org", "1.1.5": "messages/1.1.5.org", "1.1.6": "messages/1.1.6.org", "1.1.7": "messages/1.1.7.org", "1.1.8": "messages/1.1.8.org", "1.1.9": "messages/1.1.9.org", "1.1.10": "messages/1.1.10.org", "1.1.11": "messages/1.1.11.org", "1.1.12": "messages/1.1.12.org", "1.1.13": "messages/1.1.13.org", "1.1.14": "messages/1.1.14.org", "1.1.15": "messages/1.1.15.org", "1.1.16": "messages/1.1.16.org", "1.1.17": "messages/1.1.17.org", "1.1.18": "messages/1.1.18.org", "1.1.19": "messages/1.1.19.org", "1.1.20": "messages/1.1.20.org", "1.1.21": "messages/1.1.21.org", "1.1.22": "messages/1.1.22.org", "1.1.23": "messages/1.1.23.org", "1.1.24": "messages/1.1.24.org", "1.1.25": "messages/1.1.25.org", "1.1.26": "messages/1.1.26.org", "1.1.27": "messages/1.1.27.org", "1.1.28": "messages/1.1.28.org", "1.1.29": "messages/1.1.29.org", "1.1.30": "messages/1.1.30.org", "1.2.0": "messages/1.2.0.org", "1.2.1": "messages/1.2.1.org", "1.2.2": "messages/1.2.2.org", "1.2.3": "messages/1.2.3.org", "1.2.4": "messages/1.2.4.org", "1.2.5": "messages/1.2.5.org", "1.2.6": "messages/1.2.6.org", "1.2.7": "messages/1.2.7.org", "1.2.8": "messages/1.2.8.org", "1.2.9": "messages/1.2.9.org", "1.2.10": "messages/1.2.10.org", "1.2.11": "messages/1.2.11.org", "1.2.12": "messages/1.2.12.org", "1.2.13": "messages/1.2.13.org", "1.2.14": "messages/1.2.14.org", "1.2.15": "messages/1.2.15.org", "1.2.16": "messages/1.2.16.org", "1.2.17": "messages/1.2.17.org", "1.2.18": "messages/1.2.18.org", "1.2.19": "messages/1.2.19.org", "1.2.20": "messages/1.2.20.org", "1.2.21": "messages/1.2.21.org", "1.2.22": "messages/1.2.22.org", "1.2.23": "messages/1.2.23.org", "1.2.24": "messages/1.2.24.org", "1.2.25": "messages/1.2.25.org", "1.2.26": "messages/1.2.26.org", "1.2.27": "messages/1.2.27.org", "1.2.28": "messages/1.2.28.org", "1.2.29": "messages/1.2.29.org", "1.2.30": "messages/1.2.30.org", "1.2.31": "messages/1.2.31.org", "1.2.32": "messages/1.2.32.org", "1.2.33": "messages/1.2.33.org", "1.2.34": "messages/1.2.34.org", "1.2.35": "messages/1.2.35.org", "1.2.36": "messages/1.2.36.org", "1.2.37": "messages/1.2.37.org", "1.2.38": "messages/1.2.38.org", "1.2.39": "messages/1.2.39.org", "1.2.40": "messages/1.2.40.org", "1.2.41": "messages/1.2.41.org", "1.2.42": "messages/1.2.42.org", "1.2.43": "messages/1.2.43.org", "1.2.44": "messages/1.2.44.org", "1.2.45": "messages/1.2.45.org", "1.2.46": "messages/1.2.46.org", "1.2.47": "messages/1.2.47.org", "1.2.48": "messages/1.2.48.org", "1.2.49": "messages/1.2.49.org", "1.2.50": "messages/1.2.50.org", "1.2.51": "messages/1.2.51.org", "1.2.52": "messages/1.2.52.org", "1.2.53": "messages/1.2.53.org", "1.2.54": "messages/1.2.54.org", "1.2.55": "messages/1.2.55.org", "1.2.56": "messages/1.2.56.org" } ================================================ FILE: orgagenda.py ================================================ import re import os import time import sublime, sublime_plugin import datetime import fnmatch import OrgExtended.orgparse.node as node import OrgExtended.orgparse.date as orgdate import OrgExtended.orgutil.util as util import OrgExtended.orgutil.navigation as nav import OrgExtended.orgutil.template as templateEngine import OrgExtended.orgduration as dur import logging import sys import traceback import OrgExtended.orgfolding as folding import OrgExtended.orgdb as db import OrgExtended.orgdatepicker as dpick import OrgExtended.asettings as sets import OrgExtended.pymitter as evt import OrgExtended.orginsertselected as insSel import calendar import dateutil.rrule as dr import dateutil.parser as dp import dateutil.relativedelta as drel log = logging.getLogger(__name__) AGENDA_VIEW = "Org Mode Agenda" TODO_VIEW = "Org Todos" ViewMappings = {} def ReloadAllUnsavedBuffers(): sheets = sublime.active_window().sheets() for sheet in sheets: view = sheet.view() if(view and util.isPotentialOrgFileOrBuffer(view)): db.Get().FindInfo(view) def IsRawDate(ts): return isinstance(ts,datetime.date) or isinstance(ts,datetime.datetime) def EnsureDateTime(ts): if(ts and not isinstance(ts,datetime.datetime)): return datetime.datetime.combine(ts, datetime.datetime.min.time()) return ts def EnsureDate(ts): if(isinstance(ts,datetime.datetime)): return ts.date() return ts def FindMappedView(view): if(view.name() in ViewMappings): return ViewMappings[view.name()] log.debug("Could not find view named: " + view.name()) return None def move_file_other_group(myview, view): window = sublime.active_window() if (window.num_groups() < 2): #self.window.run_command('clone_file') window.set_layout({ "cols": [0.0, 0.5, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1]] }) mygroup = 0 othergroup = 1 else: window.focus_view(view) mygroup = 1 othergroup = 0 if (window.get_view_index(myview)[0] == 0): othergroup = 1 mygroup = 0 window.focus_view(view) window.run_command('move_to_group', {'group': othergroup}) window.run_command('focus_group', {'group': mygroup}) window.focus_view(myview) #view0 = self.window.active_view_in_group(0) #view1 = self.window.active_view_in_group(1) # Same file open in each of the two windows, cull to 1 if possible #if (view0.file_name() == view1.file_name()): # self.window.focus_view(view1) #class CloneFileToNewViewCommand(sublime_plugin.WindowCommand): # def run(self): def get_view_for_silent_edit_file(file): # First check all sheets for this file. window = sublime.active_window() view = window.find_open_file(file.filename) if(view): return view # Okay the file is not opened, we have to open it # but we don't want it having focus # So keep the old view so we can refocus just to # be sure. currentView = window.active_view() view = window.open_file(file.filename, sublime.ENCODED_POSITION) window.focus_view(currentView) return view def CreateUniqueViewNamed(name, mapped=None): # Close the view if it exists win = sublime.active_window() for view in win.views(): if view.name() == name: win.focus_view(view) win.run_command('close') win.run_command('new_file') view = win.active_view() view.set_name(name) # TODO: Change this. view.set_syntax_file("Packages/OrgExtended/orgagenda.sublime-syntax") ViewMappings[view.name()] = mapped return view def IsPhone(n): return n and n.todo and "PHONE" in n.todo def IsMeeting(n): return n and n.todo and "MEETING" in n.todo def IsNote(n): return n and n.todo and "NOTE" in n.todo def IsTodo(n): return n.todo and n.todo in n.env.todo_keys def IsDone(n): return n.todo and n.todo in n.env.done_keys def IsArchived(n): return "ARCHIVE" in n.tags def HasChildTasks(n): for c in n.children: if(IsTodo(c)): return True return False # Task that belongs to a project. This means we have to have a parent and that parent has to be # identified as a project. def IsProjectTask(n): if(not n or n.is_root()): return False return (IsTodo(n) and n.parent and not n.parent.is_root() and IsProject(n.parent)) def IsBlockedProject(n): if(IsProject(n) and n.num_children > 0): isBlocked = True for c in n.children: if(c.todo and c.todo == 'NEXT'): isBlocked = False return isBlocked else: return False def IsProjectTodoWithTodos(n): if(IsTodo(n) and n.num_children > 0): for c in n.children: if(IsTodo(c)): return True return False def IsProjectTaskWithProjectTag(n): if(n): tags = n.shallow_tags if("PROJECT" in tags or "Project" in tags or "project" in tags): #print("PROJ: " + n.heading) return True return False def IsProjectTaskWithProjectProperty(n): if(n and (n.get_property("PROJECT") or n.get_property("Project") or n.get_property("project"))): return True return False def IsProject(n): projType = sets.Get("agendaProjectIs", "nested_todo").lower() if(projType == "nested_todo"): return IsProjectTodoWithTodos(n) if(projType == "tag"): return IsProjectTaskWithProjectTag(n) if(projType == "property"): return IsProjectTaskWithProjectProperty(n) return IsProjectTodoWithTodos(n) def IsTodaysDate(check, today): if(not type(check) == datetime.date): check = check.date() if(not type(today) == datetime.date): today = today.date() return today == check def IsInMonthCheck(t, now): if(IsRawDate(t)): dateT = t else: dateT = datetime.date(t.start.year, t.start.month, t.start.day) if (dateT.year == now.year): if (dateT.month >= (now.month-1) and dateT.month <= (now.month+1)): return True else: return False if (dateT.year == now.year + 1) and (dateT.month == 0 and now.month == 11): return True if (dateT.year == now.year - 1) and (dateT.month == 11 and now.month == 0): return True return False def IsInMonth(n, now): if(not n): return (None,None) if(n): timestamps = n.get_timestamps(active=True,point=True,range=True) for t in timestamps: if(t.repeating): next = t.next_repeat_from(now) if(IsInMonthCheck(next, now)): if(IsRawDate(t)): return (now,True) else: return (now, True) else: if(IsInMonthCheck(t, now)): return (t,False) if(n.scheduled): if(IsInMonthCheck(n.scheduled, now)): return (n.scheduled.start,n.scheduled.repeating) return (None,None) def IsToday(n, today): # 4 months of per day scheduling is the maximum # we are willing to loop to avoid crazy slow loops. kMaxLoops = sets.GetInt("agendaMaxScheduledIterations", 120) timestamps = n.get_timestamps(active=True,point=True,range=True) for t in timestamps: if(t.repeating): if(IsTodaysDate(t.start, today)): return t next = EnsureDateTime(t.start) loopcount = 0 while(next <= EnsureDateTime(today) and loopcount <= kMaxLoops): if IsTodaysDate(next, today): return next next = t.next_repeat_from(next) loopcount += 1 else: if(t.has_overlap(today)): return t if(n.scheduled): if(n.scheduled.repeating): next = n.scheduled.start loopcount = 0 while(EnsureDateTime(next) <= EnsureDateTime(today) and loopcount <= kMaxLoops): if IsTodaysDate(next, today): return next next = n.scheduled.next_repeat_from(EnsureDateTime(next)) loopcount += 1 else: return n.scheduled.after(today) if(n.deadline): start = EnsureDateTime(n.deadline.deadline_start) if start <= today: return n.deadline if(n.deadline.repeating): next = n.deadline.start loopcount = 0 while(EnsureDateTime(next) <= EnsureDateTime(today) and loopcount <= kMaxLoops): if IsTodaysDate(next, today): return next next = n.deadline.next_repeat_from(EnsureDateTime(next)) loopcount += 1 return None def IsAllDay(n,today): if(not n): return None timestamps = n.get_timestamps(active=True,point=True,range=True) for t in timestamps: if(t.repeating): dt = t.next_repeat_from(today) if(dt.hour == 0 and dt.minute == 0 and dt.second == 0 and dt.microsecond == 0): return dt else: if(t.has_end() or t.has_time()): continue return t if(n.scheduled): if(n.scheduled.repeating): dt = n.scheduled.next_repeat_from(today) if(dt.hour == 0 and dt.minute == 0 and dt.second == 0 and dt.microsecond == 0): return n.scheduled else: if(not n.scheduled.has_end() and not n.scheduled.has_time()): return n.scheduled if(n.deadline): dt = n.deadline.deadline_start if(isinstance(dt,datetime.date)): return True if(dt.hour == 0 and dt.minute == 0 and dt.second == 0 and dt.microsecond == 0): return today return None def HasTimestamp(n): if(not n): return False timestamps = n.get_timestamps(active=True,point=True,range=True) return n.scheduled or (timestamps and len(timestamps) > 0) or n.deadline def IsInHourBracket(s, e, hour): if(not e): # TODO Make this configurable e = s + datetime.timedelta(minutes=30) # Either this task is a ranged task OR it is a single point task # Ranged tasks have to fit within the hour, point tasks have to if( Overlaps(s.hour*60 + s.minute, e.hour*60 + e.minute, hour*60, hour*60 + 59)): return True def IsInHour(n, hour, today): if(not n): return None timestamps = n.get_timestamps(active=True, point=True,range=True) if(timestamps): for t in timestamps: if(t.has_time()): if(t.repeating): next = t.next_repeat_from(today) if(next.hour == hour): return next else: s = t.start e = t.end if(IsInHourBracket(s,e,hour)): return t if(n.scheduled and n.scheduled.has_time()): if(n.scheduled.repeating): next = n.scheduled.next_repeat_from(today) if next.hour == hour: return next else: return None s = EnsureDateTime(n.scheduled.start) e = EnsureDateTime(n.scheduled.end) if(IsInHourBracket(s,e,hour)): return n.scheduled if(n.deadline): s = EnsureDateTime(n.deadline.start) e = EnsureDateTime(n.deadline.end) if(IsInHourBracket(s,e,hour)): return n.deadline return None def Overlaps(s,e,rs,re): # s | e | # +---+ if(s <= rs and e >= rs and e <= re): return True # | s | e # +---+ if(s >= rs and s < re and e >= re): return True # | s e | # +-+ if(s >= rs and e <= re): return True # s | | e # +-------+ if(s <= rs and e >= re): return True return False def IsInHourAndMinuteBracket(s,e,hour,mstart,mend): if(not e): # TODO Make this configurable e = s + datetime.timedelta(minutes=30) # Either this task is a ranged task OR it is a single point task # Ranged tasks have to fit within the hour, point tasks have to if( Overlaps(s.hour*60 + s.minute, e.hour*60 + e.minute, hour*60 + mstart, hour*60 + mend)): return True return False def IsInHourAndMinute(n, hour, mstart, mend, today): if(not n): return None timestamps = n.get_timestamps(active=True, point=True,range=True) if(timestamps): for t in timestamps: if(t.has_time()): if(t.repeating): next = t.next_repeat_from(today) if(next.hour == hour): return next else: s = t.start e = t.end if(IsInHourAndMinuteBracket(s,e,hour,mstart,mend)): return t if(n.scheduled and n.scheduled.has_time()): if(n.scheduled.repeating): next = n.scheduled.next_repeat_from(today) if(next.hour == hour): return next s = n.scheduled.start e = n.scheduled.end if(IsInHourAndMinuteBracket(s,e,hour,mstart,mend)): return n.scheduled if(n.deadline): s = EnsureDateTime(n.deadline.start) e = EnsureDateTime(n.deadline.end) if(IsInHourAndMinuteBracket(s,e,hour,mstart,mend)): return n.deadline return None def distanceFromStart(e, hour, minSlot): ts = e['ts'] if(IsRawDate(ts)): rv = 5*(hour - ts.hour) + (minSlot - int(ts.minute/12)) else: rv = 5*(hour - ts.start.hour) + (minSlot - int(ts.start.minute/12)) return rv # ================================================================================ # IDEA Make a base class that has all the functionality needed to # render an agenda view. Then create an agenda folder with # all my views, like dynamic blocks. # # The goal being to allow people to extend and create custom # agenda views from their user folder, without having to # write all the "stuff" # # Also create a BUNCH of filters that filter by tag, properties # and other things so there are example versions of each. # # statefilter # tagfilter # priorityfilter class AgendaBaseView: def __init__(self, name, setup=True, **kwargs): self.name = name self.SetTagFilter(kwargs) self.SetPriorityFilter(kwargs) self.SetStateFilter(kwargs) self.SetDurationFilter(kwargs) self.SetClockedDurationFilter(kwargs) self.SetDateFilter(kwargs) self.hasclock = "hasclock" in kwargs self.clockedtoday = "clockedtoday" in kwargs self.clockfilter = "clockfilter" in kwargs self.hasclose = "hasclose" in kwargs self.hasdeadline = "hasdeadline" in kwargs self.hasschedule = "hasschedule" in kwargs self.noclock = "noclock" in kwargs self.noclose = "noclose" in kwargs self.nodeadline = "nodeadline" in kwargs self.noschedule = "noschedule" in kwargs self.onlyTasks = "onlytasks" in kwargs self.haschildtasks = "haschildtasks" in kwargs self.nochildtasks = "nochildtasks" in kwargs if(setup): self.SetupView() else: self.BasicSetup() # Default view does not have a filter view # Only todo view def OpenFilterView(self): pass def BasicSetup(self): self.UpdateNow() self.entries = [] def SetDurationFilter(self,kwargs): self._beforeDuration = [] self._afterDuration = [] if("durationfilter" in kwargs): self._durationFilter = kwargs["durationfilter"] else: self._durationFilter = None return tags = self._durationFilter.split(' ') for tag in tags: tag = tag.strip() if not tag or len(tag) <= 0: continue m = RE_IN_OUT_TAG.search(tag) if(m): inout = m.group('inout') tagdata = m.group('tag') if(not inout or inout == '+'): self._beforeDuration.append(dur.OrgDuration.Parse(tagdata.strip())) else: self._afterDuration.append(dur.OrgDuration.Parse(tagdata.strip())) def SetClockedDurationFilter(self,kwargs): self._beforeClockedDuration = [] self._afterClockedDuration = [] if("clockfilter" in kwargs): self._clockedDurationFilter = kwargs["clockfilter"] else: self._clockedDurationFilter = None return tags = self._clockedDurationFilter.split(' ') for tag in tags: tag = tag.strip() if not tag or len(tag) <= 0: continue m = RE_IN_OUT_TAG.search(tag) if(m): inout = m.group('inout') tagdata = m.group('tag') if(not inout or inout == '+'): self._beforeClockedDuration.append(dur.OrgDuration.Parse(tagdata.strip())) else: self._afterClockedDuration.append(dur.OrgDuration.Parse(tagdata.strip())) def SetStateFilter(self,kwargs): if("statefilter" in kwargs): self._stateFilter = kwargs["statefilter"] else: self._stateFilter = None return self._inStateTags = [] self._oneofStateTags = [] self._outStateTags = [] tags = self._stateFilter.split(' ') for tag in tags: tag = tag.strip() if not tag or len(tag) <= 0: continue m = RE_IN_OUT_TAG.search(tag) if(m): inout = m.group('inout') tagdata = m.group('tag') if(not inout or inout == '+'): self._inStateTags.append(tagdata.strip()) elif(inout == '|'): self._oneofStateTags.append(tagdata.strip()) else: self._outStateTags.append(tagdata.strip()) def SetPriorityFilter(self,kwargs): if("priorityfilter" in kwargs): self._priorityFilter = kwargs["priorityfilter"] else: self._priorityFilter = None return self._inPriorityTags = [] self._oneofPriorityTags = [] self._outPriorityTagsags = [] tags = self._priorityFilter.split(' ') for tag in tags: tag = tag.strip() if not tag or len(tag) <= 0: continue m = RE_IN_OUT_TAG.search(tag) if(m): inout = m.group('inout') tagdata = m.group('tag') if(not inout or inout == '+'): self._inPriorityTags.append(tagdata.strip()) elif(inout == '|'): self._oneofPriorityTags.append(tagdata.strip()) else: self._outPriorityTags.append(tagdata.strip()) def SetTagFilter(self,kwargs): if("tagfilter" in kwargs): self._tagfilter = kwargs["tagfilter"] else: self._tagfilter = None return self._intags = [] self._oneoftags = [] self._outtags = [] tags = self._tagfilter.split(' ') for tag in tags: tag = tag.strip() if not tag or len(tag) <= 0: continue m = RE_IN_OUT_TAG.search(tag) if(m): inout = m.group('inout') tagdata = m.group('tag') if(not inout or inout == '+'): self._intags.append(tagdata.strip()) elif(inout == '|'): self._oneoftags.append(tagdata.strip()) else: self._outtags.append(tagdata.strip()) def SetDateFilter(self, kwargs): self._startDoneDateComparator = None self._endDoneDateComparator = None if "datefilter" not in kwargs: return DATE_PATTERN = "([><=]+)(\d+)" datefilter = kwargs["datefilter"].split(" ") for cond in datefilter: match = re.search(DATE_PATTERN, cond) if match is None: continue operator = match.group(1) date_str = match.group(2) try: date = dp.parse(date_str) except: log.error("Failed to parse datefilter") continue if operator == ">": self._startDoneDateComparator = lambda d, date=date: d is not None and date < d if operator == ">=": self._startDoneDateComparator = lambda d, date=date: d is not None and date <= d if operator == "<": self._endDoneDateComparator = lambda d, date=date: d is not None and d < date if operator == "<=": date = date + datetime.timedelta(days=1) self._endDoneDateComparator = lambda d, date=date: d is not None and d < date def MatchHas(self, node): if(self.hasclock and not node.clock): return False if(self.hasdeadline and not node.deadline): return False if(self.hasclose and not node.closed): return False if(self.hasschedule and not node.scheduled): return False if(self.haschildtasks and not HasChildTasks(node)): return False if(self.noclock and node.clock): return False if(self.nodeadline and node.deadline): return False if(self.noclose and node.closed): return False if(self.noschedule and node.scheduled): return False if(self.nochildtasks and HasChildTasks(node)): return False return True def MatchTags(self, node): if(not self._tagfilter): return True if(self._intags and len(self._intags) > 0 and not all(elem in node.tags for elem in self._intags)): return False if(self._outtags and any(elem in node.tags for elem in self._outtags)): return False if(self._oneoftags and len(self._oneoftags) > 0 and not any(elem in node.tags for elem in self._oneoftags)): return False return True def MatchPriorities(self, node): if(not self._priorityFilter): return True if(self._inPriorityTags and len(self._inPriorityTags) > 0 and not all(elem in node.priority for elem in self._inPriorityTags)): return False if(self._outPriorityTags and any(elem in node.priority for elem in self._outPriorityTags)): return False if(self._oneofPriorityTags and len(self._oneofPriorityTags) > 0 and not any(elem in node.priority for elem in self._oneofPriorityTags)): return False return True def MatchState(self, node): t = node.todo if(not node.todo): t = "" if(not self._stateFilter): return True if(self._inStateTags and len(self._inStateTags) > 0 and not all(re.search(elem,t) for elem in self._inStateTags)): return False if(self._outStateTags and any(re.search(elem,t) for elem in self._outStateTags)): return False if(self._oneofStateTags and len(self._oneofStateTags) > 0 and not any(re.search(elem,t) for elem in self._oneofStateTags)): return False return True def MatchDuration(self, node): t = node.closed if(t and self._afterDuration and any(not t.after_duration(elem) for elem in self._afterDuration)): return False if self._beforeDuration: s = node.scheduled d = node.deadline ts = node.get_timestamps() if(s and any(s and s.before_duration(elem) for elem in self._beforeDuration)): return True if(d and any(d and d.before_duration(elem) for elem in self._beforeDuration)): return True if(ts and len(ts) > 0 and any(ts[0] and ts[0].before_duration(elem) for elem in self._beforeDuration)): return True return False return True def MatchDate(self, node): start = node.closed.start end = node.closed.end if node.closed.end is not None else start if self._startDoneDateComparator is not None \ and not self._startDoneDateComparator(start): return False if self._endDoneDateComparator is not None \ and not self._endDoneDateComparator(end): return False return True def MatchClock(self, node): if self.clockedtoday: if not node.clock: return False now = datetime.datetime.now() for c in node.clock: if c.start.date() == now.date(): return True if c.end.date() == now.date(): return True return False if self.clockfilter: if not node.clock: return False for t in node.clock: if t: if(self._afterClockedDuration and any(not t.after_duration(elem) for elem in self._afterClockedDuration)): return False if(self._beforeClockedDuration and any(not t.before_duration(elem) for elem in self._beforeClockedDuration)): return False return True def SetupView(self): self.view = CreateUniqueViewNamed(self.name, self) self.view.set_read_only(True) self.view.set_scratch(True) self.view.set_name(self.name) self.BasicSetup() self.FilterEntries() # Keep ourselves attached to this agenda # This doesn't work BOO self.view.agenda = self def DoRenderView(self,edit, clear = False): self.StartEditing() self.RenderView(edit, clear) self.DoneEditing() def OpenFilterView(self): first = True for v in self.agendaViews: v.view = self.view v.OpenFilterView() def InsertAgendaHeading(self, edit): if(hasattr(self,'_tagfilter') and self._tagfilter): self.view.insert(edit, self.view.size(), self.name + "\t\t TAGS( " + self._tagfilter + " )\n") else: self.view.insert(edit, self.view.size(), self.name + "\n") def UpdateNow(self, now=None): if(now == None): self.now = datetime.datetime.now() else: self.now = now self.entries = [] self.FilterEntries() # You have to bookend your editing session with these def StartEditing(self): self.view.set_read_only(False) def DoneEditing(self): self.view.set_read_only(True) def RestoreCursor(self, pos): # Restore the cursor self.view.sel().clear() self.view.sel().add(pos) def AddEntry(self, node, file): self.entries.append({"node": node, "file": file}) def ClearEntriesAt(self): for e in self.entries: if 'at' in e: del e['at'] def MarkEntryAt(self, entry, ts= None): if(not 'at' in entry): entry['at'] = [] entry['at'].append(self.view.rowcol(self.view.size())[0]) entry['ts'] = ts def MarkEntryAtRegion(self, entry, reg, ts=None): if(not 'at' in entry): entry['at'] = [] entry['at'].append(reg) entry['ts'] = ts def At(self, row, col): for e in self.entries: if 'at' in e: for ea in e['at']: if(type(ea) == int): if(ea == row): return (e['node'], e['file']) elif(type(ea) == sublime.Region): if(ea.contains(self.view.text_point(row,col))): return (e['node'], e['file']) return (None, None) def Clear(self, edit): self.StartEditing() self.view.erase(edit, sublime.Region(0,self.view.size())) self.DoneEditing() # ---------------------------------------------- # These are user extended views! def RenderView(self, edit, clear=False): pass def FilterEntries(self): allowOutsideOrgDir = sets.Get("agendaIncludeFilesOutsideOrgDir", False) for file in db.Get().Files: # Skip over files not in orgDir if(not file.isOrgDir and not allowOutsideOrgDir): continue #if(not "habits" in file.filename): # continue #print("AGENDA: " + file.filename + " " + file.key) for n in file.org[1:]: if(self.MatchHas(n) and self.MatchPriorities(n) and self.MatchTags(n) and self.MatchState(n) and self.MatchDuration(n) and self.MatchDate(n) and self.MatchClock(n) and self.FilterEntry(n, file)): self.AddEntry(n, file) def FilterEntry(self, node, file): pass def IsBeforeNow(ts, now): if(isinstance(ts,orgdate.OrgDate)): return ts and (not ts.has_time() or ts.start.time() < now.time()) elif(ts and isinstance(ts,datetime.datetime)): return ts.time() < now.time() else: return False def IsAfterNow(ts, now): if(isinstance(ts,orgdate.OrgDate)): return ts and ts.has_time() and ts.start.time() >= now.time() elif(ts and isinstance(ts,datetime.datetime)): return ts.time() >= now.time() else: return False # ============================================================ class CalendarView(AgendaBaseView): def __init__(self, name, setup=True,**kwargs): super(CalendarView, self).__init__(name, setup, **kwargs) firstDayIndex = sets.GetWeekdayIndexByName(sets.Get("firstDayOfWeek","Sunday")) self.dv = dpick.DateView("orgagenda.now",firstDayIndex = firstDayIndex) def UpdateNow(self, now=None): if(now == None): self.now = datetime.datetime.now() else: self.now = now self.dv.MoveCDateToDate(self.now) def AddRepeating(self, date): self.dv.AddToDayHighlights(date, "repeat", "orgagenda.blocked") def AddTodo(self, date): if(isinstance(date,orgdate.OrgDate)): date = date.start self.dv.AddToDayHighlights(date, "todo", "orgagenda.todo", sublime.DRAW_NO_FILL) #def AddToDayHighlights(self, date, key, hightlight, drawtype = sublime.DRAW_NO_OUTLINE): def RenderView(self, edit, clear=False): self.InsertAgendaHeading(edit) self.dv.SetView(self.view) self.dv.Render(self.now) toHighlight = [] for entry in self.entries: n = entry['node'] ts, repeating = IsInMonth(n, self.now) if(ts): self.AddTodo(ts) if(ts and repeating): self.AddRepeating(ts) def FilterEntry(self, n, filename): return (not self.onlyTasks or (IsTodo(n) and not IsDone(n) and not IsArchived(n))) and not IsProject(n) and HasTimestamp(n) def bystartdate(a, b): if a.scheduled.start > b.scheduled.start: return 1 if a.scheduled.start < b.scheduled.start: return -1 return 0 def bystartdatekey(a): return a.scheduled.start def bystartnodedatekey(a): n = a['node'] dt = a['ts'] #dt = n.scheduled.start if(isinstance(dt,orgdate.OrgDate)): dt=dt.start elif(isinstance(dt, datetime.date)): return datetime.datetime.combine(dt.today(), datetime.datetime.min.time()).timestamp() return dt.timestamp() def getdatefromnode(n): dt = datetime.datetime.min timestamps = n.get_timestamps(active=True,point=True,range=True) if timestamps and len(timestamps) > 0: dt = timestamps[0] if n.deadline: dt = n.deadline.start if n.scheduled: dt = n.scheduled.start if n.closed: dt = n.closed if(isinstance(dt,orgdate.OrgDate)): dt=dt.start #if(isinstance(dt, datetime.datetime)): # return datetime.datetime.combine(dt.date(), datetime.datetime.min.time()) if(isinstance(dt, datetime.date)): return datetime.datetime.combine(dt, datetime.datetime.min.time()) return dt def getdate(a): n = a['node'] return getdatefromnode(n) def getsortkey(a): n = a['node'] dt = getdatefromnode(n) result = 0 if dt: result = (dt - datetime.datetime(1970, 1, 1)).total_seconds() result = int(result) result = float(result) result *= 1000 # Include priority after datetime information if n and n.priority and n.priority != "": result += (ord(n.priority[0]) - ord('A'))*100 else: result += 0 # Ensure todos end up before done before archived if IsTodo(n): result += 1 if IsDone(n): result += 2 if IsArchived(n): result += 3 return result # ============================================================ class WeekView(AgendaBaseView): def __init__(self, name, setup=True,**kwargs): super(WeekView, self).__init__(name, setup, **kwargs) def HighlightTime(self, date): reg = self.DateToRegion(date) style = self.dayhighlight if(style == None): style = "orgdatepicker.monthheader" self.output.add_regions("curweek",[reg],style,"",sublime.DRAW_NO_OUTLINE) def InsertTimeHeading(self, edit, hour): self.startOffset = 9 self.cellSize = 5 pt = self.view.size() row, c = self.view.rowcol(pt) dayStart = sets.Get("agendaDayStartTime",6) dayEnd = sets.Get("agendaDayEndTime",19) if(dayEnd > 23): dayEnd = 23 if(dayStart < 0): dayStart = 0 if(dayStart > dayEnd): dayStart = 0 dayEnd = 23 header = " " for i in range(dayStart, dayEnd+1): if(i == 10): header += " " header += " {:2d}".format(i) header +=" \n" #header = " 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 \n" self.view.insert(edit, self.view.size(), header) dayStart = sets.Get("agendaDayStartTime",6) col = self.startOffset + (hour-dayStart)*self.cellSize s = self.view.text_point(row,col) e = self.view.text_point(row,col+2) reg = sublime.Region(s, e) style = "orgagenda.now" self.view.add_regions("curw",[reg],style,"",sublime.DRAW_NO_OUTLINE) def InsertDay(self, name, date, edit): pt = self.view.size() row, c = self.view.rowcol(pt) if(date.day == datetime.datetime.now().day): if(date.day == self.now.day): self.view.insert(edit, self.view.size(),"@" + name + " " + "{0:2}".format(date.day) + "W[") else: self.view.insert(edit, self.view.size(),"#" + name + " " + "{0:2}".format(date.day) + "W[") elif(date.day == self.now.day): self.view.insert(edit, self.view.size(),"&" + name + " " + "{0:2}".format(date.day) + "W[") else: self.view.insert(edit, self.view.size()," " + name + " " + "{0:2}".format(date.day) + "W[") daydata = [] for entry in self.entries: n = entry['node'] timestamps = n.get_timestamps(active=True,point=True,range=True) shouldContinue = False for t in timestamps: if(t.start.day == date.day and t.start.month == date.month and t.start.year == date.year): daydata.append(entry) entry['ts'] = t shouldContinue = True break if(shouldContinue): continue if(n.scheduled and (EnsureDate(n.scheduled.start) < EnsureDate(date) and not IsDone(n) and not IsArchived(n) or EnsureDate(n.scheduled.start) == EnsureDate(date))): daydata.append(entry) entry['ts'] = n.scheduled continue if(n.deadline and (EnsureDate(n.deadline.deadline_start) < EnsureDate(date) and not IsDone(n) and not IsArchived(n) or EnsureDate(n.deadline.deadline_start) == EnsureDate(date))): daydata.append(entry) entry['ts'] = n.deadline continue daydata.sort(key=bystartnodedatekey) lastMatchStart = 0 lastMatch = None lastMatchEntry = None matchCount = 0 doneMatchCount = 0 dayStart = sets.Get("agendaDayStartTime",6) dayEnd = sets.Get("agendaDayEndTime",19) if(dayEnd > 23): dayEnd = 23 if(dayStart < 0): dayStart = 0 if(dayStart > dayEnd): dayStart = 0 dayEnd = 23 for hour in range(dayStart,dayEnd+1): for minSlot in range(0,self.cellSize): match = None matche = None for entry in daydata: n = entry['node'] ts = IsInHourAndMinute(n, hour, minSlot*12, (minSlot+1)*12,date) entry['ts'] = ts if(ts): match = n matche = entry if(lastMatch != match and lastMatch != None): s = self.view.text_point(row,lastMatchStart) e = self.view.text_point(row,self.startOffset + (hour-dayStart)*self.cellSize + minSlot) reg = sublime.Region(s, e) if(IsDone(lastMatch) or IsArchived(lastMatch)): style = "orgagenda.week.done." + str(doneMatchCount) doneMatchCount = (doneMatchCount + 1) % 2 self.MarkEntryAtRegion(lastMatchEntry,reg) self.view.add_regions("week_done_" + str(date.day) + "_" + str(hour) + "_" + str(minSlot),[reg],style,"", sublime.DRAW_SQUIGGLY_UNDERLINE) else: style = "orgagenda.week." + str(matchCount) matchCount = (matchCount + 1) % 10 self.MarkEntryAtRegion(lastMatchEntry,reg) self.view.add_regions("week_" + str(date.day) + "_" + str(hour) + "_" + str(minSlot),[reg],style,"",sublime.DRAW_NO_FILL) if(match != None): if(lastMatch != match): lastMatch = match lastMatchEntry = matche lastMatchStart = self.startOffset + (hour-dayStart)*self.cellSize + minSlot d = distanceFromStart(matche, hour, minSlot) # If the time slot is larger than the name we space pad it c = " " if(d < len(match.heading) and d >= 0): c = match.heading[d:d+1] self.view.insert(edit, self.view.size(), c) else: if(lastMatch != match): lastMatch = match lastMatchStart = self.startOffset + (hour-dayStart)*self.cellSize + minSlot lastMatchEntry = matche if(minSlot < 4): self.view.insert(edit, self.view.size(), ".") else: self.view.insert(edit, self.view.size(), "_") self.view.insert(edit, self.view.size(),"]\n") def RenderView(self, edit, clear=False): self.InsertAgendaHeading(edit) self.InsertTimeHeading(edit,self.now.hour) #print(str(self.now)) wday = self.now.weekday() firstDayIndex = sets.GetWeekdayIndexByName(sets.Get("firstDayOfWeek", "Sunday")) wstart = self.now + datetime.timedelta(days=-((wday+1)%7)-((firstDayIndex+1)%7)) dayNames = sets.Get("weekViewDayNames",["Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"]) numDays = sets.Get("agendaWeekViewNumDays",7) for i in range(0,numDays): index = (firstDayIndex + i) % len(dayNames) self.InsertDay(dayNames[index], wstart + datetime.timedelta(days=i), edit) def FilterEntry(self, n, filename): rc = (not self.onlyTasks or (IsTodo(node) or IsDone(n))) and not IsProject(n) and HasTimestamp(n) return rc # ============================================================ class AgendaView(AgendaBaseView): def __init__(self, name, setup=True, **kwargs): super(AgendaView, self).__init__(name, setup, **kwargs) self.blocks = [None,None,None,None,None,None,None] self.sym = ("$","@","!","#","%","^","&") self.symUsed = [-1,-1,-1,-1,-1,-1,-1] def RenderDateHeading(self, edit, now): headerFormat = sets.Get("agendaHeaderFormat","%A \t%d %B %Y") self.view.insert(edit, self.view.size(), now.strftime(headerFormat) + "\n\n") def BuildHabitDisplay(self, n): if(n.scheduled and n.get_property("STYLE",None)): #OrgDateRepeatedTask repeats = n.repeated_tasks habitbar = "[_____________________]" hb = list(habitbar) # not schedule but done # not schedule not done # scheduled but not done # scheduled but last day # late # done if(repeats): start = self.now-drel.relativedelta(days=20) cur = self.now-drel.relativedelta(days=21) while(cur < self.now): cur = n.scheduled.next_repeat_from(cur) if(cur < self.now): diff = (self.now - cur).days diff = 21 - diff hb[diff] = '.' for i in range(0,21): cur = start + drel.relativedelta(days=i) for r in repeats: if r.has_overlap(cur): hb[i+1] = '*' pass return "H" + ''.join(hb) return "" def GetUnusedSymbol(self, blk): start = 0 for i in range(0,len(self.symUsed)): if(self.symUsed[i] >= 0): start = i break for i in range(start,len(self.symUsed)): if(self.symUsed[i] < 0): self.symUsed[i] = blk return i return -1 def ReleaseSymbol(self, blk): for i in range(0,len(self.symUsed)): if(self.symUsed[i] == blk): self.symUsed[i] = -1 break def FindSymbol(self, blk): for i in range(0,len(self.symUsed)): if(self.symUsed[i] == blk): return i return 0 def ClearAgendaBlocks(self,h): for i in range(0, len(self.blocks)): n = self.blocks[i] if(not IsInHour(n, h,self.now)): self.ReleaseSymbol(i) self.blocks[i] = None def UpdateWithThisBlock(self, n, h): idx = -1 for i in range(0, len(self.blocks)): if(idx == -1 and self.blocks[i] == None): idx = i if(self.blocks[i] == n): idx = -1 return i if(idx != -1): self.blocks[idx] = n return idx return 0 def GetAgendaBlocks(self,n,h): out = "" if(n != None): symIdx = self.GetUnusedSymbol(0) self.ClearAgendaBlocks(h) myIdx = self.UpdateWithThisBlock(n, h) self.symUsed[symIdx] = myIdx else: self.ClearAgendaBlocks(h) spaceSym = "." for i in range(0, len(self.blocks)): if(self.blocks[i]): spaceSym = " " if(spaceSym == "."): out = ".." for i in range(0, len(self.blocks)): if(not self.blocks[i]): out = out + spaceSym else: symIdx = self.FindSymbol(i) out = out + self.sym[symIdx] return out def RenderAgendaEntry(self,edit,filename,n,h,ts): view = self.view if(IsRawDate(ts)): view.insert(edit, view.size(), "{0:12} {1:02d}:{2:02d}B[{7}] {3} {4:45} {5}{6}\n".format(filename if (len(filename) <= 12) else filename[:11] + ":" , h, ts.minute, n.todo if n.todo else "", n.heading, self.BuildDeadlineDisplay(n), self.BuildHabitDisplay(n), self.GetAgendaBlocks(n,h))) else: view.insert(edit, view.size(), "{0:12} {1:02d}:{2:02d}B[{7}] {3} {4:45} {5}{6}\n".format(filename if (len(filename) <= 12) else filename[:11] + ":" , h, ts.start.minute, n.todo if n.todo else "", n.heading, self.BuildDeadlineDisplay(n), self.BuildHabitDisplay(n), self.GetAgendaBlocks(n,h))) def BuildDeadlineDisplay(self, node): if(node.deadline): if(EnsureDateTime(node.deadline.deadline_start) <= self.now): if(EnsureDateTime(node.deadline.start).date() < self.now.date()): return "D: Overdue" elif(EnsureDateTime(node.deadline.start).date() == self.now.date()): return "D: Due Today" else: return "D:@" + str(EnsureDateTime(node.deadline.start).date()) else: return "" def RenderView(self, edit, clear=False): self.InsertAgendaHeading(edit) self.RenderDateHeading(edit, self.now) view = self.view dayStart = sets.Get("agendaDayStartTime",6) dayEnd = sets.Get("agendaDayEndTime",19) allDat = [] before = True for h in range(dayStart, dayEnd): didNotInsert = True if(self.now.hour == h): foundItems = [] for entry in self.entries: n = entry['node'] #filename = entry['file'].AgendaFilenameTag() ts = IsInHour(n, h, self.now) if(IsBeforeNow(ts, self.now) and ts): entry['ts'] = ts if(not 'found' in entry): foundItems.append(entry) entry['found'] = 'b' if(len(foundItems) > 0): foundItems.sort(key=bystartnodedatekey) for it in foundItems: n = it['node'] ts = it['ts'] if(ts == None): ts = n.scheduled filename = it['file'].AgendaFilenameTag() self.MarkEntryAt(it,ts) self.RenderAgendaEntry(edit,filename,n,h,ts) didNotInsert = False view.insert(edit, view.size(), "{0:12} {1:02d}:{2:02d} - - - - - - - - - - - - - - - - - - - - - \n".format("now =>", self.now.hour, self.now.minute) ) foundItems = [] for entry in self.entries: n = entry['node'] #filename = entry['file'].AgendaFilenameTag() ts = IsInHour(n, h, self.now) if(IsAfterNow(ts, self.now) and ts): entry['ts'] = ts if(not 'found' in entry or entry['found'] == 'b'): foundItems.append(entry) entry['found'] = 'a' if(len(foundItems) > 0): foundItems.sort(key=bystartnodedatekey) for it in foundItems: n = it['node'] ts = it['ts'] if(ts == None): ts = n.scheduled filename = it['file'].AgendaFilenameTag() self.MarkEntryAt(it,ts) self.RenderAgendaEntry(edit,filename,n,h,ts) didNotInsert = False before = False else: # Filter timestamps so we can sort by timestamp foundItems = [] for entry in self.entries: n = entry['node'] ts = IsInHour(n,h,self.now) if(ts and (not 'found' in entry or (not before and entry['found'] == 'b'))): entry['ts'] = ts foundItems.append(entry) foundItems.sort(key=bystartnodedatekey) for entry in foundItems: n = entry['node'] filename = entry['file'].AgendaFilenameTag() ts = entry['ts'] if(before): entry['found'] = 'b' else: entry['found'] = 'a' self.MarkEntryAt(entry, ts) self.RenderAgendaEntry(edit,filename,n,h,ts) didNotInsert = False if(didNotInsert): empty = " " * 12 blocks = self.GetAgendaBlocks(None,h) sep = "" esep = " " if(not '.' in blocks): sep = "B[" esep = "]" view.insert(edit, view.size(), "{0:12} {1:02d}:00{3}{2}{4}---------------------\n".format(empty, h, blocks, sep, esep)) view.insert(edit,view.size(),"\n") for entry in self.entries: n = entry['node'] filename = entry['file'].AgendaFilenameTag() ts = IsAllDay(n,self.now) if(ts): self.MarkEntryAt(entry,ts) view.insert(edit, view.size(), "{0:12} {1} {2:69} {3} {4}\n".format(filename, n.todo if n.todo else "", n.heading, self.BuildDeadlineDisplay(n), self.BuildHabitDisplay(n))) def FilterEntry(self, node, file): rc = (not self.onlyTasks or IsTodo(node)) and not IsDone(node) and not IsArchived(node) and IsToday(node, self.now) return rc RE_IN_OUT_TAG = re.compile('(?P[|+-])?(?P[^ ]+)') # ================================================================================ class TodoView(AgendaBaseView): def GetParam(self, name, defaultVal, kwargs): v = kwargs[name] if name in kwargs else None if isinstance(v,bool): v = ">10.10" return v def __init__(self, name, setup=True, **kwargs): super(TodoView, self).__init__(name, setup, **kwargs) self.showduration = self.GetParam("showduration","7.7",kwargs) self.showfilename = "15.15" if "hidefilename" not in kwargs else None self.showheading = "hideheading" not in kwargs self.showstatus = "11.11" if "hidestatus" not in kwargs else None self.showdate = self.GetParam("showdate","15.15",kwargs) self.showtime = self.GetParam("showtime","6.6",kwargs) self.showeffort = self.GetParam("showeffort",">6.6",kwargs) self.showafter = self.GetParam("showafter",">12.12",kwargs) self.showassigned = self.GetParam("showassigned",">12.12", kwargs) self.showid = self.GetParam("showid",">10.10", kwargs) self.showtotalduration = "showtotalduration" in kwargs self.byproject = "byproject" in kwargs self.input = None self.search_filter = None self.havesortorder = "sortascend" in kwargs or "sortdescend" in kwargs self.sortorder = False if self.havesortorder: self.sortorder = False if "sortascend" in kwargs else self.sortorder self.sortorder = True if "sortdescend" in kwargs else self.sortorder def GetFormatHeaders(self, n, filename): data = {} data2 = {} if self.showfilename: data['filename'] = "File" data2['filename'] = "---------------" if self.showstatus: data['status'] = "Status" data2['status'] = "-----------" if self.showduration: data['duration'] = "Duration" data2['duration']= "--------" if self.showheading: data['heading'] = "Heading" data2['heading'] = "--------------------" if self.showdate: data['date'] = "Date" data2['date']= "---------------" if self.showtime: data['time'] = "Time" data2['time'] = "------" if self.showeffort: data['effort'] = "Effort" data2['effort'] = "------" if self.showafter: data['after'] = "After" data2['after'] = "------------" if self.showid: data['id'] = "ID" data2['id'] = "-----------------" if self.showassigned: data['assigned'] = "Who" data2['assigned'] = "------------" return (data, data2) def GetFormatData(self, n, filename): data = {} if self.showfilename: data['filename'] = filename if self.showstatus: todo = "" if n: todo = n.todo if todo == None: todo = "" data['status'] = todo if self.showduration: duration = "" dur = datetime.timedelta(days=0) if n: for c in n.clock: dur += c.duration self.totalduration += dur duration = orgdate.OrgDate.format_duration(dur) data['duration'] = duration if self.showheading: heading = "" if n: heading = n.heading data['heading'] = heading if self.showdate: date = "" if n: dt = getdatefromnode(n) if dt != datetime.datetime.min and dt.date() != datetime.date.min: date = dt.strftime("%Y-%m-%d %a") data['date'] = date if self.showtime: time = "" if n: dt = getdatefromnode(n) if dt != datetime.datetime.min and dt.time() != datetime.time.min: time = dt.time().strftime("%H:%M") data['time'] = time if self.showeffort: effort = "" if n: effort = n.get_property("EFFORT","") data['effort'] = effort if self.showafter: after = "" if n: after = n.get_property("AFTER","") data['after'] = after if self.showid: idd = "" if n: idd = n.get_property("ID","") if not idd or idd == "": idd = n.get_property("CUSTOM_ID","") data['id'] = idd if self.showassigned: ass = "" if n: ass = n.get_property("ASSIGNED","") data['assigned'] = ass return data def GetF(self,p,name): if p: return "{" + name + ":" + p + "} " return "" def GetFormatString(self): formatstr = "" formatstr += self.GetF(self.showfilename,"filename") formatstr += self.GetF(self.showstatus,"status") formatstr += self.GetF(self.showduration,"duration") formatstr += self.GetF(self.showdate,"date") formatstr += self.GetF(self.showtime,"time") formatstr += self.GetF(self.showeffort,"effort") formatstr += self.GetF(self.showafter,"after") formatstr += self.GetF(self.showid,"id") formatstr += self.GetF(self.showassigned,"assigned") if self.showheading: formatstr += "{heading}" formatstr += "\n" return formatstr def OnFilter(self, text): #print("FILTER: " + str(text)) self.input.onRecalc = evt.Make(self.OnFilter) if text == None: self.search_filter = None else: self.search_filter = re.compile(text + ".*") self.view.run_command("org_agenda_re_render_view") def OpenFilterView(self): if self.input != None: self.input.onRecalc = evt.Make(self.OnFilter) self.input.run("Filter:",None,evt.Make(self.OnFilter)) def getSortOrdering(self): order = not sets.Get("agendaTodoSortAscending",True) if self.havesortorder: order = self.sortorder return order def RenderView(self, edit, clear = False): self.ClearEntriesAt() if clear: self.view.erase(edit, sublime.Region(0, self.view.size())) self.InsertAgendaHeading(edit) formatstr = self.GetFormatString() data,under = self.GetFormatHeaders(None,"") self.view.insert(edit, self.view.size(), formatstr.format(**data)) self.view.insert(edit, self.view.size(), formatstr.format(**under)) self.totalduration = datetime.timedelta(days=0) if self.byproject: projects = {} loosetasks = [] for entry in self.entries: n = entry['node'] if n == None: continue if self.search_filter and not n.is_root() and not self.search_filter.match(n.heading): continue if n.is_root() or n.parent == None or n.parent.is_root() or not IsProject(n.parent): loosetasks.append(entry) else: pname = n.parent.heading if pname not in projects: projects[pname] = [] projects[pname].append(entry) for pname,vals in projects.items(): vals.sort(key=getsortkey,reverse=self.getSortOrdering()) projects[pname] = vals for pname,vals in projects.items(): self.view.insert(edit, self.view.size(), "\n== [{0}] ==\n".format(pname)) for entry in vals: n = entry['node'] filename = entry['file'].AgendaFilenameTag() self.MarkEntryAt(entry) self.RenderEntry(n, filename, edit) if len(loosetasks) > 0: self.view.insert(edit, self.view.size(), "\n== [] ==\n") for entry in loosetasks: n = entry['node'] filename = entry['file'].AgendaFilenameTag() self.MarkEntryAt(entry) self.RenderEntry(n, filename, edit) else: self.entries.sort(key=getsortkey,reverse=self.getSortOrdering()) for entry in self.entries: n = entry['node'] if self.search_filter and not n.is_root() and not self.search_filter.match(n.heading): continue filename = entry['file'].AgendaFilenameTag() self.MarkEntryAt(entry) self.RenderEntry(n, filename, edit) if self.showtotalduration: formatstr = self.GetFormatString() data = self.GetFormatData(None,"") data['duration'] = orgdate.OrgDate.format_duration(self.totalduration) data['filename'] = "TOTAL: " self.view.insert(edit, self.view.size(), "----------------------------------------------------------------------------\n") self.view.insert(edit, self.view.size(), formatstr.format(**data)) if(self.input == None): self.input = insSel.OrgInput() shouldFilter = sets.Get("agendaTodoFilterByDefault", False) if shouldFilter: self.OpenFilterView() def RenderEntry(self, n, filename, edit): formatstr = self.GetFormatString() data = self.GetFormatData(n, filename) self.view.insert(edit, self.view.size(), formatstr.format(**data)) def FilterEntry(self, n, filename): return IsTodo(n) and not IsProject(n) and not IsArchived(n) # ================================================================================ class ProjectsView(TodoView): def __init__(self, name, setup=True, **kwargs): super(ProjectsView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsProject(n) and not IsArchived(n) # ================================================================================ class NotBlockedProjectsView(TodoView): def __init__(self, name, setup=True, **kwargs): super(ProjectsView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsProject(n) and not IsBlockedProject(n) and not IsArchived(n) # ================================================================================ class BlockedProjectsView(TodoView): def __init__(self, name, setup=True, **kwargs): super(BlockedProjectsView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsBlockedProject(n) and not IsArchived(n) # ================================================================================ class LooseTasksView(TodoView): def __init__(self, name, setup=True, **kwargs): super(LooseTasksView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): rc = IsTodo(n) and not IsProject(n) and not IsProjectTask(n) and not IsArchived(n) return rc # ================================================================================ class DoneTasksView(TodoView): def __init__(self, name, setup=True, **kwargs): super(DoneTasksView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): rc = IsDone(n) and not IsArchived(n) return rc # ================================================================================ class ClockedView(TodoView): def __init__(self, name, setup=True, **kwargs): super(ClockedView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return n and n.clock # ================================================================================ class HasStatusView(TodoView): def __init__(self, name, setup=True, **kwargs): super(HasStatusView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return n and (IsDone(n) or IsTodo(n)) # ================================================================================ class NextTasksProjectsView(TodoView): def __init__(self, name, setup=True, **kwargs): super(NextTasksProjectsView, self).__init__(name, setup, **kwargs) # TODO Print project and then the next task def RenderView(self, edit, clear=False): self.InsertAgendaHeading(edit) newEntries = [] for entry in self.entries: n = entry['node'] filename = entry['file'].AgendaFilenameTag() self.MarkEntryAt(entry) self.view.insert(edit, self.view.size(), "{0:15} {1:12} {2}\n".format(filename,"-------", n.heading)) #self.RenderEntry(n, filename, edit) for c in n.children: if(c.todo and c.todo == "NEXT"): nentry = {'node': c, 'file': entry['file']} newEntries.append(nentry) self.MarkEntryAt(nentry) self.view.insert(edit, self.view.size(), "{0:15} {1:12} {2}\n".format(" ", c.todo, c.heading)) #self.RenderEntry(c, filename, edit) for e in newEntries: self.entries.append(e) def FilterEntry(self, n, filename): return IsProject(n) and not IsBlockedProject(n) and not IsArchived(n) # ================================================================================ class NoteView(TodoView): def __init__(self, name, setup=True,**kwargs): super(NoteView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsNote(n) and not IsProject(n) and not IsProjectTask(n) and not IsArchived(n) # ================================================================================ class PhoneView(TodoView): def __init__(self, name, setup=True,**kwargs): super(PhoneView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsPhone(n) and not IsProject(n) and not IsProjectTask(n) and self.MatchTags(n) and not IsArchived(n) # ================================================================================ class MeetingView(TodoView): def __init__(self, name, setup=True,**kwargs): super(MeetingView, self).__init__(name, setup, **kwargs) def FilterEntry(self, n, filename): return IsMeeting(n) and not IsProject(n) and not IsProjectTask(n) and self.MatchTags(n) and not IsArchived(n) # ================================================================================ class CompositeViewListener(sublime_plugin.ViewEventListener): @classmethod def is_applicable(cls, settings): # 4095 seems to crash when querying settings if(int(sublime.version()) != 4095): try: return "orgagenda" in settings.get("color_scheme","not here") except: return False return False def __init__(self, view): super(CompositeViewListener, self).__init__(view) self.agenda = FindMappedView(self.view) self.phantoms = [] def clear_phantoms(self): for f in self.phantoms: self.view.erase_phantoms(f) self.phantoms = [] def on_hover_done(self): self.clear_phantoms() def on_hover(self, point, hover_zone): if(not hasattr(self,'agenda') or self.agenda == None): return if(hover_zone == sublime.HOVER_TEXT): row,col = self.view.rowcol(point) n, f = self.agenda.At(row, col) if(n and f): self.clear_phantoms() line = self.view.line(point) reg = sublime.Region(point, line.end()) body = """
{0}
{1}
""".format(n.heading,f.filename) self.view.add_phantom(n.heading, reg, body, sublime.LAYOUT_INLINE) #sublime.Phantom(sublime.Region(point, point), "" + n.heading + "",sublime.LAYOUT_INLINE, None) self.phantoms.append(n.heading) print(n.heading) sublime.set_timeout(self.on_hover_done, 1000*2) # ================================================================================ # ORG has this custom composite view feature. # I want that. Make a view up of a couple of views. class CompositeView(AgendaBaseView): def __init__(self, name, views): self.agendaViews = views super(CompositeView, self).__init__(name) self.SetupView() def RenderView(self, edit, clear=False): first = True for v in self.agendaViews: if not first: self.view.insert(edit, self.view.size(), ("=" * 75) + "\n") first = False v.view = self.view v.RenderView(edit, clear) # These get updated when rendered self.entries = [] for v in self.agendaViews: self.entries += v.entries def UpdateNow(self, now=None): if(now == None): self.now = datetime.datetime.now() else: self.now = now for v in self.agendaViews: v.UpdateNow(now) def FilterEntries(self): self.entries = [] for v in self.agendaViews: v.entries = [] v.FilterEntries() self.entries += v.entries def At(self, row, col): for av in self.agendaViews: n, f = av.At(row,col) if(n and f): return (n,f) return (None, None) # ================================================================================ class OrgTodoViewCommand(sublime_plugin.TextCommand): # This recursive crap seems to be an ST4 issue that # I don't fully understand yet. But am working around. def onDone(self, edit, todo): todo.DoRenderView(edit) if self.pos is not None: todo.RestoreCursor(self.pos) def run(self, edit, draw=False, pos=None): if(draw and self.view.name() == TODO_VIEW): todo = FindMappedView(self.view) self.pos = pos self.onDone(edit, todo) else: if self.view.name() == TODO_VIEW: pos = self.view.sel()[0].begin() todo = TodoView(TODO_VIEW) todo.view.run_command("org_todo_view", {"draw": True, "pos":pos}) # ================================================================================ # Right now this is a composite view... Need to allow the user to define # Their own versions of this. class OrgAgendaDayViewCommand(sublime_plugin.TextCommand): def onDone(self, edit, agenda): agenda.DoRenderView(edit) if(self.pos is not None): agenda.RestoreCursor(self.pos) log.info("Day view refreshed") def run(self, edit, draw=False, pos=None): VIEW_NAME="Agenda" if draw: # This is a hack: A bug in sublime 4 seems to not alow multiple inserts # on the edit object when the buffer is created. For now just work around # I HATE this but it at least stops this from being just plain broken self.pos = pos agenda = FindMappedView(self.view) self.onDone(edit, agenda) return else: if(self.view.name() == VIEW_NAME): pos = self.view.sel()[0].begin() # Save and restore the cursor views = [CalendarView("Calendar",False), WeekView("Week", False), AgendaView("Agenda", False), BlockedProjectsView("Blocked Projects",False), NextTasksProjectsView("Next",False), LooseTasksView("Loose Tasks",False)] #views = [AgendaView("Agenda", False), TodoView("Global Todo List", False)] agenda = CompositeView(VIEW_NAME, views) agenda.view.run_command("org_agenda_day_view", {"draw": True, "pos":pos}) # ================================================================================ # Goto the file in the current window (ENTER) class OrgAgendaGoToCommand(sublime_plugin.TextCommand): def run(self, edit): agenda = FindMappedView(self.view) if(agenda): row, col = self.view.curRowCol() n, f = agenda.At(row, col) if(f): if(n): path = "{0}:{1}".format(f.filename,n.start_row + 1) self.view.window().open_file(path, sublime.ENCODED_POSITION) else: log.warning("COULD NOT LOCATE AGENDA ROW") # ================================================================================ class RunEditingCommandOnNode: def __init__(self, view, command, params={}): self.view = view self.command = command self.params = params def onAfterSaved(self): pass # Not needed anymore def onSaved(self): whenDoneEvt = util.RandomString() evt.Get().once(whenDoneEvt, self.onAfterSaved) if self.viewName == "Agenda": self.view.run_command("org_agenda_day_view") else: self.view.run_command("org_agenda_custom_view", { "toShow": self.viewName, "onDone": whenDoneEvt }) def onEdited(self): # NOTE the save here doesn't seem to be working # Not sure why. BUT... view = self.savedView view.run_command("save") sublime.set_timeout_async(lambda: self.onSaved(), 100) def onLoaded(self): view = self.savedView self.n.move_cursor_to(view) eventName = util.RandomString() evt.Get().once(eventName, self.onEdited) log.debug("Trying to run: " + self.command) params = {"onDone": eventName } for k,v in self.params.items(): params[k] = v view.run_command(self.command, params) def Run(self): agenda = FindMappedView(self.view) if(agenda): self.viewName = agenda.name row, col = self.view.curRowCol() self.row = row n, f = agenda.At(row,col) if(f): if(n): self.n = n self.f = f self.savedView = get_view_for_silent_edit_file(f) # Give time for the document to be opened. sublime.set_timeout_async(lambda: self.onLoaded(), 200) else: log.warning("COULD NOT LOCATE AGENDA ROW") # ================================================================================ class CalendarViewRegistry: def __init__(self): self.KnownViews = {} self.AddView("Calendar", CalendarView) self.AddView("Day", AgendaView) self.AddView("Blocked Projects", BlockedProjectsView) self.AddView("Next Tasks", NextTasksProjectsView) self.AddView("Loose Tasks", LooseTasksView) self.AddView("Has Status", HasStatusView) self.AddView("Todos", TodoView) self.AddView("Notes", NoteView) self.AddView("Meetings", MeetingView) self.AddView("Phone", PhoneView) self.AddView("Week", WeekView) self.AddView("Done", DoneTasksView) self.AddView("Clocked", ClockedView) self.AddView("Projects", ProjectsView) self.AddView("Not Blocked Projects", NotBlockedProjectsView) def AddView(self,name,cls): self.KnownViews[name] = cls # ViewName: : def ParseArgs(self, n ): tokens = n.split(':') name = tokens[0].strip() args = {} i = 1 while(i < len(tokens)): p = tokens[i].strip() if(len(p) > 0): idx = p.find(' ') if(idx > 0): pname = p[:idx].strip() pval = p[idx:].strip() args[pname] = pval #print(pname + " -> " + pval) else: args[p] = True i += 1 return (name, args) def CreateCompositeView(self,views,name="Agenda"): vlist = [] for v in views: n, args = self.ParseArgs(v) vv = None if(args == None): vv = self.KnownViews[n](n, False) else: vv = self.KnownViews[n](n, False, **args) if(vv): vlist.append(vv) if len(vlist) == 1: vlist[0].name = name + " [" + vlist[0].name + "]" cview = CompositeView(name, vlist) cview.view.set_name(name) ViewMappings[cview.view.name()] = cview return cview viewRegistry = CalendarViewRegistry() # ================================================================================ class OrgAgendaCustomViewCommand(sublime_plugin.TextCommand): def onDone(self, edit, agenda, onDone, pos): agenda.DoRenderView(edit) if pos: agenda.RestoreCursor(pos) log.info("Custom view refreshed") evt.EmitIf(onDone) def run(self, edit, toShow="Default", onDone=None, draw=False, pos=None): if draw: agenda = FindMappedView(self.view) self.onDone(edit, agenda, onDone, pos) return #if(self.view.name() == "Agenda"): pos = self.view.sel()[0].begin() ReloadAllUnsavedBuffers() views = sets.Get("AgendaCustomViews",{ "Default": ["Calendar", "Week", "Day", "Blocked Projects", "Next Tasks", "Loose Tasks"]}) views = views[toShow] nameOfShow = toShow if(toShow == "Default"): nameOfShow = "Agenda" agenda = viewRegistry.CreateCompositeView(views, nameOfShow) agenda.view.run_command("org_agenda_custom_view", {"draw": True, "onDone": onDone, "toShow": toShow, "pos": pos}) #agenda = CompositeView("Agenda", views) #agenda = AgendaView(AGENDA_VIEW) # ================================================================================ # TODO: This is a work in progress that only lists them right now. # The goal is add parameters for filtered todos and support # multiple calendar views in the end. I should probably # rename the command above so we know it is intended to directly # select a view rather than use a quick panel. # I would like to add: # 1. Vertical Week View (Org Style) # 2. Horizontal Week View (Calendar Style) # 3. Month View (Vim Style) # 4. Month View Quick Highlight (My Style) # 5. Various Filtered Todo lists. # 6. Try an HTML version of a todo? class OrgAgendaChooseCustomViewCommand(sublime_plugin.TextCommand): def on_done_st4(self,index,modifers): self.on_done(index) def on_done(self, index): if(index < 0): return key = self.keys[index] self.view.run_command("org_agenda_custom_view", { "toShow": key }) evt.EmitIf(self.onDone) def run(self, edit, onDone=None): self.onDone = onDone self.views = sets.Get("AgendaCustomViews",{ "Default": ["Calendar", "Day", "Blocked Projects", "Next Tasks", "Loose Tasks"]}) self.keys = list(self.views.keys()) if(int(sublime.version()) <= 4096): self.view.window().show_quick_panel(self.keys, self.on_done, -1, -1) else: self.view.window().show_quick_panel(self.keys, self.on_done_st4, -1, -1) # ================================================================================ # When the view filter changes we re-render the todo view. class OrgAgendaReRenderViewCommand(sublime_plugin.TextCommand): def run(self, edit): v = FindMappedView(self.view) if v != None: v.DoRenderView(edit, True) # ================================================================================ class OrgAgendaReOpenFilterViewCommand(sublime_plugin.TextCommand): def run(self, edit): v = FindMappedView(self.view) if v != None: v.OpenFilterView() # ================================================================================ # Change the TODO status of the node. class OrgAgendaChangeTodoCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view, "org_todo_change") self.ed.Run() # ================================================================================ class OrgAgendaChangePriorityCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view, "org_priority_change") self.ed.Run() # ================================================================================ class OrgAgendaClockInCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_clock_in") self.ed.Run() # ================================================================================ class OrgAgendaClockOutCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_clock_out") self.ed.Run() # ================================================================================ class OrgAgendaInsertTagCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_insert_tag") self.ed.Run() # ================================================================================ class OrgAgendaInsertEffortCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_insert_property", {"name": "EFFORT"}) self.ed.Run() # ================================================================================ class OrgAgendaAssignCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_insert_property", {"name": "ASSIGNED"}) self.ed.Run() # ================================================================================ class OrgAgendaIdCommand(sublime_plugin.TextCommand): def run(self, edit): self.ed = RunEditingCommandOnNode(self.view,"org_insert_property", {"name": "ID"}) self.ed.Run() # ================================================================================ # Goto the file but in a split (SPACE) class OrgAgendaGoToSplitCommand(sublime_plugin.TextCommand): def run(self, edit): agenda = FindMappedView(self.view) if(agenda): row, col = self.view.curRowCol() n, f = agenda.At(row,col) if(f): if(n): path = "{0}:{1}".format(f.filename,n.start_row + 1) newView = self.view.window().open_file(path, sublime.ENCODED_POSITION) move_file_other_group(self.view, newView) #sublime.set_timeout_async(lambda: move_file_other_group(self.view, newView), 100) else: log.warning("COULD NOT LOCATE AGENDA ROW") # ================================================================================ class OrgTagFilteredTodoViewInternalCommand(sublime_plugin.TextCommand): def run(self,edit,tags): # TODO: add filtering to this and name it nicely ReloadAllUnsavedBuffers() todo = TodoView(TODO_VIEW + " Filtered By: " + tags,tagfilter=tags) todo.DoRenderView(edit) # ================================================================================ class OrgTagFilteredTodoViewCommand(sublime_plugin.TextCommand): def run(self,edit): self.view.window().show_input_panel( "Tags:", "", self.showTodos, None, None) def showTodos(self, tags): if(not tags): return self.view.run_command('org_tag_filtered_todo_view_internal', {"tags": tags}) # ================================================================================ class OrgAgendaGotoNextDayCommand(sublime_plugin.TextCommand): def run(self, edit): agenda = FindMappedView(self.view) now = agenda.now now = now + datetime.timedelta(days=1) agenda.UpdateNow(now) agenda.Clear(edit) agenda.DoRenderView(edit) # ================================================================================ class OrgAgendaGotoPrevDayCommand(sublime_plugin.TextCommand): def run(self, edit): agenda = FindMappedView(self.view) now = agenda.now now = now + datetime.timedelta(days=-1) agenda.UpdateNow(now) agenda.Clear(edit) agenda.DoRenderView(edit) ================================================ FILE: orgagenda.sublime-color-scheme ================================================ { "name": "orgagenda", "variables": { "bgcol": "#272822", // Define variables here }, "globals": { "foreground": "#F8F8F2", "background": "var(bgcol)", "accent": "#ffffff", "selection": "#9D550F", "selectionBackground": "#000000", "selectionForeground": "#FF0000", "caret": "#FF55ff", "line_highlight": "#373730" }, "rules": [ { "scope": "orgagenda.header", "foreground": "#5b96f5", "font_style": "bold italic", }, { "scope": "orgagenda.dateheader", "foreground": "#5b96f5", "font_style": "bold italic underline", }, { "scope": "orgagenda.weekendheader", "foreground": "#ab96f5", "font_style": "bold italic underline", }, { "scope": "orgagenda.timeseparator", "foreground": "#7c7c7d", }, { "scope": "orgagenda.now", "foreground": "#a88cd4", "font_style": "bold italic", }, { "scope": "orgagenda.filename", "foreground": "#76b3ae", }, { "scope": "orgagenda.todo", "foreground": "#a63229", "font_style": "bold italic", }, { "scope": "orgagenda.doing", "foreground": "#d2a2e0", "font_style": "bold italic", }, { "scope": "orgagenda.blocked", "foreground": "#FF0000", "font_style": "bold italic", }, { "scope": "orgagenda.waiting", "foreground": "#ffff00", "font_style": "bold italic", }, { "scope": "orgagenda.cancelled", "foreground": "#bab9b8", "font_style": "italic", }, { "scope": "orgagenda.inprogress", "foreground": "#d2a2e0", "font_style": "bold italic", }, { "scope": "orgagenda.cleanup", "foreground": "#d2a2e0", "font_style": "bold italic", }, { "scope": "orgagenda.fixed", "foreground": "#d2a2e0", "font_style": "bold italic", }, { "scope": "orgagenda.flag", "foreground": "#f2a2e0", "font_style": "bold italic", }, { "scope": "orgagenda.next", "foreground": "#3fd9d7", "font_style": "bold italic", }, { // Hide the habit markup in the buffer "scope": "orgagenda.habit", "foreground": "var(bgcol)", }, { "scope": "orgagenda.habit.didit", "foreground": "#ffffff", "background": "#007700", }, { "scope": "orgagenda.habit.scheduled", "foreground": "#333300", "background": "#550000", }, { "scope": "orgagenda.habit.nothing", "foreground": "#000066", "background": "#000066", }, { // Hide the week markup in the buffer "scope": "orgagenda.week", "foreground": "var(bgcol)", }, { "scope": "orgagenda.week.something", "foreground": "#ffffff", "background": "#007700", }, { "scope": "orgagenda.week.today", "foreground": "#f89cf4", "font_style": "bold", }, { "scope": "orgagenda.week.active", "foreground": "#f8fc00", "font_style": "bold", }, { "scope": "orgagenda.week.activetoday", "foreground": "#f89cf4", "background": "#485c00", "font_style": "bold", }, { "scope": "orgagenda.week.empty", "foreground": "#333300", "background": "#333333", }, { "scope": "orgagenda.week.nothing", "foreground": "var(bgcol)", "background": "var(bgcol)", }, { "scope": "orgagenda.projecttitle", "foreground": "#a87932", "font_style": "bold italic", }, { "scope": "orgagenda.blockseparator", "foreground": "#4a4a37", "font_style": "bold italic", }, { "scope": "orgagenda.monthheader", "foreground": "#a87932", "font_style": "bold italic", }, // Week View Cycling Item Colors { "scope": "orgagenda.week.done.0", "foreground": "#4f4f4f", }, { "scope": "orgagenda.week.done.1", "foreground": "#666666", }, { "scope": "orgagenda.week.0", "foreground": "#550000", }, { "scope": "orgagenda.week.1", "foreground": "#007700", }, { "scope": "orgagenda.week.2", "foreground": "#770077", }, { "scope": "orgagenda.week.3", "foreground": "#0000ff", }, { "scope": "orgagenda.week.4", "foreground": "#999900", }, { "scope": "orgagenda.week.5", "foreground": "#007777", }, { "scope": "orgagenda.week.6", "foreground": "#aa5522", }, { "scope": "orgagenda.week.7", "foreground": "#cc99cc", }, { "scope": "orgagenda.week.8", "foreground": "#225522", }, { "scope": "orgagenda.week.9", "foreground": "#623456", }, { "scope": "orgagenda.week.normal", "foreground": "#ffffff", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.1", "background": "#623456", "foreground": "#623456", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.2", "background": "#007777", "foreground": "#007777", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.3", "background": "#999900", "foreground": "#999900", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.4", "background": "#007700", "foreground": "#007700", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.5", "background": "#aa5522", "foreground": "#aa5522", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.6", "background": "#f89cf4", "foreground": "#f89cf4", }, { // Hide the block markup in the buffer "scope": "orgagenda.block.7", "background": "#0000ee", "foreground": "#0000ee", }, ] } ================================================ FILE: orgagenda.sublime-settings ================================================ { // The color scheme to use for the agenda buffer "color_scheme": "Packages/OrgExtended/orgagenda.sublime-color-scheme", } ================================================ FILE: orgagenda.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: orgagenda file_extensions: - orgagenda scope: source.orgagenda version: 2 hidden: true contexts: main: # filename and line location - match: '(^[a-zA-Z0-9_]+:)' scope: string.quoted orgagenda.filename - match: '[0-9]+:[0-9]+(\.)+ (\-)+' scope: comment orgagenda.timeseparator - match: '(D:@)\d+-\d+-\d+' scope: region.yellowish orgmode.deadline.warning captures: 1: comment orgmode.preamble - match: '(D: )Overdue' scope: region.redish orgmode.deadline.overdue captures: 1: comment orgmode.preamble - match: '(D: )Due Today' scope: region.greenish orgmode.deadline.due captures: 1: comment orgmode.preamble - match: 'H\[' push: - meta_scope: orgmode.preamble orgagenda.habit - match: '[*]' scope: orgagenda.habit.didit - match: '[.]' scope: orgagenda.habit.scheduled - match: '[_]' scope: orgagenda.habit.nothing - match: '\]' pop: true # Today in week view - match: '^(#)([A-Za-z]+ *[0-9]+)' scope: orgagenda.week.today captures: 1: orgmode.preamble orgagenda.week.nothing 2: keyword orgagenda.week.today # Active day in week view - match: '^(&)([A-Za-z]+ *[0-9]+)' scope: orgagenda.week.active captures: 1: orgmode.preamble orgagenda.week.nothing 2: string.quoted orgagenda.week.active # Both day in week view - match: '^(@)([A-Za-z]+ *[0-9]+)' scope: orgagenda.week.activetoday captures: 1: orgmode.preamble orgagenda.week.nothing 2: constant.numeric orgagenda.week.activetoday - match: 'W\[' push: - meta_scope: orgmode.preamble orgagenda.week - match: '[a-zA-Z0-9 ]' scope: variable.parameter orgagenda.week.normal - match: '[.]' scope: orgagenda.week.empty - match: '[_]' scope: orgmode.preamble orgagenda.week.nothing - match: '\]' pop: true - match: '((Su)|(Mo)|(Tu)|(We)|(Th)|(Fr)|(Sa)) ' scope: orgagenda.header captures: 2: constant.numeric orgagenda.weekendheader 3: keyword orgagenda.dateheader 4: keyword orgagenda.dateheader 5: keyword orgagenda.dateheader 6: keyword orgagenda.dateheader 7: keyword orgagenda.dateheader 8: constant.numeric orgagenda.weekendheader - match: '^[a-zA-Z][^=>:]+$' scope: keyword orgagenda.header # Datetime - match: '(\d{4,4}-\d{2,2}-\d{2,2} \d{2,2}:\d{2,2}:\d{2,2})' scope: markup.italic orgagenda.datetime - match: '^\s*now =>.*' scope: variable.parameter orgagenda.now - match: '(DONE)' scope: orgmode.state.done orgagenda.done - match: '(TODO)' scope: orgmode.state.todo orgagenda.todo - match: '(DOING)' scope: orgmode.state.doing orgagenda.doing - match: '(BLOCKED)' scope: orgmode.state.blocked orgagenda.blocked - match: '(WAITING)' scope: orgmode.state.waiting orgagenda.waiting - match: '(CANCELLED)' scope: orgmode.state.cancelled orgagenda.cancelled - match: '(IN-PROGRESS)' scope: orgmode.state.inprogress orgagenda.inprogress - match: '(CLEANUP)' scope: orgmode.state.cleanup orgagenda.cleanup - match: '(FIXED)' scope: orgmode.state.fixed orgagenda.fixed - match: '(FLAG)' scope: orgmode.state.flag orgagenda.flag - match: '(NEXT)' scope: orgmode.state.next orgagenda.next - match: '\s+-------\s+.*' scope: comment orgagenda.projecttitle - match: '^=====+' scope: comment orgagenda.blockseparator - match: '(January|February|March|April|May|June|July|August|September|October|November|December)\s*([0-9]+)' scope: constant.numeric orgagenda.monthheader - match: 'B\[' scope: orgmode.preamble orgagenda.week.nothing push: - meta_scope: orgagenda.block - match: '[\$]' scope: keyword orgagenda.block.1 - match: '[\@]' scope: constant.numeric orgagenda.block.2 - match: '[!]' scope: string orgagenda.block.3 - match: '[#]' scope: variable.parameter orgagenda.block.4 - match: '[%]' scope: entity.name.class orgagenda.block.5 - match: '[\^]' scope: entity.name.function orgagenda.block.6 - match: '[&]' scope: source orgagenda.block.7 - match: '\]' scope: orgmode.preamble orgagenda.week.nothing pop: true - match: '^== \[.*\] ==$' scope: keyword orgagenda.header orgagenda.projecttitle ================================================ FILE: orgbuiltinresources.py ================================================ import json import sublime import sublime_plugin def sortMessages(x): r = x xs = x.split('.') if(len(xs) <= 1): return 0 m = 1 c = 0 for i in range(len(xs)-1,-1,-1): x = xs[i] c = c+(int(x)*m) m *= 100 return c # =================================================================================== class OrgBuildDevDocsCommand(sublime_plugin.TextCommand): """Show the current worklog to the user""" def run(self, edit): view = sublime.active_window().new_file() view.set_syntax_file("Packages/OrgExtended/OrgExtended.sublime-syntax") messData = sublime.load_resource("Packages/OrgExtended/messages.json") msgs = json.loads(messData) ks = msgs.keys() ks = list(ks) ks = sorted(ks, key=sortMessages, reverse=True) for n in ks: name = n + ".org" pdata = None try: pdata = sublime.load_resource("Packages/OrgExtended/messages/" + name) except: pass if(not pdata): continue pdata = pdata.replace("\r","") view.insert(edit,view.size(),"\n" + pdata + "\n") pass # =================================================================================== class OrgShowTestfileCommand(sublime_plugin.TextCommand): """Show an org testfile to help users get started""" def run(self, edit): view = sublime.active_window().new_file() view.set_syntax_file("Packages/OrgExtended/OrgExtended.sublime-syntax") data = sublime.load_resource("Packages/OrgExtended/tests/testfile.org") data = data.replace("\r","") view.insert(edit,view.size(),"\n" + data + "\n") view.run_command("save") # =================================================================================== class OrgShowTableTestsCommand(sublime_plugin.TextCommand): """Show the org extended table unit tests to help users get started""" def run(self, edit): view = sublime.active_window().new_file() view.set_syntax_file("Packages/OrgExtended/OrgExtended.sublime-syntax") data = sublime.load_resource("Packages/OrgExtended/tests/tableunittests.org") data = data.replace("\r","") view.insert(edit,view.size(),"\n" + data + "\n") view.run_command("save") # =================================================================================== class OrgShowSourceBlockTestsCommand(sublime_plugin.TextCommand): """Show the org extended babel unit tests to help users get started""" def run(self, edit): view = sublime.active_window().new_file() view.set_syntax_file("Packages/OrgExtended/OrgExtended.sublime-syntax") data = sublime.load_resource("Packages/OrgExtended/tests/sourceunittests.org") data = data.replace("\r","") view.insert(edit,view.size(),"\n" + data + "\n") view.run_command("save") ================================================ FILE: orgcapture.py ================================================ import sublime import sublime_plugin import datetime import re import os import OrgExtended.orgparse.loader as loader import OrgExtended.orgparse.node as node import OrgExtended.orgutil.template as templateEngine import OrgExtended.orgparse.date as orgdate import OrgExtended.orgextension as ext import OrgExtended.orgclocking as clk import logging import OrgExtended.orgdb as db import OrgExtended.asettings as sets import OrgExtended.orgproperties as props import OrgExtended.pymitter as evt import OrgExtended.orgdaypage as daypage log = logging.getLogger(__name__) captureBufferName = "*capture*" lastHeader = None def GetViewById(id): win = sublime.active_window() for v in win.views(): if (v.id() == id): return v return None def GetDict(): tempDict = { 'refile': sets.Get('refile', ''), 'daypage': daypage.dayPageGetName(daypage.dayPageGetToday()), } return tempDict def GetCaptureFile(view, template, target): # temp = templateEngine.TemplateFormatter(sets.Get) filename = templateEngine.ExpandTemplate(view, target[1], GetDict(), sets.Get)[0] return filename def GetCaptureFileAndParam(view, template, target): # temp = templateEngine.TemplateFormatter(sets.Get) tempDict = GetDict() filename = templateEngine.ExpandTemplate(view, target[1], tempDict, sets.Get)[0] headline = None if (len(target) > 2): headline = templateEngine.ExpandTemplate(view, target[2], tempDict, sets.Get)[0] return (filename, headline) def FindNodeByPath(n, target, idx): if (idx >= len(target)): return n for c in n.children: if (c.heading == target[idx]): return FindNodeByPath(c, target, idx + 1) return None def GetCapturePath(view, template): target = ['file', '{refile}'] if 'target' in template: target = template['target'] filename = None file = None at = None toinsert = "" if ('file' in target[0]): filename = GetCaptureFile(view, template, target) if ('file+headline' in target[0]): filename, headline = GetCaptureFileAndParam(view, template, target) file = db.Get().LoadNew(filename) if (file and headline): at = file.FindOrCreateNode(headline) if (at): at = at.local_end_row elif ('file+regexp' in target[0]): filename, reg = GetCaptureFileAndParam(view, template, target) file = db.Get().LoadNew(filename) if (file and reg): r = re.compile(reg) row = 0 for n in file.org: for line in n._lines: m = r.search(line) if (m): at = row break row += 1 elif ('file+olp+datetree' in target[0]): filename, reg = GetCaptureFileAndParam(view, template, target) file = db.Get().FindInfo(filename) n = FindNodeByPath(file.org, target, 2) if (not n): n = file.org # Now we assume this is a date tree. Default is per day. t = datetime.datetime.now() yearformat = t.strftime(GetProp(template, "year-format", "%Y")) monthformat = t.strftime(GetProp(template, "month-format", "%Y-%m %B")) dayformat = t.strftime(GetProp(template, "day-format", "%Y-%m-%d %A")) nyear = None nmonth = None nday = None prefix = "" if (n.level > 0): prefix = "*" * n.level for c in n.children: if (c.heading == yearformat): nyear = c break if (nyear is None): toinsert += "{prefix}* {yearformat}\n".format(prefix=prefix, yearformat=yearformat) else: n = nyear for c in nyear.children: if (c.heading == monthformat): nmonth = c break if (nmonth is None): toinsert += "{prefix}** {monthformat}\n".format(prefix=prefix, monthformat=monthformat) else: n = nmonth for c in nmonth.children: if (c.heading == dayformat): nday = c break if (nday is None): toinsert += "{prefix}*** {dayformat}\n".format(prefix=prefix, dayformat=dayformat) else: n = nday if (n and toinsert == ""): at = n.local_end_row else: at = n.end_row elif ('file+olp' in target[0]): filename, reg = GetCaptureFileAndParam(view, template, target) file = db.Get().LoadNew(filename) n = FindNodeByPath(file.org, target, 2) if (n): at = n.local_end_row elif ('id' == target[0]): file, at = db.Get().FindByCustomId(target[1]) if (file is None): log.error("Could not find id: " + target[1]) return filename = file.filename elif ('clock' == target[0]): if (not clk.ClockManager.ClockRunning()): log.debug("ERROR: clock is not running!") raise "ERROR: clock is not running" filename = clk.ClockManager.GetActiveClockFile() at = clk.ClockManager.GetActiveClockAt() # Try to create my capture file if I can try: # Ensure the directory exists first dirName = os.path.dirname(os.path.abspath(filename)) if (not os.path.exists(dirName)): os.makedirs(dirName, exist_ok=True) if (not os.path.isfile(str(filename))): with open(filename, "w", encoding=sets. Get("captureWriteFormat", "utf-8")) as fp: fp.write("#+FILETAGS: :refile:\n") except Exception as e: log.error("@@@@@@@@@@@@\nFailed to create capture file: " + str(filename) + "\n" + str(e)) # Now make sure that file is loaded in the DB # it might not be in my org path if (file is None): file = db.Get().LoadNew(filename) else: file = db.Get().FindInfo(filename) if (not at and file): at = file.org.start_row return (target, filename, file, at, toinsert) # This is a bit hokey. We track the last header so # if you change the header we can still find it # in your target file. Every time you swap your # mouse away from the capture window we auto save # the capture to your target location. # TODO: Add more target locations than your refile file. def onDeactivated(view): global captureBufferName global lastHeader if (view.name() == captureBufferName): tempIndex = view.settings().get('cap_index') templates = sets.Get("captureTemplates", []) template = templates[tempIndex] # outpath, outfile = GetCaptureOutput() # print('template index was: ' + str(tempIndex)) target, capturePath, captureFile, at, toinsert = GetCapturePath(GetViewById(view.settings().get('cap_view')), template) # refilePath = sets.Get("refile","UNKNOWN") # refile = load(refilePath) captureFileRoot = None if (captureFile is not None): captureFileRoot = captureFile.org bufferContentsToInsert = view.substr(sublime.Region(0, view.size())) if not bufferContentsToInsert.endswith('\n'): bufferContentsToInsert += "\n" didInsert = False # Get a capture node captureNode = loader.loads(bufferContentsToInsert) # if we moused out of the window we might be replacing # ourselves again. if (lastHeader is None): lastHeader = str(captureNode[1].heading) # We may haved moved around in the capture file # so find the old heading. for heading in captureFileRoot: if (type(heading) is node.OrgRootNode): continue if str(heading.heading) == lastHeader: # log.debug("REPLACING: " + str(heading.heading)) heading.replace_node(captureNode[1]) didInsert = True continue if (not didInsert): insertAt = captureFileRoot inserted = captureNode[1] if (at is not None and at > 0): # This does not work? its a node not a file insertAt = captureFile.At(at) insertAt.insert_child(inserted) f = open(capturePath, "w+", encoding=sets.Get("captureWriteFormat", "utf-8")) # reauthor the ENTIRE file. # This can get expensive! for item in captureFileRoot: f.write(str(item)) f.close() lastHeader = str(captureNode[1].heading) log.debug("***************>>>>> [" + view.name() + "] is no more") # Respond to panel events. If the panel is hidden we stop # tracking the last header. def onPostWindowCommand(window, cmd, args): if cmd == "hide_panel": global lastHeader # This stops the capture refiling # From finding an entry across capture # window openings lastHeader = None class OrgCopyCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifers): self.on_done(index) def on_done(self, index): file, fileIndex = db.Get().FindFileInfoByAllHeadingsIndex(index) node = db.Get().AtInView(self.view) if (fileIndex is not None): # print(str(file.key)) file.org[fileIndex].insert_child(node) file.Save() else: log.error("Failed to copy, fileindex not found") def run(self, edit): self.headings = db.Get().AllHeadingsWContext(self.view) if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(self.headings, self.on_done, -1, -1) else: self.view.window().show_quick_panel(self.headings, self.on_done_st4, -1, -1) class OrgOpenRefileCommand(sublime_plugin.TextCommand): def run(self, edit): refile = sets.Get("refile", None) log.debug("REFILE: ", refile) if (refile): self.view.window().open_file(refile) else: log.error("Could not find refile file, have you set it in your config?") # Archiving will push the current item to an archive file (with some tags etc) class OrgArchiveSubtreeCommand(sublime_plugin.TextCommand): def close_tempView(self): self.tempView.run_command("close") def finish_archive_on_loaded(self): while (self.tempView. is_loading()): sublime.set_timeout_async(lambda: self.finish_archive_on_loaded(), 100) node = self.file.At(self.result.start_row) # :ARCHIVE_TIME: 2017-11-30 Thu 18:15 # :ARCHIVE_FILE: ~/notes/inxile/worklog.org # :ARCHIVE_OLPATH: Daily # :ARCHIVE_CATEGORY: InXile # :ARCHIVE_ITAGS: InXile props.UpdateProperty(self.tempView, node, "ARCHIVE_TIME", datetime.datetime.now().strftime("%Y-%m-%d %a %H:%M")) props.UpdateProperty(self.tempView, node, "ARCHIVE_FILE", self.view.file_name()) self.tempView.run_command("save") sublime.set_timeout_async(lambda: self.close_tempView(), 1000) # Now remove the old node self.sourceNode.remove_node() fromFile = db.Get().FindInfo(self.view) fromFile.Save() fromFile.Reload() def run(self, edit, onDone=None): globalArchive = sets.Get("archive", "%s_archive::") node = db.Get().AtInView(self.view) archive = node.archive(globalArchive) if (archive is None or archive.strip() == ""): node = db.Get().AtInView(self.view) node.add_tag("ARCHIVE") file = db.Get().FindInfo(self.view) file.Save() print(str(node)) return # Set the root to empty if not provided if ('::' not in archive): archive = archive + "::" (fileTemplate, headingTarget) = archive.split('::') if ('%' in fileTemplate): filename = fileTemplate % (self.view.file_name()) else: filename = fileTemplate log.debug("ARCHIVE FILE: " + filename) log.debug("ARCHIVE HEADING: " + headingTarget) # Ensure the file actually exists. if (not os.path.dirname(filename).strip() == ''): os.makedirs(os.path.dirname(filename), exist_ok=True) # Okay the file is probably a local path # Get the full path from our file. else: localDirname = os.path.dirname(self.view.file_name()) if ('/' not in filename and '\\' not in filename): filename = os.path.join(localDirname, filename) with open(filename, "a", encoding=sets.Get("captureWriteFormat", "utf-8")) as f: f.write("") log.debug(" Archive file created...") # Okay now open the file. file = db.Get().FindInfo(filename) sourceNode = db.Get().AtInView(self.view) if (sourceNode is not None): log.debug("Find or create: " + headingTarget) targetNode = file.FindOrCreateNode(headingTarget) if (targetNode is None): targetNode = file.Root() self.result = targetNode.insert_child(sourceNode) self.result.update_property("ARCHIVE_TIME", datetime.datetime.now().strftime("%Y-%m-%d %a %H:%M")) self.result.update_property("ARCHIVE_FILE", self.view.file_name()) for n in file.org[1:]: print(n.full_heading) else: log.debug("Inserting heading at: " + targetNode.heading) log.debug("Inserting: " + sourceNode.heading) self.result = targetNode.insert_child(sourceNode) self.result.update_property("ARCHIVE_TIME", datetime.datetime.now().strftime("%Y-%m-%d %a %H:%M")) self.result.update_property("ARCHIVE_FILE", self.view.file_name()) for n in file.org[1:]: print(n.full_heading) log.debug("Saving the source file") file.Save() file.Reload() sourceNode.remove_node() fromFile = db.Get().FindInfo(self.view) fromFile.Save() fromFile.Reload() # self.tempView = self.view.window().open_file(file.filename, sublime.ENCODED_POSITION) # self.file = file # self.sourceNode = sourceNode # sublime.set_timeout_async(lambda: self.finish_archive_on_loaded(), 1000) else: log.error("Failed to archive subtree! Could not find source Node") evt.EmitIf(onDone) class OrgArchiveAllDoneCommand(sublime_plugin.TextCommand): def onDone(self): self.view.run_command("org_archive_all_done") def run(self, edit): file = db.Get().Find(self.view) if len(file) > 1: for n in file[1:]: if n.todo == "DONE": self.view.sel().clear() sp = self.view.text_point(n.start_row,0) self.view.sel().add(sp) self.view.run_command("org_archive_subtree", {"onDone": evt.Make(self.onDone)}) return def RefileCurNode(view, file, nodeIndex): (curRow, curCol) = view.curRowCol() node = db.Get().At(view, curRow) if (node is None): log.error("COULD NOT REFILE: Node at line " + str(curRow) + " not found") return if (nodeIndex is None): log.error("Could not refile node index is out of bounds") return log.debug("Inserting child into: " + str(nodeIndex) + " vs " + str(len(file.org)) + " in file: " + file.filename) fromFile = db.Get().FindInfo(view) file.org[nodeIndex].insert_child(node) node.remove_node() # Have to save down here in case # file and fromFile are the same! file.Save() file.Reload() fromFile.Save() fromFile.Reload() # This refile gives you a list of all headings to make it quicker to jump to # "That heading" This one is bound to R for really quick refiling. class OrgRefileCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifiers): self.on_done(index) def on_done(self, index): if (index < 0): return file, fileIndex = db.Get().FindFileInfoByAllHeadingsIndex(index) RefileCurNode(self.view, file, fileIndex) def run(self, edit): self.headings = db.Get().AllHeadingsWContext(self.view) if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(self.headings, self.on_done, -1, -1) else: self.view.window().show_quick_panel(self.headings, self.on_done_st4, -1, -1) # This refile, files to the end of the file. class OrgRefileToFileCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifiers): self.on_done(index) def on_done(self, index): if (index < 0): return file = db.Get().FindFileByIndex(index) fileIndex = 0 RefileCurNode(self.view, file, fileIndex) def run(self, edit): self.headings = db.Get().AllFiles(self.view) if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(self.headings, self.on_done, -1, -1) else: self.view.window().show_quick_panel(self.headings, self.on_done_st4, -1, -1) # This refile version takes a filename prompt first # then it shows the headings in the file. class OrgRefileToFileAndHeadlineCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifiers): self.on_done(index) def on_done(self, index): if (index < 0): return self.file = db.Get().FindFileByIndex(index) self.headings = db.Get().AllHeadingsForFile(self.file) if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(self.headings, self.on_done_v2, -1, -1) else: self.view.window().show_quick_panel(self.headings, self.on_done_st4_v2, -1, -1) def on_done_st4_v2(self, index, modifiers): self.on_done_v2(index) def on_done_v2(self, index): if (index < 0): return RefileCurNode(self.view, self.file, index + 1) pass def run(self, edit): headings = db.Get().AllFiles(self.view) if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(headings, self.on_done, -1, -1) else: self.view.window().show_quick_panel(headings, self.on_done_st4, -1, -1) class OrgCaptureBaseCommand(sublime_plugin.TextCommand): def on_done(self, index): pass def on_done_base_st3(self, index): if (index < 0): return self.templates = sets.Get("captureTemplates", []) self.on_done(index) def on_done_base_st4(self, index, modifiers): self.on_done_base_st3(index) def run(self, edit): templates = sets.Get("captureTemplates", []) temps = [] for temp in templates: log.debug("TEMPLATE: ", temp) temps.append(temp['name']) if (int(sublime.version()) >= 4096): self.view.window().show_quick_panel(temps, self.on_done_base_st4, -1, -1) else: self.view.window().show_quick_panel(temps, self.on_done_base_st3, -1, -1) def IsType(val, template): return 'type' in template and template['type'].strip() == val def GetProp(template, name, defaultVal=None): if ('properties' in template): props = template['properties'] if (isinstance(props, dict)): if (name in props): return props[name] return defaultVal # Capture some text into our refile org file class OrgCaptureCommand(OrgCaptureBaseCommand): def insert_template(self, template, panel): # template = templates[index]['template'] startPos = -1 template, startPos = templateEngine.ExpandTemplate(self.view, template) panel.run_command("insert", {"characters": template}) if (startPos >= 0): startPos = sublime.Region(startPos) else: startPos = panel.sel()[0] return startPos def cleanup_capture_panel(self): global captureBufferName if (not self.openas): self.panel.set_syntax_file('Packages/OrgExtended/OrgExtended.sublime-syntax') self.panel.set_name(captureBufferName) # In OpenAs mode we insert some pre-heading stars # Before inserting the snippet. This SHOULD get our # heading where it needs to be? def on_added_stars(self): self.pt = self.panel.text_point(self.insertRow, 0) linev = self.panel.line(self.pt) linetxt = self.panel.substr(linev) self.panel.sel().clear() self.panel.sel().add(linev.begin() + len(linetxt.rstrip())) self.insert_snippet(self.index) def find_end_of_thing(self, panel, insertAt, itemre): self.insertRow = insertAt.local_end_row self.pt = panel.text_point(insertAt.local_end_row, 0) # item_line_regex = re.compile(r'^(\s*)([-+])\s*[^\[]') have = False itemtype = '-' preprefix = " " * (insertAt.level + 1) for row in range(insertAt.start_row, insertAt.local_end_row + 1): pt = panel.text_point(row, 0) line = panel.substr(panel.line(pt)) m = itemre.search(line) if (m): preprefix = m.group(1) itemtype = m.group(2) have = True elif (have): self.insertRow = row self.pt = pt break return (preprefix, itemtype) def on_panel_ready(self, index, openas, panel, cnt=0): self.panel = panel global captureBufferName captureBufferName = sets.Get("captureBufferName", captureBufferName) window = self.view.window() template = self.templates[index] target, capturePath, captureFile, at, toinsert = GetCapturePath(self.view, template) if (panel.is_loading()): sublime.set_timeout_async(lambda: self.on_panel_ready(index, openas, panel), 100) return if (toinsert != "" and cnt == 0): pt = panel.text_point(at, 0) linev = panel.line(pt) linetxt = panel.substr(linev) if ((linetxt and not linetxt.strip() == "") or at == 0 or panel.lastRow() == at): toinsert = "\n" + toinsert pt = linev.end() else: pt = linev.begin() panel.Insert(pt, toinsert, evt.Make(lambda: self.on_panel_ready(index, openas, panel, cnt + 1))) return startPos = -1 # Try to store the capture index panel.settings().set('cap_index', index) panel.settings().set('cap_view', self.view.id()) self.openas = openas if ((IsType('item', template) or IsType('checkitem', template) or IsType('plain', template) or IsType('table-line', template)) and 'snippet' not in template): template['snippet'] = 'plain_template' if ('template' in template): del template['template'] if ('template' in template): startPos = self.insert_template(template['template'], panel) window.run_command('show_panel', args={'panel': 'output.orgcapture'}) panel.sel().clear() panel.sel().add(startPos) window.focus_view(panel) self.cleanup_capture_panel() elif ('snippet' in template): self.level = 0 self.pt = None prefix = "" preprefix = "" itemtype = '-' if (self.openas): insertAt = captureFile.At(at) if (IsType('plain', template)): self.pt = panel.text_point(insertAt.local_end_row, 0) self.insertRow = insertAt.local_end_row elif (IsType('checkitem', template)): preprefix, itemtype = self.find_end_of_thing(panel, insertAt, re.compile(r'^(\s*)([-+])\s*(\[[xX\- ]\])\s+')) elif (IsType('item', template)): preprefix, itemtype = self.find_end_of_thing(panel, insertAt, re.compile(r'^(\s*)([-+])\s*[^\[]')) elif (IsType('table-line', template)): preprefix, itemtype = self.find_end_of_thing(panel, insertAt, re.compile(r'^(\s*)([|])')) else: self.pt = panel.text_point(insertAt.end_row, 0) self.insertRow = insertAt.end_row linev = panel.line(self.pt) linetxt = panel.substr(linev) if ((linetxt and not linetxt.strip() == "") or at == 0 or (insertAt and panel.lastRow() == insertAt.end_row)): prefix = "\n" self.pt = linev.end() self.insertRow += 1 else: self.pt = linev.begin() panel.sel().clear() panel.sel().add(self.pt) self.level = insertAt.level else: window.run_command('show_panel', args={'panel': 'output.orgcapture'}) if (self.openas and self.level > 0): self.index = index self.panel = panel if (IsType('plain', template)): self.panel.Insert(self.pt, prefix + (" " * (self.level + 1)), evt.Make(self.on_added_stars)) elif (IsType('item', template)): self.panel.Insert(self.pt, prefix + preprefix + itemtype + " ", evt.Make(self.on_added_stars)) elif (IsType('checkitem', template)): self.panel.Insert(self.pt, prefix + preprefix + itemtype + " [ ] ", evt.Make(self.on_added_stars)) elif (IsType('table-line', template)): self.panel.Insert(self.pt, prefix + preprefix + itemtype, evt.Make(self.on_added_stars)) else: self.panel.Insert(self.pt, prefix + ("*" * self.level), evt.Make(self.on_added_stars)) else: if (IsType('plain', template)): self.panel.Insert(self.pt, prefix, evt.Make(self.on_added_stars)) elif (prefix != ""): self.index = index self.panel = panel self.panel.Insert(self.pt, prefix, evt.Make(self.on_added_stars)) else: self.insert_snippet(index) def insert_snippet(self, index): window = self.view.window() template = self.templates[index] ai = sublime.active_window().active_view().settings().get('auto_indent') self.panel.settings().set('auto_indent', False) snippet = template['snippet'] snipName = ext.find_extension_file('orgsnippets', snippet, '.sublime-snippet') window.focus_view(self.panel) # panel.meta_info("shellVariables", 0)[0]['TM_EMAIL'] = "Trying to set email value" self.panel.run_command('_enter_insert_mode', {"count": 1, "mode": "mode_internal_normal"}) now = datetime.datetime.now() inow = orgdate.OrgDate.format_date(now, False) anow = orgdate.OrgDate.format_date(now, True) # "Packages/OrgExtended/orgsnippets/"+snippet+".sublime-snippet" # OTHER VARIABLES: # TM_FULLNAME - Users full name # TM_FILENAME - File name of the file being edited # TM_CURRENT_WORD - Word under cursor when snippet was triggered # TM_SELECTED_TEXT - Selected text when snippet was triggered # TM_CURRENT_LINE - Line of snippet when snippet was triggered self.panel.run_command("insert_snippet", { "name": snipName, "ORG_INACTIVE_DATE": inow, "ORG_ACTIVE_DATE": anow, "ORG_DATE": str(datetime.date.today()), "ORG_TIME": datetime.datetime.now().strftime("%H:%M:%S"), "ORG_CLIPBOARD": sublime.get_clipboard(), "ORG_SELECTION": self.view.substr(self.view.sel()[0]), "ORG_LINENUM": str(self.view.curRow()), "ORG_FILENAME": self.view.file_name() }) sublime.active_window().active_view().settings().set('auto_indent', ai) self.cleanup_capture_panel() def on_done_st4(self, index, modifiers): self.on_done(index) def on_done(self, index): if (index < 0): return global captureBufferName captureBufferName = sets.Get("captureBufferName", captureBufferName) window = self.view.window() template = self.templates[index] target, capturePath, captureFile, at, toinsert = GetCapturePath(self.view, template) openas = False if ('openas' in template and 'direct' == template['openas']): panel = window.open_file(capturePath) openas = True else: panel = window.create_output_panel("orgcapture") self.on_panel_ready(index, openas, panel) ================================================ FILE: orgcheckbox.py ================================================ import sublime import sublime_plugin import re import logging import OrgExtended.orgdb as db import OrgExtended.asettings as sets log = logging.getLogger(__name__) # Stolen from the original orgmode class CheckState: Unchecked, Checked, Indeterminate, Error = range(1, 5) indent_regex = re.compile(r'^(\s*).*$') summary_regex = re.compile(r'(\[\d*[/%]\d*\])') checkbox_regex = re.compile(r'(\[[xX\- ]\])') checkbox_line_regex = re.compile(r'\s*[-+]?\s*(\[[xX\- ]\])\s+') unordered_line_regex = re.compile(r'\s*[-+]\s+') # Extract the indent of this checkbox. # RETURNS: a string with the indent of this line. def get_indent(view, content): if isinstance(content, sublime.Region): content = view.substr(content) match = indent_regex.match(content) if (match): return match.group(1) else: log.debug("Could not match indent: " + content) return "" RE_HEADING = re.compile('^[*]+ ') def check_type(line): if checkbox_regex.search(line): return "C" if unordered_line_regex.search(line): return "L" ls = line.strip() if len(ls) > 0 and ls[0] == "*": return "H" # Try to find the parent of a region (by indent) def find_parent(view, region): row, col = view.rowcol(region.begin()) content = view.substr(view.line(region)) indent = len(get_indent(view, content)) row -= 1 found = False # Look upward while row >= 0: point = view.text_point(row, 0) content = view.substr(view.line(point)) if len(content.strip()): if (RE_HEADING.search(content)): break cur_indent = len(get_indent(view, content)) if cur_indent < indent: found = True break row -= 1 if found: # return the parent we found. return view.line(view.text_point(row,0)) def find_heading(view, region): row, col = view.rowcol(region.begin()) row -= 1 found = False while row >= 0: point = view.text_point(row, 0) content = view.substr(view.line(point)) if len(content.strip()): if RE_HEADING.search(content) and get_summary(view, view.line(point)): found = True break row -= 1 if found: # return the heading we found. return view.line(view.text_point(row, 0)) def find_children(view, region, cre = checkbox_regex, includeSiblings=False, recursiveChildFind=False): row, col = view.rowcol(region.begin()) line = view.line(region) content = view.substr(line) # print content indent = get_indent(view, content) if(not indent): log.debug("Unable to locate indent for line: " + str(row)) indent = len(indent) # print repr(indent) row += 1 child_indent = None children = [] last_row, _ = view.rowcol(view.size()) check = None while row <= last_row: point = view.text_point(row, 0) line = view.line(point) content = view.substr(line) summary = get_summary(view, line) lc = content.lstrip() if lc.startswith("*") or lc.startswith('#'): break if cre.search(content): if check is None: check = check_type(content) cur_indent = len(get_indent(view, content)) # check for end of descendants if includeSiblings and cur_indent < indent: break elif not includeSiblings and cur_indent <= indent: break # only immediate children (and siblings) if(not recursiveChildFind): if child_indent is None: child_indent = cur_indent if cur_indent == child_indent: children.append(line) if(includeSiblings and cur_indent < child_indent): children.append(line) else: children.append(line) else: if check is not None: lineType = check_type(content) if check != "H" and lineType != check: break row += 1 return children def find_siblings(view, child, parent): row, col = view.rowcol(parent.begin()) parent_indent = get_indent(view, parent) child_indent = get_indent(view, child) siblings = [] row += 1 last_row, _ = view.rowcol(view.size()) while row <= last_row: # Don't go past end of document. line = view.text_point(row, 0) line = view.line(line) content = view.substr(line) # print content if len(content.strip()): cur_indent = get_indent(view, content) if len(cur_indent) <= len(parent_indent): break # Indent same as parent found! if len(cur_indent) == len(child_indent): siblings.append((line, content)) row += 1 return siblings def get_summary(view, line): row, _ = view.rowcol(line.begin()) content = view.substr(line) match = summary_regex.search(content) if not match: return None col_start, col_stop = match.span() return sublime.Region( view.text_point(row, col_start), view.text_point(row, col_stop), ) def get_checkbox(view, line): row, _ = view.rowcol(line.begin()) content = view.substr(line) # print content match = checkbox_regex.search(content) if not match: return None # checkbox = match.group(1) # print repr(checkbox) # print dir(match), match.start(), match.span() col_start, col_stop = match.span() return sublime.Region( view.text_point(row, col_start), view.text_point(row, col_stop), ) def get_check_state(view, line): if '[-]' in view.substr(line): return CheckState.Indeterminate if '[ ]' in view.substr(line): return CheckState.Unchecked if '[X]' in view.substr(line) or '[x]' in view.substr(line): return CheckState.Checked return CheckState.Error def get_check_char(view, check_state): if check_state == CheckState.Unchecked: return ' ' elif check_state == CheckState.Checked: return 'x' elif check_state == CheckState.Indeterminate: return '-' else: return 'E' def recalc_summary(view, region): recursive = sets.Get("checkboxSummaryRecursive",False) at = db.Get().AtInView(view) if(at): props = at.properties if(props and 'COOKIE_DATA' in props): cook = props['COOKIE_DATA'] if(cook and 'notrecursive' in cook): recursive = False elif(cook and 'recursive' in cook): recursive = True children = None children = find_children(view, region, checkbox_regex, False, recursive) if not len(children) > 0: return (0, 0) num_children = len(children) checked_children = len( [child for child in children if (get_check_state(view,child) == CheckState.Checked)]) # print ('checked_children: ' + str(checked_children) + ', num_children: ' + str(num_children)) return (num_children, checked_children) def update_line(view, edit, region, parent_update=True, children_update=False): #print ('update_line', self.view.rowcol(region.begin())[0]+1) (num_children, checked_children) = recalc_summary(view, region) # No children we don't have to update anything else. if num_children <= 0: return False # update region checkbox if checked_children == num_children: newstate = CheckState.Checked else: if checked_children != 0: newstate = CheckState.Indeterminate else: newstate = CheckState.Unchecked toggle_checkbox(view, edit, region, newstate) # update region summary update_summary(view, edit, region, checked_children, num_children) if children_update: children = find_children(view, region) for child in children: line = view.line(child) summary = get_summary(view, view.line(child)) if summary: return update_line(view, edit, line, parent_update=False, children_update=True) if parent_update: parent = find_parent(view, region) if parent: update_line(view, edit, parent) else: # ok, no parent, but may be there is heading with summary? heading = find_heading(view, region) if heading and get_summary(view, heading): update_line(view, edit, heading, parent_update=False) return True def update_summary(view, edit, region, checked_children, num_children): # print('update_summary', self.view.rowcol(region.begin())[0]+1) summary = get_summary(view, region) if not summary: return False # print('checked_children: ' + str(checked_children) + ', num_children: ' + str(num_children)) line = view.substr(summary) if("%" in line): view.replace(edit, summary, '[{0}%]'.format(int(checked_children/num_children*100))) else: view.replace(edit, summary, '[%d/%d]' % (checked_children, num_children)) def toggle_checkbox(view, edit, region, checked=None, recurse_up=False, recurse_down=False): # print 'toggle_checkbox', self.view.rowcol(region.begin())[0]+1 checkbox = get_checkbox(view, region) if not checkbox: return False if checked is None: check_state = get_check_state(view, region) if (check_state == CheckState.Unchecked) | (check_state == CheckState.Indeterminate): check_state = CheckState.Checked elif (check_state == CheckState.Checked): check_state = CheckState.Unchecked else: check_state = checked view.replace(edit, checkbox, '[%s]' % ( get_check_char(view, check_state))) if recurse_down: # all children should follow children = find_children(view, region) for child in children: toggle_checkbox(view, edit, child, check_state, recurse_down=True) if (get_summary(view, child)): update_line(view, edit, child, parent_update=False) if get_summary(view, region): (num_children, checked_children) = recalc_summary(view, region) update_summary(view, edit, region, checked_children, num_children) if recurse_up: # update parent parent = find_parent(view, region) if parent: update_line(view, edit, parent) else: # ok, no parent, but may be there is heading with summary? heading = find_heading(view, region) if heading and get_summary(view, heading): update_line(view, edit, heading, parent_update=False) def is_checkbox(view, sel): names = view.scope_name(sel.end()) return 'orgmode.checkbox' in names or 'orgmode.checkbox.checked' in names or 'orgmode.checkbox.blocked' in names def is_checkbox_line(view,sel=None): point = None if(sel == None): row = view.curRow() point = view.text_point(row, 0) else: point = sel.end() line = view.line(point) content = view.substr(line) return checkbox_line_regex.search(content) def find_all_summaries(view): return view.find_by_selector("orgmode.checkbox.summary") def recalculate_checkbox_summary(view, sel, edit): line = view.line(sel.begin()) update_line(view, edit, line) def recalculate_all_checkbox_summaries(view, edit): sums = find_all_summaries(view) for sel in sums: recalculate_checkbox_summary(view, sel, edit) cline_info_regex = re.compile(r'^(\s*)([-+0-9](\.)?)?.*$') class OrgInsertCheckboxCommand(sublime_plugin.TextCommand): def run(self, edit,insertHere=True): row = self.view.curRow() line = self.view.getLine(row) match = cline_info_regex.match(line) indent = match.group(1) start = match.group(2) if(start): indent = indent + start + " [ ] " reg = self.view.curLine() list_regex = re.compile(r'\s*(([-+]\s\[)|[^#*|+-])') children = find_children(self.view, reg, list_regex, not insertHere) if(children and len(children) > 0): reg = children[len(children) - 1] row,_ =self.view.rowcol(reg.begin()) self.view.insert(edit,reg.end(),"\n" + indent) # Move to end of line row = row + 1 pt = self.view.text_point(row,0) ln = self.view.line(pt) self.view.sel().clear() self.view.sel().add(ln.end()) uline_info_regex = re.compile(r'^(\s*)([-+]) .*$') def isUnorderedList(line): return uline_info_regex.match(line) RE_THING = re.compile(r'^\s*[+-](\s\[[ xX-]\])?\s(?P.*)$') RE_NOTHEADERS = re.compile(r'^\s*[\#|0-9]') def getListAtPointForSorting(view): parent = view.findParentByIndent(view.curLine(),RE_NOTHEADERS, RE_THING) if(None != parent): prow, _ = view.rowcol(parent.begin()) list_regex = re.compile(r'\s*(([-+]\s\[)|[^#*|+-])') children = find_children(view, parent, list_regex, True) sortby = view.getLine(prow) m = RE_THING.search(sortby) if(m): sortby = m.group('data') things = [[[prow,0],sortby]] for c in children: srow, _ = view.rowcol(c.begin()) if(len(things) > 0): things[len(things)-1][0][1] = srow sortby = view.getLine(srow) m = RE_THING.search(sortby) if(m): sortby = m.group('data') things.append([[srow,0],sortby]) if(len(things) > 0): srow, _ = view.rowcol(children[len(children)-1].end()) things[len(things)-1][0][1] = srow+1 return things return None def getListAtPoint(view,pt=None): if(pt): line = view.line(pt) else: line = view.curLine() parent = view.findParentByIndent(line,RE_NOTHEADERS, RE_THING) if(None != parent): prow, _ = view.rowcol(parent.begin()) list_regex = re.compile(r'\s*(([-+]\s\[)|[^#*|+-])') children = find_children(view, parent, list_regex, True) sortby = view.getLine(prow) m = RE_THING.search(sortby) if(m): sortby = m.group('data') things = [] lastAppend = False for c in children: srow, _ = view.rowcol(c.begin()) if(lastAppend and len(things) > 0): things[len(things)-1][0][1] = srow lastAppend = False sortby = view.getLine(srow) m = RE_THING.search(sortby) if(m): sortby = m.group('data') things.append([[srow,0],sortby]) lastAppend = True if(len(things) > 0): srow, _ = view.rowcol(children[len(children)-1].end()) things[len(things)-1][0][1] = srow+1 return things return None class OrgInsertUnorderedListCommand(sublime_plugin.TextCommand): def run(self, edit,insertHere=True): row = self.view.curRow() line = self.view.getLine(row) match = uline_info_regex.match(line) indent = match.group(1) start = match.group(2) if(start): indent = indent + start + " " reg = self.view.curLine() list_regex = re.compile(r'\s*([-+]|[^#*|])') children = find_children(self.view, reg, list_regex, not insertHere) if(children and len(children) > 0): reg = children[len(children) - 1] row,_ =self.view.rowcol(reg.begin()) self.view.insert(edit,reg.end(),"\n" + indent) # Move to end of line row = row + 1 pt = self.view.text_point(row,0) ln = self.view.line(pt) self.view.sel().clear() self.view.sel().add(ln.end()) cbsline_info_regex = re.compile(r'^(\s*)(.*)\[\s*[0-9]*/[0-9]\s*\]\s*$') class OrgInsertCheckboxSummaryCommand(sublime_plugin.TextCommand): def run(self, edit): row = self.view.curRow() line = self.view.getLine(row) match = cbsline_info_regex.match(line) if(not match): reg = self.view.curLine() self.view.insert(edit,reg.end()," [/] ") recalculate_all_checkbox_summaries(self.view, edit) class OrgToggleCheckboxCommand(sublime_plugin.TextCommand): def run(self, edit): view = self.view for sel in view.sel(): if(not is_checkbox_line(view, sel)): continue line = view.line(sel.end()) toggle_checkbox(view, edit, line, recurse_up=True, recurse_down=True) class OrgRecalcCheckboxSummaryCommand(sublime_plugin.TextCommand): def run(self, edit): view = self.view backup = [] for sel in view.sel(): if 'orgmode.checkbox.summary' not in view.scope_name(sel.end()): continue backup.append(sel) #summary = view.extract_scope(sel.end()) line = view.line(sel.end()) update_line(view, edit, line) view.sel().clear() for region in backup: view.sel().add(region) class OrgRecalcAllCheckboxSummariesCommand(sublime_plugin.TextCommand): def run(self, edit): recalculate_all_checkbox_summaries(self.view, edit) ================================================ FILE: orgclocking.py ================================================ import sublime import sublime_plugin import datetime import os # from OrgExtended.orgparse.sublimenode import * import logging import OrgExtended.orgdb as db import OrgExtended.asettings as sets import OrgExtended.orgproperties as props from OrgExtended.orgparse.node import * import copy import yaml import OrgExtended.pymitter as evt log = logging.getLogger(__name__) class ClockManager: Clock = None @staticmethod def ClockInRecord(file, onode, dt): # parentHeading = "" # if (onode.parent and type(onode.parent) != node.OrgRootNode): # parentHeading = onode.parent.heading ClockManager.Clock = { 'file': file.filename, 'start': dt, 'heading': onode.get_locator() } ClockManager.SaveClock() @staticmethod def ClockRunning(): return ClockManager.Clock is not None @staticmethod def FormatClock(now): return now.strftime("[%Y-%m-%d %a %H:%M]") @staticmethod def FormatDuration(d): hours = d.seconds / 3600 minutes = (d.seconds / 60) % 60 return "{0:02d}:{1:02d}".format(int(hours), int(minutes)) @staticmethod def ClockPath(): return os.path.join(sublime.packages_path(), "User", "OrgExtended_Clocks.yaml") @staticmethod def SaveClock(): f = open(ClockManager.ClockPath(), "w") yaml.dump(ClockManager.Clock, f) f.close() @staticmethod def LoadClock(): cpath = ClockManager.ClockPath() if (os.path.isfile(cpath)): stream = open(cpath, 'r') res = yaml.load(stream, Loader=yaml.SafeLoader) if res is not None and isinstance(res, dict): ClockManager.Clock = res else: ClockManager.Clock = None stream.close() @staticmethod def ClockIn(view): if (ClockManager.ClockRunning()): view.set_status("Clock", "CLOCK") ClockManager.ClockOut(view) # Handle clock already running node = db.Get().AtInView(view) if (node): file = db.Get().FindInfo(view) if (file): dt = datetime.datetime.now() ClockManager.ClockInRecord(file, node, dt) if (sets.Get("clockInPropertyBlock", False)): props.AddProperty(view, node, "CLOCK", ClockManager.FormatClock(dt) + "--") else: props.AddLogbook(view, node, "CLOCK:", ClockManager.FormatClock(dt) + "--") @staticmethod def UpdateClockStart(view): if (not ClockManager.ClockRunning()): log.error("Clock not running, nothing to update") return # Eventually we want to navigate to this node # rather than doing this. if ClockManager.Clock is not None: node = db.Get().FindNode(ClockManager.Clock["file"], ClockManager.Clock["heading"]) newStart = None if (node): tview = view.window().open_file(ClockManager.Clock["file"], sublime.ENCODED_POSITION) if (sets.Get("clockInPropertyBlock", False)): val = props.GetProperty(tview, node, "CLOCK") else: val = props.GetLogbook(tview, node, r"CLOCK:") if val: clock = OrgDateClock.from_str(val) if clock: newStart = clock.start if newStart: file = db.Get().FindInfo(ClockManager.Clock["file"]) ClockManager.ClockInRecord(file, node, newStart) @staticmethod def ClockOut(view): if (not ClockManager.ClockRunning()): return # Eventually we want to navigate to this node # rather than doing this. if ClockManager.Clock is not None: node = db.Get().FindNode(ClockManager.Clock["file"], ClockManager.Clock["heading"]) if (node): end = datetime.datetime.now() start = ClockManager.Clock["start"] duration = end - start # Should we keep clocking entries less than a minute? shouldKeep = sets.Get("clockingSubMinuteClocks", True) tview = view.window().open_file(ClockManager.Clock["file"], sublime.ENCODED_POSITION) if (not shouldKeep and duration.seconds < 60): if (sets.Get("clockInPropertyBlock", False)): props.RemoveProperty(tview, node, "CLOCK") else: props.RemoveLogbook(tview, node, r"CLOCK:") else: if (sets.Get("clockInPropertyBlock", False)): props.UpdateProperty(tview, node, "CLOCK", ClockManager.FormatClock(start) + "--" + ClockManager.FormatClock(end) + " => " + ClockManager.FormatDuration(duration)) else: props.UpdateLogbook(tview, node, "CLOCK:", ClockManager.FormatClock(start) + "--" + ClockManager.FormatClock(end) + " => " + ClockManager.FormatDuration(duration)) view.window().focus_view(view) tview.run_command("save") ClockManager.ClearClock() view.run_command("save") else: log.error("Failed to clock out, couldn't find node") @staticmethod def ClearClock(): ClockManager.Clock = None cpath = ClockManager.ClockPath() if (os.path.isfile(cpath)): os.remove(cpath) @staticmethod def GetActiveClockFile(): if (not ClockManager.ClockRunning()): return None return ClockManager.Clock["file"] if ClockManager.Clock is not None else None @staticmethod def GetActiveClockAt(): if (not ClockManager.ClockRunning()): return None if ClockManager.Clock is not None: node = db.Get().FindNode(ClockManager.Clock["file"], ClockManager.Clock["heading"]) if (node): return node.start_row # Load the clock cache. def Load(): ClockManager.LoadClock() # Clock in a task class OrgClockInCommand(sublime_plugin.TextCommand): def run(self, edit, onDone=None): ClockManager.LoadClock() ClockManager.ClockIn(self.view) evt.EmitIf(onDone) # Clock out a task class OrgClockOutCommand(sublime_plugin.TextCommand): def run(self, edit, onDone=None): ClockManager.LoadClock() ClockManager.ClockOut(self.view) evt.EmitIf(onDone) # Jump to an active clock class OrgJumpToClockCommand(sublime_plugin.TextCommand): def run(self, edit, onDone=None): ClockManager.LoadClock() at = ClockManager.GetActiveClockAt() filename = ClockManager.GetActiveClockFile() if at and filename: path = "{0}:{1}".format(filename, at + 1) self.view.window().open_file(path, sublime.ENCODED_POSITION) else: print("No active clock") evt.EmitIf(onDone) # Clear the currently running clock (if there is one) class OrgClearClockCommand(sublime_plugin.TextCommand): def run(self, edit): ClockManager.ClearClock() # Update the currently running command based on an open clock manual update class OrgUpdateClockCommand(sublime_plugin.TextCommand): def run(self, edit): ClockManager.UpdateClockStart(self.view) # Recalculate all the clock values in a node (Crtl-c Ctrl-c on a clock entry) class OrgRecalculateClockCommand(sublime_plugin.TextCommand): def run(self, edit): node = db.Get().AtInView(self.view) clockList = copy.copy(node.clock) log.debug(str(clockList)) log.debug(str(len(clockList))) if (sets.Get("clockInPropertyBlock", False)): props.RemoveAllInstances(self.view, node, "CLOCK") else: props.RemoveAllLogbookInstances(self.view, node, r"^\s*CLOCK:") log.debug(str(clockList)) log.debug(str(len(clockList))) for clock in clockList: # File is reloaded have to regrab node node = db.Get().At(self.view, node.start_row) if (sets.Get("clockInPropertyBlock", False)): props.AddProperty(self.view, node, "CLOCK", clock.format_clock_str()) else: props.AddLogbook(self.view, node, "CLOCK:", clock.format_clock_str()) ================================================ FILE: orgdateeditor.sublime-settings ================================================ { // The color scheme to use for the datepicker buffer "color_scheme": "Packages/OrgExtended/orgdatepicker.sublime-color-scheme", //"font_face": "Courier New", //"font_size": 15 } ================================================ FILE: orgdateeditor.sublime-syntax ================================================ %YAML1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: orgdateeditor file_extensions: - orgdateeditor scope: source.orgdateeditor version: 2 hidden: true contexts: main: # filename and line location - match: '(Mon|Tue|Wed|Thu|Fri)' scope: orgdatepicker.weekdayheader - match: '(Sat|Sun)' scope: orgdatepicker.weekendheader - match: '(January|February|March|April|May|June|July|August|September|October|November|December)\s*([0-9]+)' scope: orgdatepicker.monthheader - match: '[0-9][0-9]:[0-9][0-9]' scope: orgdatepicker.time ================================================ FILE: orgdatepicker.py ================================================ import calendar import sublime import sublime_plugin import datetime from OrgExtended.orgparse.date import * import OrgExtended.pymitter as evt import OrgExtended.asettings as sets import OrgExtended.orgutil.asciiclock as aclock import OrgExtended.orgduration as orgduration todayHighlight="orgagenda.block.1" def CreateUniqueViewNamed(name, mapped=None): # Close the view if it exists win = sublime.active_window() for view in win.views(): if view.name() == name: win.focus_view(view) win.run_command('close') win.run_command('new_file') view = win.active_view() view.set_name(name) # TODO: Change this. view.set_syntax_file("Packages/OrgExtended/orgdatepicker.sublime-syntax") #ViewMappings[view.name()] = mapped return view class DateView: def __init__(self, dayhighlight=None,firstDayIndex=0, timeView=False): self.months = [] self.columnsPerMonth = 30 # 7 * 3 = 21 + 9 self.columnsInDay = 2 self.columnsPerDay = self.columnsInDay + 1 # 2 digits plus a space self.midmonth = datetime.datetime.now().month self.monthdata = None self.headingLines = 2 self.output = None self.cdate = OrgDateFreeFloating(datetime.datetime.now()) self.startrow = 0 self.endrow = 7 self.dayhighlight = dayhighlight self.firstdayindex = firstDayIndex self.timeView = timeView def SetView(self, view): self.output = view def SetStartRow(self, row): self.startrow = row def DateToRegion(self, date): # Convert monthIndex = (date.month - (self.midmonth) + 1) % 12 if(monthIndex < 0 or monthIndex >= len(self.monthdata)): return monthData = self.monthdata[monthIndex] weekIndex = 0 dayIndex = 0 for weekId in range(0,len(monthData)): weekData = monthData[weekId] for dayId in range(0,len(weekData)): day = weekData[dayId] if(day == date.day): weekIndex = weekId dayIndex = dayId # 2 row heading? # We should have an offset? Probably row = self.headingLines + weekIndex col = monthIndex * self.columnsPerMonth + dayIndex*self.columnsPerDay #print("ROW: " + str(row) + " COL: " + str(col)) s = self.output.text_point(row,col) e = self.output.text_point(row,col+2) return sublime.Region(s, e) def HighlightDay(self, date): reg = self.DateToRegion(date) style = self.dayhighlight if(style == None): style = "orgdatepicker.monthheader" self.output.add_regions("cur",[reg],style,"",sublime.DRAW_NO_OUTLINE) def AddToDayHighlights(self, date, key, highlight, drawtype = sublime.DRAW_NO_OUTLINE): reg = self.DateToRegion(date) if(not reg): #print("NO REGION FOR DATE: " + str(date)) return regs = self.output.get_regions(key) if not regs: regs = [] regs.append(reg) self.output.add_regions(key,regs,highlight,"",drawtype) def ClearDayHighlights(self,key): self.output.erase_regions(key) def MapRowColToDate(self,row,col): weekid = int(row - self.headingLines) monthid = int(col / self.columnsPerMonth) dayid = int((col % self.columnsPerMonth) / self.columnsPerDay) day = self.monthdata[monthid][weekid][dayid] month = monthid + self.midmonth - 1 year = self.cdate.start.year time = self.cdate.start.time() duration = None if(time): result = datetime.datetime(year, month, day, time.hour, time.minute, time.second, time.microsecond) else: result = datetime.datetime(year, month, day) return result def MoveCDateToDate(self, now): self.cdate = OrgDateFreeFloating(now) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToNextDay(self): self.cdate.add_days(1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToPrevDay(self): self.cdate.add_days(-1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToNextWeek(self): self.cdate.add_days(7) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToPrevWeek(self): self.cdate.add_days(-7) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToNextMonth(self): self.cdate.add_months(1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToPrevMonth(self): self.cdate.add_months(-1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToNextHour(self): self.cdate.add_hours(1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToPrevHour(self): self.cdate.add_hours(-1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToNextMinute(self): self.cdate.add_minutes(1) self.ReShow() self.HighlightDay(self.cdate.start) def MoveCDateToPrevMinute(self): self.cdate.add_minutes(-1) self.ReShow() self.HighlightDay(self.cdate.start) def ReShow(self): if(self.cdate == None): return now = self.cdate.start if(now == None): return mid = (now.month - self.midmonth + 1) if(mid < 0 or mid > 2 or self.timeView): self.Render(now) self.ResetRenderState() self.ClearDayHighlights("today") self.AddToDayHighlights(datetime.datetime.now(), "today",todayHighlight, sublime.DRAW_NO_FILL) @staticmethod def NextMonth(now): month = now.month + 1 year = now.year if(month > 12): year += 1 month = 1 return (month, year) @staticmethod def PrevMonth(now): month = now.month - 1 year = now.year if(month <= 0): year -= 1 month = 12 return (month, year) def Render(self,now): days = [calendar.MONDAY, calendar.TUESDAY, calendar.WEDNESDAY, calendar.THURSDAY, calendar.FRIDAY, calendar.SATURDAY, calendar.SUNDAY] firstDay = days[self.firstdayindex] c = calendar.TextCalendar(firstDay) str = c.formatmonth(now.year, now.month) calendar.setfirstweekday(firstDay) self.midmonth = now.month pmonth, pyear = DateView.PrevMonth(now) nmonth, nyear = DateView.NextMonth(now) self.monthdata = [ calendar.monthcalendar(pyear, pmonth), calendar.monthcalendar(now.year, now.month), calendar.monthcalendar(nyear, nmonth)] #print(str) m2 = str.split('\n') month, year = DateView.NextMonth(now) str = c.formatmonth(year, month) #print(str) m3 = str.split('\n') month, year = DateView.PrevMonth(now) str = c.formatmonth(year, month) #print(str) m1 = str.split('\n') self.output.set_read_only(False) self.output.sel().clear() pt = self.output.text_point(self.startrow,0) self.output.sel().add(pt) l = max(len(m1),len(m2),len(m3)) self.endrow = self.startrow + l row = self.startrow clock = None endrange = l if(self.timeView): clock = aclock.draw_clock(now,30,26) endrange = 25 for i in range(0,endrange): line = "{0:90}".format(" ") pt = self.output.text_point(row,0) row += 1 if(i < l): ml1 = m1[i] if i < len(m1) else "" ml2 = m2[i] if i < len(m2) else "" ml3 = m3[i] if i < len(m3) else "" line = "{0:30}{1:30}{2:30}".format(ml1,ml2,ml3) if(clock and self.timeView): line += clock.get_row(i+2) lreg = self.output.line(pt) lreg = sublime.Region(lreg.begin(), lreg.end() + 1) self.output.ReplaceRegion(lreg, line + "\n") #print(line) self.HighlightDay(now) def ResetRenderState(self): self.output.set_read_only(True) self.output.set_scratch(True) if not self.output.name(): self.output.set_name("DatePicker") class DatePicker: def __init__(self,firstDayIndex=0): self.dateView = DateView(None, firstDayIndex, True) self.months = [] def on_done(self, text): self.dateView.output.close() if(self.onDone): evt.Get().emit(self.onDone, self.dateView.cdate) def on_canceled(self): self.dateView.output.close() if(self.onDone): evt.Get().emit(self.onDone, None) def on_changed(self, text): #print("CHANGED: " + text) duration = orgduration.OrgDuration.Parse(text,True) if(not duration): duration = orgduration.OrgDuration.ParseWeekDayOffset(text) if(not duration): duration = orgduration.OrgDuration.ParseMonthOffset(text) # We allow duration syntax 3h if(text == "." or text == "+0"): now = datetime.datetime.now() self.dateView.cdate = OrgDateFreeFloating(now) elif(text.isnumeric()): # We assume this is a day of the month (this month or next) now = datetime.datetime.now() cday = int(text) if(cday > now.day): now = now.replace(day=cday) else: now = now.replace(month=now.month+1,day=cday) self.dateView.cdate = OrgDateFreeFloating(now) elif(duration): now = OrgDateFreeFloating(datetime.datetime.now()) self.dateView.cdate = now + duration else: self.dateView.cdate = OrgDateFreeFloating.from_str(text) self.dateView.ReShow() if(self.dateView.cdate): self.dateView.HighlightDay(self.dateView.cdate.start) def MapRowColToNewDate(self,row,col): time = self.dateView.cdate.start.time() duration = None if(self.dateView.cdate.has_end()): duration = self.dateView.cdate.end - self.dateView.cdate.start self.dateView.cdate._start = self.dateView.MapRowColToDate(row,col) if(duration): self.dateView.cdate._end = self.dateView.cdate.start + duration self.inputpane.ReplaceRegion(self.inputpane.line(self.inputpane.text_point(0,0)), OrgDate.format_datetime(self.dateView.cdate.start)) self.dateView.HighlightDay(self.dateView.cdate.start) def RefreshInputPanelFromDateView(self): self.inputpane.ReplaceRegion(self.inputpane.line(self.inputpane.text_point(0,0)), OrgDate.format_datetime(self.dateView.cdate.start)) def MoveNextDay(self): self.dateView.MoveCDateToNextDay() self.RefreshInputPanelFromDateView() def MovePrevDay(self): self.dateView.MoveCDateToPrevDay() self.RefreshInputPanelFromDateView() def MoveNextWeek(self): self.dateView.MoveCDateToNextWeek() self.RefreshInputPanelFromDateView() def MovePrevWeek(self): self.dateView.MoveCDateToPrevWeek() self.RefreshInputPanelFromDateView() def MoveNextMonth(self): self.dateView.MoveCDateToNextMonth() self.RefreshInputPanelFromDateView() def MovePrevMonth(self): self.dateView.MoveCDateToPrevMonth() self.RefreshInputPanelFromDateView() def MoveNextHour(self): self.dateView.MoveCDateToNextHour() self.RefreshInputPanelFromDateView() def MovePrevHour(self): self.dateView.MoveCDateToPrevHour() self.RefreshInputPanelFromDateView() def MoveNextMinute(self): self.dateView.MoveCDateToNextMinute() self.RefreshInputPanelFromDateView() def MovePrevMinute(self): self.dateView.MoveCDateToPrevMinute() self.RefreshInputPanelFromDateView() def Show(self,now, onDone): self.onDone = onDone window = sublime.active_window() self.output = CreateUniqueViewNamed("DatePicker") self.dateView.SetView(self.output) self.dateView.Render(now) self.dateView.ResetRenderState() curstr = OrgDate.format_datetime(now) self.cdate = OrgDateFreeFloating.from_str(curstr) self.inputpane = window.show_input_panel( "Date:", curstr, self.on_done, self.on_changed, self.on_canceled) pt = self.inputpane.text_point(0,0) self.inputpane.set_syntax_file("Packages/OrgExtended/orgdateeditor.sublime-syntax") # ============================================================= datePicker = None def is_pt_date_view(view, pt): return 'source.orgdatepicker' in view.scope_name(pt) def onMouse(pt, view, edit): if(not is_pt_date_view(view, pt)): return row, col = view.rowcol(pt) if(datePicker): datePicker.MapRowColToNewDate(row,col) # TODO Convert point back to a date and push that into # the input box. def SetupMouse(): evt.Get().on("orgmouse",onMouse) class OrgDatePickerCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker = DatePicker() datePicker.Show(datetime.datetime.now(),None) class OrgDatePickerNextDayCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MoveNextDay() class OrgDatePickerPrevDayCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MovePrevDay() class OrgDatePickerPrevWeekCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MovePrevWeek() class OrgDatePickerNextWeekCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MoveNextWeek() class OrgDatePickerPrevMonthCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MovePrevMonth() class OrgDatePickerNextMonthCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MoveNextMonth() class OrgDatePickerNextHourCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MoveNextHour() class OrgDatePickerPrevHourCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MovePrevHour() class OrgDatePickerNextMinuteCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MoveNextMinute() class OrgDatePickerPrevMinuteCommand(sublime_plugin.TextCommand): def run(self, edit): global datePicker datePicker.MovePrevMinute() def Pick(onDone): global datePicker firstDayIndex = sets.GetWeekdayIndexByName(sets.Get("firstDayOfWeek","Sunday")) datePicker = DatePicker(firstDayIndex) datePicker.Show(datetime.datetime.now(), onDone) ================================================ FILE: orgdatepicker.sublime-color-scheme ================================================ { "name": "orgdatepicker", "variables": { "bgcol": "#272822", // Define variables here }, "globals": { "foreground": "#F8F8F2", "background": "var(bgcol)", "accent": "#ffffff", "selection": "#9D550F", "selectionBackground": "#000000", "selectionForeground": "#FF0000", "caret": "#FF55ff", "line_highlight": "#373730" }, "rules": [ { "scope": "orgdatepicker.weekendheader", "foreground": "#5b96f5", "font_style": "bold italic", }, { "scope": "orgdatepicker.weekdayheader", "foreground": "#0762a3", "font_style": "bold italic", }, { "scope": "orgdatepicker.monthheader", "foreground": "#7e4794", "font_style": "bold italic", }, { "scope": "orgdatepicker.time", "foreground": "#aaaaaa", "font_style": "bold italic", }, ] } ================================================ FILE: orgdatepicker.sublime-settings ================================================ { // The color scheme to use for the datepicker buffer "color_scheme": "Packages/OrgExtended/orgdatepicker.sublime-color-scheme", //"font_face": "Courier New", //"font_size": 15 } ================================================ FILE: orgdatepicker.sublime-syntax ================================================ %YAML1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: orgdatepicker file_extensions: - orgdatepicker scope: source.orgdatepicker version: 2 hidden: true contexts: main: # filename and line location - match: '(Mo|Tu|We|Th|Fr)' scope: keyword orgdatepicker.weekdayheader - match: '(Sa|Su)' scope: constant.numeric orgdatepicker.weekendheader - match: '(January|February|March|April|May|June|July|August|September|October|November|December)\s*([0-9]+)' scope: string.quoted orgdatepicker.monthheader - match: '\.|`' scope: comment orgdatepicker.timetick - match: 'O' scope: orgagenda.block.1 orgdatepicker.hourhand - match: 'o' scope: orgagenda.block.2 orgdatepicker.minutehand ================================================ FILE: orgdaypage.py ================================================ import sublime import sublime_plugin import datetime import re import os import logging import getpass import OrgExtended.asettings as sets import OrgExtended.pymitter as evt import OrgExtended.orgextension as ext import OrgExtended.orgparse.date as orgdate import OrgExtended.orgdb as db log = logging.getLogger(__name__) # I think I will model this feature after org-roam dailies. # olBc has not really gotten back to me on the subject and I think # dailies makes a lot of sense. def dayPageGetToday(): dt = datetime.datetime.now() change = ["monday","tuesday","wednesday","thursday","friday","saturday","sunday"] if(sets.Get("dayPageMode","day") == "week"): firstDay = sets.Get("dayPageModeWeekDay","Monday").lower() startAt = [idx for idx, element in enumerate(change) if element.startswith(firstDay)] if(len(startAt) > 0): startAt = startAt[0] else: startAt = 0 offset = (dt.weekday() - startAt) if(offset != 0): dt = dt - datetime.timedelta(days=offset) return dt def dayPageGetPath(): dpPath = sets.Get("dayPagePath",None) if(dpPath == None): return None try: if isinstance(dpPath, list): sublime.status_message("Day Page error. dayPagePath setting should be a string not a list! ABORT!") log.error(" Cannot create day page without propper dayPathPath in configuration. Expected string, found list") return None if isinstance(dpPath, str) and not dpPath.strip() == "": os.makedirs(dpPath, exist_ok=True) except Exception as e: sublime.status_message("Day Page error. dayPagePath setting is not valid could not create daypage! ABORT!") log.error("Cannot create day page without propper dayPathPath in configuration: \n" + str(e)) return None return dpPath def dayPageGetDateString(dt): formatStr = sets.Get("dayPageNameFormat","%a_%Y_%m_%d") return dt.strftime(formatStr) def dayPageFilenameToDateTime(view): filename = view.file_name() if(not filename): return None formatStr = sets.Get("dayPageNameFormat","%a_%Y_%m_%d") filename = os.path.splitext(os.path.basename(filename))[0] return datetime.datetime.strptime(filename,formatStr) def dayPageGetName(dt): path = dayPageGetPath() if path == None: return "DAY_PAGE_NOT_SET.org" else: return os.path.join(dayPageGetPath(),dayPageGetDateString(dt) + ".org") def OnLoaded(view,dt): view.sel().clear() view.sel().add(0) snippet = sets.Get("dayPageSnippet","dayPageSnippet") snipName = ext.find_extension_file('orgsnippets',snippet,'.sublime-snippet') if(snipName == None): log.error(" Could not locate snippet file: " + str(snippet) + ".sublime-snippet using default") snipName = ext.find_extension_file('orgsnippets','dayPageSnippet.sublime-snippet') # NeoVintageous users probably prefern not to have to hit insert when editing things. view.run_command('_enter_insert_mode', {"count": 1, "mode": "mode_internal_normal"}) now = dt inow = orgdate.OrgDate.format_date(now, False) anow = orgdate.OrgDate.format_date(now, True) ai = view.settings().get('auto_indent') view.settings().set('auto_indent',False) # "Packages/OrgExtended/orgsnippets/"+snippet+".sublime-snippet" # OTHER VARIABLES: # TM_FULLNAME - Users full name # TM_FILENAME - File name of the file being edited # TM_CURRENT_WORD - Word under cursor when snippet was triggered # TM_SELECTED_TEXT - Selected text when snippet was triggered # TM_CURRENT_LINE - Line of snippet when snippet was triggered #insert_snippet {"name": "Packages/OrgExtended/orgsnippets/page.sublime-snippet"} view.run_command("insert_snippet", { "name" : snipName , "ORG_INACTIVE_DATE": inow , "ORG_ACTIVE_DATE": anow , "ORG_DATE": str(dt.date().today()) , "ORG_TIME": dt.strftime("%H:%M:%S") , "ORG_CLIPBOARD": sublime.get_clipboard() , "ORG_SELECTION": view.substr(view.sel()[0]) , "ORG_LINENUM": str(view.curRow()) , "ORG_FILENAME": dayPageGetDateString(dt) , "ORG_AUTHOR": getpass.getuser() }) view.settings().set('auto_indent',ai) def LoadedCheck(view,dt): if(view.is_loading()): sublime.set_timeout(lambda: LoadedCheck(view,dt),1) else: OnLoaded(view,dt) def LoadedCheck2(view,dt, onDone): if(view.is_loading()): sublime.set_timeout(lambda: LoadedCheck2(view,dt,onDone),1) else: onDone(view,dt) def dayPageInsertSnippet(view,dt): window = view.window() window.focus_view(view) LoadedCheck(view,dt) def dayPageFindOldPage(dt): maxScan = 90 for i in range(maxScan): dt = dt - datetime.timedelta(days=1) fn = dayPageGetName(dt) if(os.path.exists(fn)): return fn return None def dayPageArchiveOld(dt): fn = dayPageFindOldPage(dt) if(fn == None): return f = db.Get().FindFileByFilename(os.path.basename(fn)) if(f == None): return if(f.org[0].set_comment("FILETAGS","ARCHIVE")): f.Save() def IsTodo(n): return n.todo and n.todo in n.env.todo_keys def IsDone(n): return n.todo and n.todo in n.env.done_keys def IsArchived(n): return "ARCHIVE" in n.tags def EnsureDate(ts): if(isinstance(ts,datetime.datetime)): return ts.date() return ts def dayPageCopyOpenTasks(tview, dt): fn = dayPageFindOldPage(dt) if(fn == None): dayPageInsertSnippet(tview,dt) return f = db.Get().FindFileByFilename(os.path.basename(fn)) if(f == None): dayPageInsertSnippet(tview,dt) return out = "" for h in f.org[0].children: if IsTodo(h): for line in h._lines: out += line + "\n" if(out != ""): LoadedCheck2(tview, dt, lambda a,b: tview.run_command("org_internal_insert", {"location": 0, "text": out, "onDone": evt.Make(lambda : dayPageInsertSnippet(tview, dt))})) else: dayPageInsertSnippet(tview,dt) pass def dayPageCopyOpenPhase(tview,dt): if(sets.Get("dayPageCopyOpenTasks", True)): dayPageCopyOpenTasks(tview, dt) else: dayPageInsertSnippet(tview,dt) def dayPageCopyTodayTasks(path, tview, dt): allowOutsideOrgDir = sets.Get("dayPageIncludeFilesOutsideOrgDir", False) out = "" for file in db.Get().Files: # Quick out if ARCHIVE is marked on the file globalTags = file.org.list_comment("FILETAGS",[]) if("ARCHIVE" in globalTags): continue # Skip over files not in orgDir if(not file.isOrgDir and not allowOutsideOrgDir): continue # Skip over ourselves. if(path.lower() == file.GetFilename().lower()): continue skipTill = 0 for i in range(1,len(file.org)): if(i < skipTill): continue n = file.org[i] if(IsTodo(n)): ok = False timestamps = n.get_timestamps(active=True,point=True,range=True) for t in timestamps: if(t.start.day == dt.day and t.start.month == dt.month and t.start.year == dt.year): ok = True break if(n.scheduled and (EnsureDate(n.scheduled.start) < EnsureDate(dt) and not IsDone(n) and not IsArchived(n) or EnsureDate(n.scheduled.start) == EnsureDate(dt))): ok = True if(n.deadline and (EnsureDate(n.deadline.deadline_start) < EnsureDate(dt) and not IsDone(n) and not IsArchived(n) or EnsureDate(n.deadline.deadline_start) == EnsureDate(dt))): ok = True if(ok): for line in n._lines: out += line + "\n" skipTill = n.find_last_child_index() + 1 if(out != ""): LoadedCheck2(tview, dt, lambda a,b: tview.run_command("org_internal_insert", {"location": 0, "text": out, "onDone": evt.Make(lambda : dayPageCopyOpenPhase(tview, dt))})) else: dayPageCopyOpenPhase(tview,dt) def dayPageCreateOrOpen(dt): dpPath = dayPageGetName(dt) dateString = dayPageGetDateString(dt) didCreate = False if(not os.path.exists(dpPath)): with open(dpPath,"w") as f: f.write("") didCreate = True tview = sublime.active_window().open_file(dpPath, sublime.ENCODED_POSITION) if(didCreate): if(sets.Get("dayPageArchiveOld", True)): dayPageArchiveOld(dt) if(sets.Get("dayPageCopyTasksForToday", True)): dayPageCopyTodayTasks(dpPath, tview, dt) else: dayPageCopyOpenPhase(tview,dt) class OrgDayPagePreviousCommand(sublime_plugin.TextCommand): def OnDone(self): evt.EmitIf(self.onDone) def run(self, edit, onDone=None): self.edit = edit self.onDone = onDone self.dt = datetime.datetime.now() dt = dayPageFilenameToDateTime(self.view) maxScan = 90 for i in range(maxScan): dt = dt - datetime.timedelta(days=1) if(sets.Get("dayPageCreateOldPages",False)): dayPageCreateOrOpen(dt) break else: fn = dayPageGetName(dt) if(os.path.exists(fn)): tview = sublime.active_window().open_file(fn, sublime.ENCODED_POSITION) sublime.active_window().focus_view(tview) break else: #log.warning("Day page does not exist: " + fn) pass class OrgDayPageNextCommand(sublime_plugin.TextCommand): def OnDone(self): evt.EmitIf(self.onDone) def run(self, edit, onDone=None): self.edit = edit self.onDone = onDone self.now = datetime.datetime.now() dt = dayPageFilenameToDateTime(self.view) maxScan = 90 for i in range(maxScan): dt = dt + datetime.timedelta(days=1) if(dt.date() < self.now.date()): fn = dayPageGetName(dt) if(os.path.exists(fn)): tview = sublime.active_window().open_file(fn, sublime.ENCODED_POSITION) sublime.active_window().focus_view(tview) break else: #log.warning("Day page does not exist: " + fn) pass elif(dt.date() == self.now.date()): dayPageCreateOrOpen(dt) break else: fn = dayPageGetName(dt) log.error(" Create day page in the future? " + fn) break class OrgDayPageCreateCommand(sublime_plugin.TextCommand): def OnDone(self): evt.EmitIf(self.onDone) def run(self, edit, onDone=None): self.edit = edit self.onDone = onDone self.dt = dayPageGetToday() dayPageCreateOrOpen(self.dt) self.OnDone() ================================================ FILE: orgdb.py ================================================ import sublime import sublime_plugin import datetime import re from pathlib import Path import os import OrgExtended.orgparse.loader as loader import OrgExtended.orgparse.node as node import OrgExtended.orgutil.util as util import logging import traceback import OrgExtended.asettings as sets import OrgExtended.pymitter as evt log = logging.getLogger(__name__) headingRe = re.compile("^([*]+) (.+)") class FileInfo: def __init__(self, file, parsed, orgPaths): self.isOrgDir = False self.org = parsed self.filename = file self.key = file.lower() if file else None self.change_count = 0 self.org.setFile(self) displayFn = self.key oldLen = len(displayFn) if displayFn else 0 if (not displayFn): self.displayFn = "" return for prefix in orgPaths: displayFn = displayFn.replace(prefix, "") displayFn = displayFn.replace(prefix.lower(), "") self.isOrgDir = displayFn != self.key # Max Slashes! # No prefixes. We should count the slashes and truncate # if there are to many. maxSlash = 3 if (oldLen == len(displayFn)): scount = displayFn.count('/') if (scount > maxSlash): llist = displayFn.split('/') displayFn = '/'.join(llist[-maxSlash:]) scount = displayFn.count('\\') if (scount > maxSlash): llist = displayFn.split('\\') displayFn = '\\'.join(llist[-maxSlash:]) if (len(displayFn) > 1 and (displayFn[0] == '\\' or displayFn[0] == '/')): displayFn = displayFn[1:] self.displayName = displayFn def GetFilename(self): return self.filename def RebuildBacklinks(self): links = self.org.env.links for link in links: if (link.IsFile()): f = link.link if (not os.path.isabs(f)): f = os.path.normpath(os.path.join(os.path.dirname(self.filename), f)) Get().AddBacklink(f, link, self) def Root(self): return self.org[0] def RootInView(self, view, db): self.ReloadIfChanged(view, db) return self.Root() def LoadS(self, view): bufferContents = view.substr(sublime.Region(0, view.size())) self.org = loader.loads(bufferContents, view.file_name() if view.file_name() else "") self.org.setFile(self) # Keep track of last change count. self.change_count = view.change_count() self.RebuildBacklinks() def Reload(self): self.org = loader.load(self.filename) self.org.setFile(self) self.RebuildBacklinks() def ResetChangeCount(self): self.change_count = 0 def HeadingCount(self): return len(self.org) - 1 def Save(self): f = open(self.filename, "w+", encoding="utf-8") for item in self.org: f.write(str(item)) f.close() def ReloadIfChanged(self, view, db): if (self.HasChanged(view)): self.LoadS(view) db.RebuildAllIdsForFile(self) def HasChanged(self, view): return self.change_count < view.change_count() def At(self, row): return self.org.at(row) def AtPt(self, view, pt, db): self.ReloadIfChanged(view, db) row, col = view.rowcol(pt) return self.org.at(row) def AtRegion(self, view, reg): row, col = view.rowcol(reg.begin()) return self.org.at(row) def AtInView(self, view, db): self.ReloadIfChanged(view, db) (row, col) = view.curRowCol() return self.org.at(row) def AgendaFilenameTag(self): return os.path.splitext(os.path.basename(self.filename))[0] + ":" def FindOrCreateNode(self, heading): for n in self.org[1:]: if (heading == n.full_heading): return n for n in self.org[1:]: if (heading == n.heading): return n # Okay got here and didn't find the node, have to make it. m = headingRe.search(heading) if (m is None): log.error("FindorCreateNode: failed to parse heading: " + heading) return None levelGroup = m.group(1) level = len(levelGroup) cur = self.org[0] parentLevel = level - 1 while (cur.level < parentLevel): if (cur.num_children == 0): tree = loader.loads("* " + str(datetime.datetime())) cur.insert_child(tree[1]) cur = cur.get_last_child() if (heading is None or heading.isspace() or heading.strip() == ""): return cur else: tree = loader.loads(heading) cur.insert_child(tree[1]) cur = cur.get_last_child() return cur class OrgFileId: def __init__(self, file, id, index): self.file = file self.id = id self.index = index class OrgDb: def __init__(self): self.files = {} self.Files = [] self.orgPaths = None self.customids = [] self.customidmaps = {} self.ids = [] self.idmaps = {} self.tags = set() self.backlinks = {} def GetBacklinks(self, view): fn = view.file_name() if (fn in self.backlinks): return self.backlinks[fn] return None def AddBacklink(self, f, link, fi): link.fromFile = fi link.targetName = f if (f not in self.backlinks): self.backlinks[f] = [] for i in range(len(self.backlinks[f])): ff = self.backlinks[f][i] if (link.row == ff.row): self.backlinks[f][i] = link return self.backlinks[f].append(link) def OnTags(self, tags): for i in tags: self.tags.add(i) def RebuildCustomIdsForFile(self, file): for id in file.org.env.customids: if (id not in self.customidmaps): index = len(self.customids) fid = OrgFileId(file, id, index) self.customids.append(fid) self.customidmaps[id] = fid def RebuildIdsForFile(self, file): for id in file.org.env.ids: if (id not in self.idmaps): index = len(self.ids) fid = OrgFileId(file, id, index) self.ids.append(fid) self.idmaps[id] = fid def RebuildAllIdsForFile(self, file): self.RebuildIdsForFile(file) self.RebuildCustomIdsForFile(file) def RebuildIds(self): self.ids = [] self.idmaps = {} self.customids = [] self.customidmaps = {} for file in self.Files: self.RebuildAllIdsForFile(file) def LoadNew(self, fileOrView): if (fileOrView is None): return None if (not hasattr(self, 'orgPaths') or self.orgPaths is None): self.orgPaths = self.__GetPaths("orgDirs") filename = self.FilenameFromFileOrView(fileOrView) if (util.isPotentialOrgFile(filename)): file = FileInfo(filename, loader.load(filename), self.orgPaths) self.AddFileInfo(file) return file elif (util.isView(fileOrView) and util.isOrgSyntax(fileOrView)): bufferContents = fileOrView.substr(sublime.Region(0, fileOrView.size())) file = FileInfo(filename if filename else util.getKey(fileOrView), loader.loads(bufferContents), self.orgPaths) self.AddFileInfo(file) return file else: log.debug("File is not an org file, not loading into the database: " + str(filename)) return None def Remove(self, fileOrView): if (type(fileOrView) is sublime.View): filename = fileOrView.file_name().lower() else: filename = fileOrView.lower() for i in range(len(self.Files) - 1, -1, -1): if (self.Files[i].key == filename): del self.Files[i] if (filename in self.files): del self.files[filename] # self.files.pop(filename,None) def Reload(self, fileOrView): self.orgPaths = self.__GetPaths("orgDirs") fi = self.FindInfo(fileOrView) if (fi is not None): fi.Reload() self.RebuildIds() fi.RebuildBacklinks() return fi else: rv = self.LoadNew(fileOrView) self.RebuildIds() return rv def GetIndentForRegion(self, view, region): node = self.AtRegion(view, region) return node.level + 1 def FilenameFromFileOrView(self, fileOrView): filename = None if (type(fileOrView) is sublime.View): filename = fileOrView.file_name() else: filename = fileOrView return filename def AddFileInfo(self, fi): if (self.files is None): self.files = {} self.files[fi.key] = fi if (self.Files is None): self.Files = [] unique = True for i, f in enumerate(self.Files): if f.filename == fi.filename: unique = False self.Files[i] = fi break if unique: self.Files.append(fi) self.SortFiles() fi.RebuildBacklinks() def SortFiles(self): self.Files.sort(key=lambda x: x.key) @staticmethod def IsExcluded(filename, excludedPaths, excludedFiles): if (excludedPaths): excludedPaths = [x.lower().replace('\\', '/') for x in excludedPaths] mypath = os.path.dirname(filename).lower().replace('\\', '/') for item in excludedPaths: if mypath.startswith(item): return True if (excludedFiles): excludedFiles = [x.lower().replace('\\', '/') for x in excludedFiles] myfile = os.path.basename(filename).lower().replace('\\', '/') for item in excludedFiles: if (item == myfile): return True return False def RebuildDb(self): if (evt.Get().listeners('tagsfound')): evt.Get().clear_listeners('tagsfound') evt.Get().on("tagsfound", self.OnTags) self.Files = [] self.files = {} self.orgPaths = self.__GetPaths("orgDirs") self.orgFiles = self.__GetPaths("orgFiles") self.orgExcludePaths = self.__GetPaths("orgExcludeDirs") self.orgExcludeFiles = self.__GetPaths("orgExcludeFiles") if (self.orgPaths): # Just in case the user gave us a string instead of a list. if (isinstance(self.orgPaths, str)): self.orgPaths = [self.orgPaths] for orgPath in self.orgPaths: orgPath = orgPath.replace('\\', '/') globSuffix = sets.Get("validOrgExtensions", [".org"]) for suffix in globSuffix: if ('archive' in suffix): continue suffix = "*" + suffix dirGlobPos = orgPath.find("*") if (dirGlobPos > 0): suffix = os.path.join(orgPath[dirGlobPos:], suffix) orgPath = orgPath[0:dirGlobPos] if ("*" in orgPath): log.error(" orgDirs only supports double star style directory wildcards! Anything else is not supported: " + str(orgPath)) if (sublime.active_window().active_view()): sublime.active_window().active_view().set_status("Error: ", "orgDirs only supports double star style directory wildcards! Anything else is not supported: " + str(orgPath)) log.error(" skipping orgDirs value: " + str(orgPath)) continue try: if not Path(orgPath).exists(): log.warning('orgDir path {} does not exist!'.format(orgPath)) continue except Exception as e: log.warning('could not add org path: {} - does not seem to exist {}'.format(orgPath, str(e))) continue try: for path in Path(orgPath).glob(suffix): if OrgDb.IsExcluded(str(path), self.orgExcludePaths, self.orgExcludeFiles): continue try: filename = str(path) log.debug("PARSING: " + filename) file = FileInfo(filename, loader.load(filename), self.orgPaths) file.isOrgDir = True self.AddFileInfo(file) except Exception: log.warning("FAILED PARSING: %s\n %s", str(path), traceback.format_exc()) except Exception: log.warning("ERROR globbing {}\n{}".format(orgPath, traceback.format_exc())) if (self.orgFiles): # Just in case the user gave us a string instead of a list. if (isinstance(self.orgFiles, str)): self.orgFiles = [self.orgFiles] for orgFile in self.orgFiles: path = orgFile.replace('\\', '/') if OrgDb.IsExcluded(str(path), self.orgExcludePaths, self.orgExcludeFiles): continue try: filename = str(path) file = FileInfo(filename, loader.load(filename), self.orgPaths) file.isOrgDir = True self.AddFileInfo(file) except Exception: log.warning("FAILED PARSING: %s\n %s", str(path), traceback.format_exc()) self.SortFiles() self.RebuildIds() def FindInfo(self, fileOrView): try: if (not fileOrView): return None key = util.getKey(fileOrView).lower() if (key and key in self.files): f = self.files[key] else: f = self.LoadNew(fileOrView) if (f and util.isView(fileOrView)): f.ReloadIfChanged(fileOrView, self) return f except Exception: try: f = self.LoadNew(fileOrView) if (type(fileOrView) is sublime.View): f.ReloadIfChanged(fileOrView, self) return f except Exception: log.warning("FAILED PARSING: \n %s", traceback.format_exc()) return None def Find(self, fileOrView): n = self.FindInfo(fileOrView) if (n is not None): return n.org return None def At(self, fileOrView, line): x = self.Find(fileOrView) if (x is not None): return x.at(line) return None def AtInView(self, view): (row, col) = view.curRowCol() return self.At(view, row) def AtPt(self, view, pt): file = self.FindInfo(view) return file.AtPt(view, pt, self) def RootInView(self, view): file = self.FindInfo(view) if file: return file.RootInView(view, self) return None def AtRegion(self, view, reg): file = self.FindInfo(view) return file.AtRegion(view, reg) def NodeAtIndex(self, fileOrView, index): return self.Find(fileOrView).node_at(index + 1) def Headings(self, view): f = self.Find(view) headings = [] if (f is not None): for n in f[1:]: headings.append((". " * (n.level)) + n.heading) return headings # This is paired with FindFileInfo def AllHeadings(self, view): headings = [] for o in self.Files: displayFn = o.displayName f = o.org for n in f[1:]: formattedHeading = "{0:35}::{1}{2}".format(displayFn, (". " * (n.level)), n.heading) headings.append(formattedHeading) return headings # This is paired with FindFileInfo def AllHeadingsWContext(self, view): headings = [] count = 0 for o in self.Files: displayFn = o.displayName f = o.org for n in f[1:]: parents = "" t = n while (type(t.parent) != node.OrgRootNode and t.parent is not None): t = t.parent parents = t.heading + ":" + parents formattedHeading = ["{0}{1}".format(parents, n.heading), displayFn] headings.append(formattedHeading) count += 1 return headings def AllHeadingsForFile(self, file): headings = [] count = 0 f = file.org for n in f[1:]: parents = "" t = n while (type(t.parent) != node.OrgRootNode and t.parent is not None): t = t.parent parents = t.heading + ":" + parents formattedHeading = "{0}{1}".format(parents, n.heading) headings.append(formattedHeading) count += 1 return headings # This is paired with FindFileInfo def AllFiles(self, view): files = [] for o in self.Files: displayFn = o.displayName files.append(displayFn) return files def FindFileByIndex(self, index): return self.Files[index] # This is a pair with AllHeadings, it can go from an index in that BACK to the # fileinfo def FindFileInfoByAllHeadingsIndex(self, index): curVal = 0 for o in self.Files: if (index >= curVal and index < (curVal + o.HeadingCount())): return (o, (index - curVal) + 1) # remember to account for header curVal += o.HeadingCount() return None # Try to find a node by filename and locator def FindNode(self, filename, locator): file = self.FindInfo(filename) if (not file): return None # Basic locator search through the headings headings = locator.split(":") cur = file.org[0] for index in range(len(headings)): heading = headings[index] for n in cur.children: if (n.heading == heading): cur = n break # Did not find this level of heading darn if (not cur or cur.is_root() or cur.heading != heading): break heading = headings[len(headings)-1] if (not cur or cur.is_root() or cur.heading == heading): return cur if (len(headings) > 1): parent = headings[-1] bestMatch = None # fuzzy search, heading must match (hopefully) for n in file.org[1:]: if (n.heading == heading): bestMatch = n if (n.parent and n.parent.heading == parent): return n return bestMatch def JumpToCustomId(self, id): path = None file, at = self.FindByCustomId(id) if (file is not None): path = "{0}:{1}".format(file.filename, at + 1) if (path): sublime.active_window().open_file(path, sublime.ENCODED_POSITION) return True else: log.info("Could not locate Custom ID failed to jump there") return False def JumpToId(self, id): path = None file, at = self.FindById(id) if (file is not None): path = "{0}:{1}".format(file.filename, at + 1) if (path): sublime.active_window().open_file(path, sublime.ENCODED_POSITION) return True else: log.info("Could not locate ID failed to jump there") return False def JumpToAnyId(self, id): if (not self.JumpToId(id)): return self.JumpToCustomId(id) return True def FindByAnyId(self, id): v = self.FindById(id) if (not v or v[0] is None): return self.FindByCustomId(id) return v def FindNodeByAnyId(self, id): v = self.FindByAnyId(id) if (v and v[0]): return v[0].At(v[1]) return None def FindFileByFilename(self, filename): for f in self.Files: if (filename in f.filename): return f return None def FindByCustomId(self, id): if (id in self.customidmaps): fid = self.customidmaps[id] file = fid.file at = file.org.env.customids[id][1] return (file, at) return (None, None) def FindById(self, id): if (id in self.idmaps): fid = self.idmaps[id] file = fid.file at = file.org.env.ids[id][1] return (file, at) return (None, None) def GetIds(self): return self.idmaps.keys() def __GetPaths(self, name): paths = sets.Get(name, None) if (str == type(paths)): return os.path.expanduser(paths) if (list == type(paths)): return list(map(os.path.expanduser, paths)) return None # EXPORTED ORGDB orgDb = OrgDb() def Get(): global orgDb return orgDb # rebuild our org database from our org directory class OrgRebuildDbCommand(sublime_plugin.TextCommand): def run(self, edit): Get().RebuildDb() # Just reload the current file. class OrgReloadFileCommand(sublime_plugin.TextCommand): def run(self, edit): file = Get().FindInfo(self.view) if (file): file.LoadS(self.view) orgDb.RebuildIds() else: log.debug("FAILED TO FIND FILE INFO?") class OrgJumpToCustomIdCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifers): self.on_done(index) def on_done(self, index): if (index < 0 or index >= len(orgDb.customids)): return fid = orgDb.customids[index] file = fid.file id = fid.id at = file.org.env.customids[id][1] path = "{0}:{1}".format(file.filename, at + 1) self.view.window().open_file(path, sublime.ENCODED_POSITION) def run(self, edit): if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(orgDb.customids, self.on_done, -1, -1) else: self.view.window().show_quick_panel(orgDb.customids, self.on_done_st4, -1, -1) class OrgJumpToIdCommand(sublime_plugin.TextCommand): def on_done_st4(self, index, modifers): self.on_done(index) def on_done(self, index): if (index < 0 or index >= len(orgDb.ids)): return fid = orgDb.ids[index] file = fid.file id = fid.id at = file.org.env.ids[id][1] path = "{0}:{1}".format(file.filename, at + 1) self.view.window().open_file(path, sublime.ENCODED_POSITION) def run(self, edit): if (int(sublime.version()) <= 4096): self.view.window().show_quick_panel(orgDb.ids, self.on_done, -1, -1) else: self.view.window().show_quick_panel(orgDb.ids, self.on_done_st4, -1, -1) class OrgJumpToTodayCommand(sublime_plugin.TextCommand): def run(self, edit): file, at = Get().FindByCustomId("TODAY") path = "{0}:{1}".format(file.filename, at + 1) self.view.window().open_file(path, sublime.ENCODED_POSITION) ================================================ FILE: orgduration.py ================================================ from ctypes import ArgumentError import datetime import re import math import sublime_plugin # This library provides tools to manipulate durations. A duration # can have multiple formats: # # - 3:12 # - 1:23:45 # - 1y 3d 3h 4min # - 1d3h5min # - 3d 13:35 # - 2.35h # # More accurately, it consists of numbers and units, as defined in # variable `org-duration-units', possibly separated with white # spaces, and an optional "H:MM" or "H:MM:SS" part, which always # comes last. White spaces are tolerated between the number and its # relative unit. Variable `org-duration-format' controls durations # default representation. # # The library provides functions allowing to convert a duration to, # and from, a number of minutes: `org-duration-to-minutes' and # `org-duration-from-minutes'. It also provides two lesser tools: # `org-duration-p', and `org-duration-h:mm-only-p'. # # Users can set the number of minutes per unit, or define new units, # in `org-duration-units'. The library also supports canonical # duration, i.e., a duration that doesn't depend on user's settings, # through optional arguments. RE_DURATION_PARSER = re.compile(r'\s*((?P[0-9.]+)y)?\s*((?P[0-9.]+)d)?\s*((?P[0-9.]+)h)?\s*((?P[0-9.]+)min)?\s*((?P[0-9]+)[:](?P[0-9]+)([:](?P[0-9]+))?)?') class OrgDuration: def __init__(self, minutes): self.mins = minutes def __str__(self): r = "" y = int(self.mins / 525600.0) if (y > 0): r += str(y) + "y " days = math.fmod(self.mins, 525600.0) d = int(days / 1440.0) if (d > 0): r += str(d) + "d " hours = math.fmod(days, 1440.0) h = int(hours / 60.0) if (h > 0): r += str(h) + "h " mins = int(math.fmod(hours, 60)) if (mins > 0): r += str(mins) + "mins" return r.strip() def days(self): return self.mins / 1440.0 def months(self): return self.mins / 43800.0 def weeks(self): return self.mins / 10080.0 def hours(self): return self.mins / 60.0 def minutes(self): return self.mins def seconds(self): return self.mins * 60.0 def doubled(self): return OrgDuration(self.mins * 2.0) def __sub__(self, o): if (isinstance(o, int)): d = OrgDuration.ParseInt(o) mins = self.mins - d.mins d.mins = abs(mins) return d if (isinstance(o, float)): d = OrgDuration.ParseFloat(o) mins = self.mins - d.mins d.mins = abs(mins) return d if (isinstance(o, OrgDuration)): d = OrgDuration.ParseInt(1) d.mins = abs(self.mins - o.mins) return d return self def __add__(self, o): if (isinstance(o, int)): d = OrgDuration.ParseInt(o) mins = self.mins + d.mins d.mins = mins return d if (isinstance(o, float)): d = OrgDuration.ParseFloat(o) mins = self.mins + d.mins d.mins = mins return d if (isinstance(o, OrgDuration)): d = OrgDuration.ParseInt(1) d.mins = self.mins + o.mins return d return self def __div__(self, other): if (isinstance(other, int) or isinstance(other, float)): return OrgDuration(self.mins / other) return OrgDuration(self.mins) def __mul__(self, other): if isinstance(other, int) or isinstance(other, float): return OrgDuration(self.mins * other) return OrgDuration(self.mins) def __rmul__(self, other): return self.__mul__(other) def __radd__(self, other): return self.__add__(other) def __ne__(self, other): return not self.__eq__(other) def __gt__(self, other): if isinstance(other, int) or isinstance(other, float): return self.mins > other if isinstance(other, str): v = OrgDuration.Parse(other) if v is not None: return self.mins > v.mins else: raise ArgumentError(other + " is not a valid duration") if isinstance(other, OrgDuration): return self.mins > other.mins return False def __ge__(self, other): if isinstance(other, int) or isinstance(other, float): return self.mins >= other if isinstance(other, str): v = OrgDuration.Parse(other) if v is not None: return self.mins >= v.mins else: raise ArgumentError(other + " is not a valid duration") if isinstance(other, OrgDuration): return self.mins >= other.mins return False def __lt__(self, other): if isinstance(other, int) or isinstance(other, float): return self.mins < other if isinstance(other, str): v = OrgDuration.Parse(other) if v is not None: return self.mins < v.mins else: raise ArgumentError(other + " is not a valid duration") if isinstance(other, OrgDuration): return self.mins < other.mins return False def __le__(self, other): if isinstance(other, int) or isinstance(other, float): return self.mins <= other if isinstance(other, str): v = OrgDuration.Parse(other) if v is not None: return self.mins <= v.mins else: raise ArgumentError(other + " is not a valid duration") if isinstance(other, OrgDuration): return self.mins <= other.mins return False def timedelta(self): y = int(self.mins / 525600.0) days = math.fmod(self.mins, 525600.0) d = int(days / 1440.0) hours = math.fmod(days, 1440.0) h = int(hours / 60.0) mins = int(math.fmod(hours, 60)) td = datetime.timedelta(days=d + (y * 365), hours=h, minutes=mins) return td @staticmethod def FromTimedelta(td: datetime.timedelta): return OrgDuration(td.days * 1440 + (td.seconds / 60.0)) @staticmethod def Parse(txt: str, need: bool = False): m = RE_DURATION_PARSER.search(txt) if (m): mtot = 0.0 got = False y = m.group('years') if (y): mtot += float(y) * 525600.0 got = True d = m.group('days') if (d): mtot += float(d) * 1440 got = True h = m.group('hours') if (h): mtot += float(h) * 60 got = True mins = m.group('mins') if (mins): mtot += float(mins) got = True h = m.group('thours') if (h): mtot += float(h) * 60 got = True mins = m.group('tmins') if (mins): mtot += float(mins) got = True secs = m.group('tsecs') if (secs): mtot += float(secs) * 0.01666667 got = True if (got or not need): return OrgDuration(mtot) return None @staticmethod def ParseWeekDayOffset(txt: str): if (len(txt) < 3): return None change = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"] nextDay = txt.lower() nextOf = [idx for idx, element in enumerate(change) if element.startswith(nextDay)] if (len(nextOf) > 0): nextOf = nextOf[0] else: return None wd = datetime.datetime.now().weekday() if (wd >= nextOf): offset = 7 - wd + nextOf else: offset = nextOf - wd mtot = 0.0 if (offset != 0): mtot += float(offset) * 1440 return OrgDuration(mtot) return None @staticmethod def ParseMonthOffset(txt: str): if (len(txt) < 3): return None change = ["january", "febuary", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"] tokens = txt.split(' ') monthOffset = 0 dayOffset = 0 day = datetime.datetime.now().day for token in tokens: tk = token.lower() monthCheck = [idx for idx, element in enumerate(change) if element.startswith(tk)] if (len(monthCheck) > 0): monthOffset = (monthCheck[0] + 1) if tk.isnumeric(): dayOffset = int(tk) if (monthOffset == 0 and dayOffset == 0): return None if (dayOffset == 0): dayOffset = day dt = datetime.datetime.now().replace(month=monthOffset, day=dayOffset) offset = dt - datetime.datetime.now() mtot = 0.0 if ((offset.total_seconds() / 60.0) != 0): mtot += offset.total_seconds() / 60.0 return OrgDuration(mtot) return None @staticmethod def ParseInt(d: int): # Let the user determine default meaning d is the default mtot = float(d) * 1440 return OrgDuration(mtot) @staticmethod def ParseFloat(d: float): # Let the user determine default meaning d is the default mtot = float(d) * 1440 return OrgDuration(mtot) # ================================================================================ class OrgTestDurationCommand(sublime_plugin.TextCommand): def run(self, edit, onDone=None): d = OrgDuration.Parse("2y3d5h6min") print(str(d)) d = OrgDuration.Parse("1y") print(str(d)) d = OrgDuration.Parse("2d") print(str(d)) d = OrgDuration.Parse("3h") print(str(d)) d = OrgDuration.Parse("4min") print(str(d)) d = OrgDuration.Parse("1d 3:44") print(str(d)) d = OrgDuration.Parse("1d 4:55:55") print(str(d)) ================================================ FILE: orgdwim.py ================================================ import sublime import sublime_plugin import os import OrgExtended.orgparse.node as node from OrgExtended.orgparse.sublimenode import * import OrgExtended.orgutil.util as util import logging import sys import traceback import OrgExtended.orgdb as db import OrgExtended.asettings as sets import OrgExtended.orgcheckbox as checkbox import OrgExtended.orgnumberedlist as numberedlist import OrgExtended.orgdynamicblock as dynamic import OrgExtended.orgsourceblock as src import OrgExtended.orgediting as editing import OrgExtended.orgtableformula as tbl log = logging.getLogger(__name__) # ==================================================================== # Another Do What I Mean style command. # Contextually looks at where you are and "does the right thing." # All about inserting things state. class OrgGenericInsertCommand(sublime_plugin.TextCommand): def run(self, edit): line = self.view.curLine() cb = checkbox.get_checkbox(self.view, line) if(cb): self.view.run_command('org_insert_checkbox') return if(checkbox.isUnorderedList(self.view.substr(line))): self.view.run_command('org_insert_unordered_list') return if(numberedlist.isNumberedLine(self.view)): numberedlist.AppendLine(self.view, edit) return n = db.Get().AtInView(self.view) if(not n.is_root()): self.view.run_command('org_insert_heading_sibling') # ==================================================================== class OrgGenericInsertAuxCommand(sublime_plugin.TextCommand): def run(self, edit): line = self.view.curLine() cb = checkbox.get_checkbox(self.view, line) if(cb): self.view.run_command('org_insert_checkbox',{'insertHere': False}) return if(checkbox.isUnorderedList(self.view.substr(line))): self.view.run_command('org_insert_unordered_list',{'insertHere': False}) return if(numberedlist.isNumberedLine(self.view)): numberedlist.AppendLine(self.view, edit, insertHere=False) return n = db.Get().AtInView(self.view) if(not n.is_root()): self.view.run_command('org_insert_heading_child') # ==================================================================== # Another Do What I Mean style command. # Contextually looks at where you are and "does the right thing." # Recalculates checkboxes, recalculates blocks etc. class OrgRecalcCommand(sublime_plugin.TextCommand): def run(self, edit): if(dynamic.IsDynamicBlock(self.view)): self.view.run_command('org_execute_dynamic_block') return if(src.IsInlineSourceBlock(self.view)): self.view.run_command('org_execute_inline_source_block') return if(src.IsSourceBlock(self.view)): self.view.run_command('org_execute_source_block') return if(src.IsCallCommentBlock(self.view)): self.view.run_command('org_execute_call_comment') return if(tbl.isTable(self.view)): self.view.run_command('org_execute_table') return checkbox.recalculate_all_checkbox_summaries(self.view, edit) numberedlist.UpdateLine(self.view, edit) # ==================================================================== # Another Do What I Mean style command. # Contextually looks at where you are and "does the right thing." # All about toggling things state. class OrgToggleCommand(sublime_plugin.TextCommand): def run(self, edit): line = self.view.curLine() cb = checkbox.is_checkbox_line(self.view) #cb = checkbox.get_checkbox(self.view, line) if(cb): self.view.run_command('org_toggle_checkbox') return else: self.view.run_command('org_todo_change') # ==================================================================== class OrgChangeIndentCommand(sublime_plugin.TextCommand): def run(self, edit): line = self.view.curLine() cb = checkbox.get_checkbox(self.view, line) if(cb): editing.indent_list(self.view,self.view.curRow(), edit) return if(checkbox.isUnorderedList(self.view.substr(line))): editing.indent_list(self.view,self.view.curRow(), edit) return if(numberedlist.isNumberedLine(self.view)): editing.indent_list(self.view,self.view.curRow(), edit) return n = db.Get().AtInView(self.view) if(n and type(n) != node.OrgRootNode): editing.indent_node(self.view, n, edit) file = db.Get().FindInfo(self.view) file.LoadS(self.view) # ==================================================================== # This does not handle indention of sub trees! Need to fix that! class OrgChangeDeIndentCommand(sublime_plugin.TextCommand): def run(self, edit): line = self.view.curLine() cb = checkbox.get_checkbox(self.view, line) if(cb): editing.deindent_list(self.view,self.view.curRow(), edit) return if(checkbox.isUnorderedList(self.view.substr(line))): editing.deindent_list(self.view,self.view.curRow(), edit) return if(numberedlist.isNumberedLine(self.view)): editing.deindent_list(self.view,self.view.curRow(), edit) return n = db.Get().AtInView(self.view) if(n and type(n) != node.OrgRootNode): editing.deindent_node(self.view, n, edit) file = db.Get().FindInfo(self.view) file.LoadS(self.view) ================================================ FILE: orgdynamic/clocktable.py ================================================ import sublime import OrgExtended.orgdb as db import OrgExtended.orgparse.date as d # This is a placeholder clocktable dynamic block def setup_heading(output,level): title = "|Heading|Time|" + ('|' * (level-1)) output.append(title) output.append("|-") def handle_heading(skip, node, clevel, level): #print("H: " + node.heading) skipstr = "" if(skip > 0): skipstr = ("|" * skip) clevelskip = "" if(clevel > 0): clevelskip = "|" * clevel difflevel = level - clevel - 1 difflevelskip = "" if(difflevel > 0): difflevelskip = "|" * difflevel hindent = "" if(clevel > 0): hindent = r'\_' if(clevel > 1): hindent = hindent + ('__' * (clevel - 1)) if(hindent != ""): hindent = hindent + " " return "{0}|{1}|{2}{3}{4}|".format(skipstr,hindent + node.heading,clevelskip,d.OrgDate.format_duration(node.duration()),difflevelskip) def handle_subheading(output, skip, view, node, params, clevel, level): output.append(handle_heading(skip, node, clevel, level)) for c in node.children: handle_subheading(output, skip, view, c, params, clevel+1, level) def handle_subtree(view, params, level): node = db.Get().AtInView(view) output = [] setup_heading(output, level) output.append(handle_heading(0, node, 0, level)) for c in node.children: handle_subheading(output, 0, view, c, params, 1, level) return output def get_level(params): level = params.GetInt('maxlevel',2) if(level < 2): level = 2 return level def Execute(view, params): level = get_level(params) if(params.Get('scope','subtree') == 'subtree'): return handle_subtree(view, params, level) else: print(params['scope'] + " is not implemented") file = db.Get().FindInfo(view) if(file): r = file.org for n in r.children: n.duration() output = [] output.append("|Heading|Time|") output.append("|-") output.append("|A|B|") return output def PostExecute(view, params, region): row,col = view.rowcol(view.sel()[0].begin()) view.sel().clear() view.sel().add(view.text_point(row+1,col)) view.run_command("table_editor_next_field") ================================================ FILE: orgdynamic/columnview.py ================================================ import os import re import OrgExtended.orgdb as db def GetLevel(params): level = params.GetInt('maxlevel',2) if(level < 2): level = 2 return level def HandleItem(params,n,defs,output,depth,maxdepth): if(maxdepth > 0 and depth > maxdepth): return out = [] emptyCount = 0 for d in defs: v = str(d.GetCellValue(n,params)).strip() emptyCount += 1 if v == "" else 0 out.append(v) ok = True exclude = params.GetList('exclude-tags',[]) for e in exclude: if(e in n.tags): ok = False break if(params.Get('skip-empty-rows','nil') != 'nil'): ok = ok and emptyCount < (len(defs)-1) if(ok): v = params.Get('hlines','nil') if(v == 't'): output.append(["-"]) elif(v != 'nil' and v != ""): v = int(v) if(depth <= v): output.append(["-"]) output.append(out) for c in n.children: HandleItem(params,c,defs,output,depth+1,maxdepth) def HandleHeadings(defs,output): out = "|" for d in defs: out += d.Heading() + "|" output.append(out) class ColumnHandler: def Setup(self,width,propName,heading,summary): self.width = width self.name = propName if(heading): self.heading = heading else: self.heading = propName self.summary = summary def Heading(self): return self.heading class ItemHandler(ColumnHandler): def GetCellValue(self,n,params): indent = "" if(params.Get('indent','') == 't'): indent = '..' * (n.level-1) return indent + n.heading class DeadlineHandler(ColumnHandler): def GetCellValue(self,n,params): return n.deadline.format_datetime_str() if n.deadline else "" class ClosedHandler(ColumnHandler): def GetCellValue(self,n,params): return n.closed.format_datetime_str() if n.closed else "" class ScheduledHandler(ColumnHandler): def GetCellValue(self,n,params): return n.scheduled.format_datetime_str() if n.scheduled else "" class TimestampHandler(ColumnHandler): def GetCellValue(self,n,params): ts = n.get_timestamps(active=True, inactive=False, range=True, point=True) if(ts and len(ts) >= 1): return ts[0].format_datetime_str() return "" class IATimestampHandler(ColumnHandler): def GetCellValue(self,n,params): ts = n.get_timestamps(active=False, inactive=True, range=True, point=True) if(ts and len(ts) >= 1): return ts[0].format_datetime_str() return "" class PriorityHandler(ColumnHandler): def GetCellValue(self,n,params): return n.priority if n.priority else "" class TodoHandler(ColumnHandler): def GetCellValue(self,n,params): return n.todo if n.todo else "" class AllTagsHandler(ColumnHandler): def GetCellValue(self,n,params): return ' '.join(n.tags) if n.tags else "" class TagsHandler(ColumnHandler): def GetCellValue(self,n,params): return ' '.join(n.shallow_tags) if n.shallow_tags else "" class FilenameHandler(ColumnHandler): def GetCellValue(self,n,params): return os.path.basename(n.env.filename) class PropertyHandler(ColumnHandler): def GetCellValue(self,n,params): v = n.get_property(self.name,None) if(not v): v = n.get_property(self.name.upper(),None) if(not v): v = n.get_property(self.name.lower(),"") return v special_registry = { #‘ITEM’ The headline of the entry. "ITEM": ItemHandler, #‘PRIORITY’ The priority of the entry, a string with a single letter. "PRIORITY": PriorityHandler, #‘CLOSED’ When was this entry closed? "CLOSED": ClosedHandler, #‘SCHEDULED’ The scheduling timestamp. "SCHEDULED": ScheduledHandler, #‘TODO’ The TODO keyword of the entry. "TODO": TodoHandler, #‘DEADLINE’ The deadline timestamp. "DEADLINE": DeadlineHandler, #‘ALLTAGS’ All tags, including inherited ones. "ALLTAGS": AllTagsHandler, #‘FILE’ The filename the entry is located in. "FILE": FilenameHandler, #‘TAGS’ The tags defined directly in the headline. "TAGS": TagsHandler, #‘TIMESTAMP’ The first keyword-less timestamp in the entry. "TIMESTAMP": TimestampHandler, #‘TIMESTAMP_IA’ The first inactive timestamp in the entry. "TIMESTAMP_IA": IATimestampHandler, } #‘BLOCKED’ t if task is currently blocked by children or siblings. #‘CATEGORY’ The category of an entry. #‘CLOCKSUM’ The sum of CLOCK intervals in the subtree. org-clock-sum # must be run first to compute the values in the current buffer. #‘CLOCKSUM_T’ The sum of CLOCK intervals in the subtree for today. # org-clock-sum-today must be run first to compute the # values in the current buffer. #%[WIDTH]PROPERTY[(TITLE)][{SUMMARY-TYPE}] RE_PARSER = re.compile(r"[%](?P[0-9]+)?(?P[a-zA-Z][a-zA-Z0-9_-]+)([(](?P([a-zA-Z0-9 +-]|\s)+)[)])?(?P[^ ())]+)?") def GetColumnDefinitions(f,node): columns = node.list_comment("COLUMNS",[r"%70ITEM(Task)",r"%17Effort(Effort)"]) h = [] for item in columns: m = RE_PARSER.search(item) if(m): width = m.group('width') if(width and width != ""): width = int(width) else: width = 0 prop = m.group('prop') heading = m.group('heading') summary = m.group('summary') if(prop in special_registry): cfactory = special_registry[prop] else: cfactory = PropertyHandler v = cfactory() v.Setup(width,prop,heading,summary) h.append(v) return h def Execute(view, params): # This is the most crucial parameter it defines how # we will process nodes. id = params.Get('id',"global") # How far down the tree do we allow? maxdepth = params.GetInt('maxdepth',0) # We accumulate output in here line by line for insertion # into the main buffer. output = [] # By default we operate in the current file off the current view # Look it up in the DB. This will also reload it if it is dirty. file = db.Get().FindInfo(view) if(file): node = db.Get().AtInView(view) defs = GetColumnDefinitions(file,node) r = file.org # Local we search up till we find the node parent that is not the root if(id == 'local'): if(node): while(node and node.parent and node.parent.parent): node = node.parent r = node # Operate on all children of the root (default) elif(id == 'global'): pass # Operate on the root of another file in the db elif('file:' in id): files = id.split(':') file = db.Get().FindFileByFilename(files[1].strip()) r = file.org # Operate on a node marked with an ID or CUSTOM_ID # ONLY if found in the DB. else: r = db.Get().FindNodeByAnyId(id) # Output the headings of our table based on the fields and handlers # we found in our COLUMNS definition. HandleHeadings(defs,output) # If we had a root, run over it and process it's children # building up our output array. outarrays = [] if(r): for n in r.children: HandleItem(params,n,defs,outarrays,1,maxdepth) # Did we get some output? return it if(len(outarrays) > 0): for o in outarrays: out = "|" + '|'.join(o) + "|" output.append(out) return output # Nope add a generic error so we know we failed getting output at all... output.append("|NO COLUMNVIEW DATA|") return output def PostExecute(view, params, region): # We wrote our data to the buffer, get the TableEditor to # align our data for us. row,col = view.rowcol(view.sel()[0].begin()) view.sel().clear() view.sel().add(view.text_point(row+1,col)) view.run_command("table_editor_next_field") ================================================ FILE: orgdynamic/insertdatetime.py ================================================ import sublime import datetime def Execute(view, params): return [str(datetime.datetime.now())] ================================================ FILE: orgdynamicblock.py ================================================ import sublime import sublime_plugin import datetime import re from pathlib import Path import os import fnmatch import OrgExtended.orgparse.node as node from OrgExtended.orgparse.sublimenode import * import OrgExtended.orgutil.util as util import OrgExtended.orgutil.navigation as nav import OrgExtended.orgutil.template as templateEngine import logging import sys import traceback import OrgExtended.orgfolding as folding import OrgExtended.orgdb as db import OrgExtended.asettings as sets import OrgExtended.orgcapture as capture import OrgExtended.orglinks as links import OrgExtended.orgclocking as clocking import OrgExtended.orgextension as ext import OrgExtended.pymitter as evt from OrgExtended.orgplist import * import importlib log = logging.getLogger(__name__) RE_END = re.compile(r"^\s*\#\+(END|end)[:]") RE_DYN_BLOCK = re.compile(r"^\s*\#\+(BEGIN|begin)[:]\s+(?P[^: ]+)\s*") RE_FN_MATCH = re.compile(r"\s+[:]([a-zA-Z][a-zA-Z0-9-_]+)\s+(([^ ()]+)|([(][^)]+[)]))") def IsDynamicBlock(view): line = view.getLine(view.curRow()) return RE_DYN_BLOCK.search(line) or RE_END.search(line) class OrgExecuteDynamicBlockCommand(sublime_plugin.TextCommand): def on_replaced(self): if(hasattr(self.curmod,"PostExecute")): self.curmod.PostExecute(self.view, self.params, self.region) def run(self, edit): view = self.view at = view.sel()[0] if(view.match_selector(at.begin(),'orgmode.fence.dynamicblock')): # Okay we have a dynamic block, now we need to know where it ends. start = at.begin() end = None erow = view.endRow() row = view.curRow() for rw in range(row,erow+1): line = view.substr(view.line(view.text_point(rw,0))) if(RE_END.search(line)): end = rw break if(not end): log.debug("Could not locate #+END: tag") return # Okay now we have a start and end to build a region out of. # time to run a command and try to get the output. dynamic = ext.find_extension_modules('orgdynamic', ["insertdatetime", "clocktable", "columnview"]) line = view.substr(view.line(start)) m = RE_DYN_BLOCK.search(line) if(not m): log.error("FAILED TO PARSE DYNAMIC BLOCK: " + line) return fnname = m.group('name') #log.debug("DYN NAME: " + fnname) params = PList.createPList(line[len(m.group(0)):]) # Now find me that function! if(fnname not in dynamic): log.error("Function not found in dynamic folder! Cannot execute!") return # Run the "writer" if(hasattr(dynamic[fnname],"Execute")): self.curmod = dynamic[fnname] self.params = params outputs = self.curmod.Execute(view, params) #log.debug("OUTPUT: " + str(outputs)) # Okay now time to replace the contents of the block s = view.text_point(row+1,0) e = view.text_point(end,0) self.region = sublime.Region(s,e) # Reformat adding indents to each line! # No bad formatting allowed! n = db.Get().AtInView(view) level = n.level indent = "\n"+ (" " * level) + " " #outputs = output.split('\n') output = indent.join(outputs) print(output) self.view.run_command("org_internal_replace", {"start": s, "end": e, "text": (" " * level + " ") + output+"\n","onDone": evt.Make(self.on_replaced)}) else: log.error("NOT in A DynamicBlock, nothing to run") ================================================ FILE: orgediting.py ================================================ import sublime import sublime_plugin import datetime import re from pathlib import Path import os import fnmatch import OrgExtended.orgparse.loader as loader import OrgExtended.orgparse.node as node import OrgExtended.orgparse.date as orgdate from OrgExtended.orgparse.sublimenode import * import OrgExtended.orgutil.util as util import OrgExtended.orgutil.navigation as nav import OrgExtended.orgutil.template as templateEngine import logging import sys import traceback import OrgExtended.orgfolding as folding import OrgExtended.orgdb as db import OrgExtended.asettings as sets import OrgExtended.pymitter as evt import OrgExtended.orgproperties as props import OrgExtended.orgdatepicker as datep import OrgExtended.orginsertselected as insSel import OrgExtended.orglinks as orglink import OrgExtended.orgneovi as nvi import OrgExtended.orgagenda as oa import OrgExtended.orgcheckbox as checkbox import OrgExtended.orgnumberedlist as numberedlist log = logging.getLogger(__name__) # MOVING TO ANY DONE STATE: # Support these: #+STARTUP: lognotedone Prompt and stored below the item with a Closing Note heading. #+STARTUP: logdone CLOSED: [TIMESTAMP] in LOGBOOK # As well as configuration options # # PER TRANSITON MOVEMENT: # @ - note # ! - timestamp # / - when leaving the state if next state doesn't log # # Then they go futher with: :LOGGING: WAIT(@) logrepeat properties # # - 1) We need the transitions recorded in the node (in the todos list) # - 2) We need a method to insert CLOSED: and or prompt and note # - 3) We need to track the state transitions themselves (from / to) # # - 4) Habits break all this with LAST_REPEAT and To From transition text. # RE_CLOSED = re.compile(r"^\s*CLOSED:\s*\[.*\]") def LocateClosed(view,node): for row in range(node.start_row, node.local_end_row + 1): pt = view.text_point(row,0) line = view.line(pt) lstr = view.substr(line) m = RE_CLOSED.search(lstr) if(m): return line return None def InsertClosed(view, node, onDone=None): stamp = OrgDate.format_clock(datetime.datetime.now(),active=False) closedPt = LocateClosed(view,node) if(closedPt): text = node.indent() + "CLOSED: " + stamp view.ReplaceRegion(closedPt, text, onDone) else: row = node.start_row+1 pt = view.text_point(row,0) newline = "\n" if view.isBeyondLastRow(row) else "" text = newline + node.indent() + "CLOSED: " + stamp + "\n" view.Insert(pt, text, onDone) #props.UpdateLogbook(view,node, "CLOSED:", stamp) def RemoveClosed(view, node, onDone=None): closedPt = LocateClosed(view, node) if(closedPt): view.ReplaceRegion(closedPt.IncEnd(),"",onDone) #view.run_command("org_internal_replace", {"start": closedPt.begin(), "end": closedPt.end() + 1, "text": "", "onDone": onDone}) else: evt.EmitIf(onDone) def IsDoneState(node, toState): return toState in node.env.done_keys def ShouldRecur(node, fromState, toState): if(IsDoneState(node, toState)): if(node.scheduled and node.scheduled.repeating): return node.scheduled if(node.deadline and node.deadline.repeating): return node.deadline timestamps = node.get_timestamps(active=True,point=True,range=True) for t in timestamps: if(t and t.repeating): return t return None def ShouldClose(node, fromState, toState): if(ShouldRecur(node,fromState,toState)): return False # NOTE: We need to get the todo transitions # into this as well! toState = toState.strip() startup = node.root.startup() logDone = sets.Get("logDone",None) if(IsDoneState(node, toState) and (Startup.logdone in startup or logDone)): return True def InsertRecurrence(view, node, fromState, toState, onDone=None): # - State "DONE" from "TODO" [2009-09-29 Tue]" stamp = OrgDate.format_clock(datetime.datetime.now(),active=False) def OnLogAdded(): props.UpdateProperty(view, node, "LAST_REPEAT", stamp, onDone) props.AddLogbook(view,node, "- State {0:12} from {1:12} ".format('"' + toState + '"', '"' + fromState + '"'), stamp, evt.Make(OnLogAdded)) def InsertNote(view, node, text, fromState, toState, onDone=None): stamp = OrgDate.format_clock(datetime.datetime.now(),active=False) props.AddLogbook(view,node, "Note (to:{0},at:{1}): ".format(toState,stamp), text, onDone) def ShouldNote(node, fromState, toState): if(ShouldRecur(node,fromState,toState)): return False # NOTE: We need to get the todo transitions # into this as well! toState = toState.strip() startup = node.root.startup() if(IsDoneState(node,toState) and Startup.lognotedone in startup): return True RE_T = re.compile(r'\s(?P