Add a config option for org-list-allow-alphabetical.
This fixes an issue where lines in a paragraph were incorrectly getting identified as lists because I had defaulted to assuming alphabetical bullets were allowed.
This commit is contained in:
		
							parent
							
								
									ac0db64081
								
							
						
					
					
						commit
						33372429dd
					
				| @ -12,6 +12,10 @@ pub struct GlobalSettings<'g, 's> { | ||||
|     pub file_access: &'g dyn FileAccessInterface, | ||||
|     pub in_progress_todo_keywords: BTreeSet<String>, | ||||
|     pub complete_todo_keywords: BTreeSet<String>, | ||||
|     /// Set to true to allow for plain lists using single letters as the bullet in the same way that numbers are used.
 | ||||
|     ///
 | ||||
|     /// Corresponds to the org-list-allow-alphabetical elisp variable.
 | ||||
|     pub org_list_allow_alphabetical: bool, | ||||
| } | ||||
| 
 | ||||
| impl<'g, 's> GlobalSettings<'g, 's> { | ||||
| @ -23,6 +27,7 @@ impl<'g, 's> GlobalSettings<'g, 's> { | ||||
|             }, | ||||
|             in_progress_todo_keywords: BTreeSet::new(), | ||||
|             complete_todo_keywords: BTreeSet::new(), | ||||
|             org_list_allow_alphabetical: false, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -141,7 +141,7 @@ fn _detect_element<'b, 'g, 'r, 's>( | ||||
|     can_be_paragraph: bool, | ||||
| ) -> Res<OrgSource<'s>, ()> { | ||||
|     if alt(( | ||||
|         detect_plain_list, | ||||
|         parser_with_context!(detect_plain_list)(context), | ||||
|         detect_footnote_definition, | ||||
|         detect_diary_sexp, | ||||
|         detect_comment, | ||||
|  | ||||
| @ -41,12 +41,15 @@ use crate::types::PlainList; | ||||
| use crate::types::PlainListItem; | ||||
| 
 | ||||
| #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] | ||||
| pub(crate) fn detect_plain_list<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> { | ||||
| pub(crate) fn detect_plain_list<'b, 'g, 'r, 's>( | ||||
|     context: RefContext<'b, 'g, 'r, 's>, | ||||
|     input: OrgSource<'s>, | ||||
| ) -> Res<OrgSource<'s>, ()> { | ||||
|     if verify( | ||||
|         tuple(( | ||||
|             start_of_line, | ||||
|             space0, | ||||
|             bullet, | ||||
|             parser_with_context!(bullet)(context), | ||||
|             alt((space1, line_ending, eof)), | ||||
|         )), | ||||
|         |(_start, indent, bull, _after_whitespace)| { | ||||
| @ -145,12 +148,17 @@ fn plain_list_item<'b, 'g, 'r, 's>( | ||||
|     let (remaining, leading_whitespace) = space0(input)?; | ||||
|     // It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
 | ||||
|     let indent_level = leading_whitespace.len(); | ||||
|     let (remaining, bull) = verify(bullet, |bull: &OrgSource<'_>| { | ||||
|         Into::<&str>::into(bull) != "*" || indent_level > 0 | ||||
|     })(remaining)?; | ||||
|     let (remaining, bull) = verify( | ||||
|         parser_with_context!(bullet)(context), | ||||
|         |bull: &OrgSource<'_>| Into::<&str>::into(bull) != "*" || indent_level > 0, | ||||
|     )(remaining)?; | ||||
| 
 | ||||
|     let (remaining, _maybe_counter_set) = | ||||
|         opt(tuple((space1, tag("[@"), counter, tag("]"))))(remaining)?; | ||||
|     let (remaining, _maybe_counter_set) = opt(tuple(( | ||||
|         space1, | ||||
|         tag("[@"), | ||||
|         parser_with_context!(counter)(context), | ||||
|         tag("]"), | ||||
|     )))(remaining)?; | ||||
| 
 | ||||
|     // TODO: parse checkbox
 | ||||
| 
 | ||||
| @ -228,18 +236,36 @@ fn plain_list_item<'b, 'g, 'r, 's>( | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] | ||||
| fn bullet<'s>(i: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { | ||||
| fn bullet<'b, 'g, 'r, 's>( | ||||
|     context: RefContext<'b, 'g, 'r, 's>, | ||||
|     input: OrgSource<'s>, | ||||
| ) -> Res<OrgSource<'s>, OrgSource<'s>> { | ||||
|     alt(( | ||||
|         tag("*"), | ||||
|         tag("-"), | ||||
|         tag("+"), | ||||
|         recognize(tuple((counter, alt((tag("."), tag(")")))))), | ||||
|     ))(i) | ||||
|         recognize(tuple(( | ||||
|             parser_with_context!(counter)(context), | ||||
|             alt((tag("."), tag(")"))), | ||||
|         ))), | ||||
|     ))(input) | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] | ||||
| fn counter<'s>(i: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { | ||||
|     alt((recognize(one_of("abcdefghijklmnopqrstuvwxyz")), digit1))(i) | ||||
| fn counter<'b, 'g, 'r, 's>( | ||||
|     context: RefContext<'b, 'g, 'r, 's>, | ||||
|     input: OrgSource<'s>, | ||||
| ) -> Res<OrgSource<'s>, OrgSource<'s>> { | ||||
|     if context.get_global_settings().org_list_allow_alphabetical { | ||||
|         alt(( | ||||
|             recognize(one_of( | ||||
|                 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", | ||||
|             )), | ||||
|             digit1, | ||||
|         ))(input) | ||||
|     } else { | ||||
|         digit1(input) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] | ||||
| @ -558,21 +584,30 @@ dolar"#, | ||||
|             r#"+
 | ||||
| "#,
 | ||||
|         ); | ||||
|         let result = detect_plain_list(input); | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let result = detect_plain_list(&initial_context, input); | ||||
|         assert!(result.is_ok()); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn detect_eof() { | ||||
|         let input = OrgSource::new(r#"+"#); | ||||
|         let result = detect_plain_list(input); | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let result = detect_plain_list(&initial_context, input); | ||||
|         assert!(result.is_ok()); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn detect_no_gap() { | ||||
|         let input = OrgSource::new(r#"+foo"#); | ||||
|         let result = detect_plain_list(input); | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let result = detect_plain_list(&initial_context, input); | ||||
|         // Since there is no whitespace after the '+' this is a paragraph, not a plain list.
 | ||||
|         assert!(result.is_err()); | ||||
|     } | ||||
| @ -580,7 +615,10 @@ dolar"#, | ||||
|     #[test] | ||||
|     fn detect_with_gap() { | ||||
|         let input = OrgSource::new(r#"+ foo"#); | ||||
|         let result = detect_plain_list(input); | ||||
|         let global_settings = GlobalSettings::default(); | ||||
|         let initial_context = ContextElement::document_context(); | ||||
|         let initial_context = Context::new(&global_settings, List::new(&initial_context)); | ||||
|         let result = detect_plain_list(&initial_context, input); | ||||
|         assert!(result.is_ok()); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander