Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orgmode fixes and improvements, closes #2405 #2504

Merged
merged 2 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.gsantner.markor.format.markdown.MarkdownSyntaxHighlighter;
import net.gsantner.markor.format.markdown.MarkdownTextConverter;
import net.gsantner.markor.format.orgmode.OrgmodeActionButtons;
import net.gsantner.markor.format.orgmode.OrgmodeReplacePatternGenerator;
import net.gsantner.markor.format.orgmode.OrgmodeSyntaxHighlighter;
import net.gsantner.markor.format.orgmode.OrgmodeTextConverter;
import net.gsantner.markor.format.plaintext.PlaintextActionButtons;
Expand Down Expand Up @@ -184,8 +185,8 @@ public static FormatRegistry getFormat(int formatId, @NonNull final Context cont
format._converter = CONVERTER_ORGMODE;
format._highlighter = new OrgmodeSyntaxHighlighter(appSettings);
format._textActions = new OrgmodeActionButtons(context, document);
format._autoFormatInputFilter = new AutoTextFormatter(MarkdownReplacePatternGenerator.formatPatterns);
format._autoFormatTextWatcher = new ListHandler(MarkdownReplacePatternGenerator.formatPatterns);
format._autoFormatInputFilter = new AutoTextFormatter(OrgmodeReplacePatternGenerator.formatPatterns);
format._autoFormatTextWatcher = new ListHandler(OrgmodeReplacePatternGenerator.formatPatterns);
break;
}
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import net.gsantner.markor.R;
import net.gsantner.markor.format.ActionButtonBase;
import net.gsantner.markor.format.markdown.MarkdownReplacePatternGenerator;
import net.gsantner.markor.format.orgmode.OrgmodeReplacePatternGenerator;
import net.gsantner.markor.frontend.textview.AutoTextFormatter;
import net.gsantner.markor.model.Document;

Expand Down Expand Up @@ -35,7 +35,10 @@ public List<ActionItem> getFormatActionList() {
new ActionItem(R.string.abid_orgmode_italic, R.drawable.ic_format_italic_black_24dp, R.string.italic),
new ActionItem(R.string.abid_orgmode_strikeout, R.drawable.ic_format_strikethrough_black_24dp, R.string.strikeout),
new ActionItem(R.string.abid_orgmode_underline, R.drawable.ic_format_underlined_black_24dp, R.string.underline),
new ActionItem(R.string.abid_orgmode_code_inline, R.drawable.ic_code_black_24dp, R.string.inline_code)
new ActionItem(R.string.abid_orgmode_code_inline, R.drawable.ic_code_black_24dp, R.string.inline_code),
new ActionItem(R.string.abid_orgmode_h1, R.drawable.format_header_1, R.string.heading_1),
new ActionItem(R.string.abid_orgmode_h2, R.drawable.format_header_2, R.string.heading_2),
new ActionItem(R.string.abid_orgmode_h3, R.drawable.format_header_3, R.string.heading_3)
);
}

Expand All @@ -47,13 +50,39 @@ int getFormatActionsKey() {

@Override
protected void renumberOrderedList() {
// Use markdown format for orgmode too
AutoTextFormatter.renumberOrderedList(_hlEditor.getText(), MarkdownReplacePatternGenerator.formatPatterns);
AutoTextFormatter.renumberOrderedList(_hlEditor.getText(), OrgmodeReplacePatternGenerator.formatPatterns);
}

@Override
public boolean onActionClick(final @StringRes int action) {
switch (action) {
case R.string.abid_orgmode_h1: {
runRegexReplaceAction(OrgmodeReplacePatternGenerator.setOrUnsetHeadingWithLevel(1));
return true;
}
case R.string.abid_orgmode_h2: {
runRegexReplaceAction(OrgmodeReplacePatternGenerator.setOrUnsetHeadingWithLevel(2));
return true;
}
case R.string.abid_orgmode_h3: {
runRegexReplaceAction(OrgmodeReplacePatternGenerator.setOrUnsetHeadingWithLevel(3));
return true;
}
case R.string.abid_common_unordered_list_char: {
final String listChar = _appSettings.getUnorderedListCharacter();
runRegexReplaceAction(OrgmodeReplacePatternGenerator.replaceWithUnorderedListPrefixOrRemovePrefix(listChar));
return true;
}
case R.string.abid_common_checkbox_list: {
final String listChar = _appSettings.getUnorderedListCharacter();
runRegexReplaceAction(OrgmodeReplacePatternGenerator.toggleToCheckedOrUncheckedListPrefix(listChar));
return true;
}
case R.string.abid_common_ordered_list_number: {
runRegexReplaceAction(OrgmodeReplacePatternGenerator.replaceWithOrderedListPrefixOrRemovePrefix());
runRenumberOrderedListIfRequired();
return true;
}
case R.string.abid_orgmode_bold: {
runSurroundAction("*");
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*#######################################################
*
* Maintained 2018-2025 by Gregor Santner <gsantner AT mailbox DOT org>
* License of this file: Apache 2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
#########################################################*/
package net.gsantner.markor.format.orgmode;

import android.util.Log;

import net.gsantner.markor.format.ActionButtonBase;
import net.gsantner.markor.frontend.textview.AutoTextFormatter;
import net.gsantner.markor.frontend.textview.ReplacePatternGeneratorHelper;
import net.gsantner.opoc.format.GsTextUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class OrgmodeReplacePatternGenerator {

// TODO: write tests

public static final Pattern PREFIX_ORDERED_LIST = Pattern.compile("^(\\s*)((\\d+)(\\.|\\))(\\s))");
public static final Pattern PREFIX_ATX_HEADING = Pattern.compile("^(\\s{0,3})(\\*+\\s)");
public static final Pattern PREFIX_CHECKED_LIST = Pattern.compile("^(\\s*)((-|\\+)\\s\\[(X)]\\s)");
public static final Pattern PREFIX_CHECKBOX_LIST = Pattern.compile("^(\\s*)(([-+]\\s\\[)[\\sX](]\\s))");
public static final Pattern PREFIX_UNCHECKED_LIST = Pattern.compile("^(\\s*)((-|\\+)\\s\\[\\s]\\s)");
public static final Pattern PREFIX_UNORDERED_LIST = Pattern.compile("^(\\s*)((-|\\+)\\s)");
public static final Pattern PREFIX_LEADING_SPACE = Pattern.compile("^(\\s*)");

public static final AutoTextFormatter.FormatPatterns formatPatterns = new AutoTextFormatter.FormatPatterns(
OrgmodeReplacePatternGenerator.PREFIX_UNORDERED_LIST,
OrgmodeReplacePatternGenerator.PREFIX_CHECKBOX_LIST,
OrgmodeReplacePatternGenerator.PREFIX_ORDERED_LIST,
2);

public static final Pattern[] PREFIX_PATTERNS = {
PREFIX_ORDERED_LIST,
PREFIX_ATX_HEADING,
PREFIX_CHECKED_LIST,
PREFIX_UNCHECKED_LIST,
// Unordered has to be after checked list. Otherwise checklist will match as an unordered list.
PREFIX_UNORDERED_LIST,
PREFIX_LEADING_SPACE,
};

private final static String ORDERED_LIST_REPLACEMENT = "$11. ";

/**
* Set/unset ATX heading level on each selected line
* <p>
* This routine will make the following conditional changes
* <p>
* Line is heading of same level as requested -> remove heading
* Line is heading of different level that that requested -> add heading of specified level
* Line is not heading -> add heading of specified level
*
* @param level ATX heading level
*/
public static List<ActionButtonBase.ReplacePattern> setOrUnsetHeadingWithLevel(int level) {

List<ActionButtonBase.ReplacePattern> patterns = new ArrayList<>();

String heading = "\\*".repeat(level);

// Replace this exact heading level with nothing
patterns.add(new ActionButtonBase.ReplacePattern("^(\\s{0,3})" + heading + " ", "$1"));

// Replace other headings with commonmark-compatible leading space
patterns.add(new ActionButtonBase.ReplacePattern(OrgmodeReplacePatternGenerator.PREFIX_ATX_HEADING, "$1" + heading + " "));

// Replace all other prefixes with heading
for (final Pattern pp : OrgmodeReplacePatternGenerator.PREFIX_PATTERNS) {
patterns.add(new ActionButtonBase.ReplacePattern(pp, heading + "$1 "));
}

return patterns;
}

public static List<ActionButtonBase.ReplacePattern> replaceWithUnorderedListPrefixOrRemovePrefix(String listChar) {
final String unorderedListReplacement = "$1" + listChar + " ";
return ReplacePatternGeneratorHelper.replaceWithTargetPrefixOrRemove(PREFIX_PATTERNS, PREFIX_UNORDERED_LIST, unorderedListReplacement);
}

public static List<ActionButtonBase.ReplacePattern> toggleToCheckedOrUncheckedListPrefix(String listChar) {
final String unchecked = "$1" + listChar + " [ ] ";
final String checked = "$1" + listChar + " [X] ";
return ReplacePatternGeneratorHelper.replaceWithTargetPatternOrAlternative(PREFIX_PATTERNS, PREFIX_UNCHECKED_LIST, unchecked, checked);
}

public static List<ActionButtonBase.ReplacePattern> replaceWithOrderedListPrefixOrRemovePrefix() {
return ReplacePatternGeneratorHelper.replaceWithTargetPrefixOrRemove(PREFIX_PATTERNS, PREFIX_ORDERED_LIST, ORDERED_LIST_REPLACEMENT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
import java.util.regex.Pattern;

public class OrgmodeSyntaxHighlighter extends SyntaxHighlighterBase {
public final static String COMMON_EMPHASIS_PATTERN = "(?<=(\\n|^|\\s|\\{|\\())([%s])(?=\\S)(.*?)\\S\\2(?=(\\n|$|\\s|\\.|,|:|;|-|\\}|\\)))";
public final static String COMMON_EMPHASIS_PATTERN = "(?<=(\\n|^|\\s|\\{|\\())([%s])(?=\\S)(?!\\2+\\2)(.*?)\\S\\2(?=(\\n|$|\\s|\\.|,|:|;|-|\\}|\\)))";
public final static Pattern BOLD = Pattern.compile(String.format(COMMON_EMPHASIS_PATTERN, "*"));
public final static Pattern ITALICS = Pattern.compile(String.format(COMMON_EMPHASIS_PATTERN, "/"));
public final static Pattern STRIKETHROUGH = Pattern.compile(String.format(COMMON_EMPHASIS_PATTERN, "+"));
public final static Pattern UNDERLINE = Pattern.compile(String.format(COMMON_EMPHASIS_PATTERN, "_"));
public final static Pattern CODE_INLINE = Pattern.compile(String.format(COMMON_EMPHASIS_PATTERN, "=~"));
public final static Pattern HEADING = Pattern.compile("(?m)^(\\*+)\\s(.*?)(?=\\n|$)");
public final static Pattern HEADING = Pattern.compile("(?m)^(\\*+) (.*?)(?=\\n|$)");
public final static Pattern BLOCK = Pattern.compile("(?m)(?<=#\\+BEGIN_.{1,15}$\\s)[\\s\\S]*?(?=#\\+END)");
public final static Pattern PREAMBLE = Pattern.compile("(?m)^(#\\+)(.*?)(?=\\n|$)");
public final static Pattern COMMENT = Pattern.compile("(?m)^(#+)\\s(.*?)(?=\\n|$)");
public final static Pattern LIST_UNORDERED = Pattern.compile("(\\n|^)\\s{0,16}([*+-])( \\[[ xX]\\])?(?= )");
public final static Pattern COMMENT = Pattern.compile("(?m)^(#+) (.*?)(?=\\n|$)");
public final static Pattern LIST_UNORDERED = Pattern.compile("(\\n|^)\\s{0,16}([+-])( \\[[ X]\\])?(?= )");
public final static Pattern LIST_ORDERED = Pattern.compile("(?m)^\\s{0,16}(\\d+)(:?\\.|\\))\\s");
public final static Pattern LINK = Pattern.compile("\\[\\[.*?]]|<.*?>|https?://\\S+|\\[.*?]\\[.*?]|\\[.*?]\n");
private static final int ORG_COLOR_HEADING = 0xffef6D00;
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/res/values/string-not_translatable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,10 @@ work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
<string name="abid_todotxt_due_date" translatable="false">abid_todotxt_due_date</string>
<string name="abid_todotxt_sort_todo" translatable="false">abid_todotxt_sort_todo</string>



<string name="abid_orgmode_h1" translatable="false">abid_orgmode_h1</string>
<string name="abid_orgmode_h2" translatable="false">abid_orgmode_h2</string>
<string name="abid_orgmode_h3" translatable="false">abid_orgmode_h3</string>
<string name="abid_orgmode_bold" translatable="false">abid_orgmode_bold</string>
<string name="abid_orgmode_italic" translatable="false">abid_orgmode_italic</string>
<string name="abid_orgmode_strikeout" translatable="false">abid_orgmode_strikeout</string>
Expand Down
Loading