ctags icon indicating copy to clipboard operation
ctags copied to clipboard

Adding unique names to markdown headings

Open rickalex21 opened this issue 3 years ago • 4 comments

Hello, I have several markdown files that start with # Introduction # Getting started. To avoid duplicate tags I started doing # Topic1 Introduction and # Topic2 Introduction. This does not look good in documentation, is there a way that I can make unique tags based on file name without changing the markdown?

What I want to do in vim is:

:tag topic1 introduction

But I want the markdown to look like this:

## Introduction

Something about topic1.

I don't want to create my own language file but if I have to I can do something like touch ~/.ctags.d/mymarkdown.ctags ? I'm not experienced in ctags, this was just something I was messing around with before #2965 issue.

--_mtable-regex-MarkdownNew=main_sharp/^##[ \t]+([^\n]+)([ \t]+#+)[\n]*/\1/s/{_field=sectionMarker:##}{scope=push}{tenter=section,main}

Do something like this:

...*/printf "%s%s" \1 this.filename/s/{_file=...

I understand that this may be difficult because the tags need to get referenced some how.

So my next question to that would be, is there a way I can associate file1.md line 11 with 'topic1 introduction' tag in the .tags file? Then I would associate file2.md line 9 with 'topic2 introduction' in the .tags file. Then I could just reference :tag topic1 introduction and :tag topic2 introduction in vim.

rickalex21 avatar May 11 '21 21:05 rickalex21

I found following two solutions:

# Plan A. extending existing parser
--_extradef-Markdown=withfname,appending input filename
--extras-Markdown=+{withfname}
--_makeTagEntryReflection-Markdown={{
    /withfname _extraenabled {
        mark . :name (@) . :input _basename _buildstring
        . :kind
        . :line _tag dup /withfname _markextra _commit pop
   } if    
}}

# Plan B. using a subparser
--langdef=mymarkdown{base=Markdown}
--_extradef-mymarkdown=withfname,appending input filename
--extras-mymarkdown=+{withfname}
--kindef-mymarkdwon=S,subsection,subsections
--kindef-mymarkdwon=T,l4subsection,level 4 subsections
--kindef-mymarkdwon=c,chapter,chapsters
--kindef-mymarkdwon=s,section,sections
--kindef-mymarkdwon=t,subsubsection,subsubsections
--kindef-mymarkdwon=u,l5subsection,level 5 subsections
--_makeTagEntryNotifycation-mymarkdown={{
    /withfname _extraenabled {
        mark . :name (@) . :input _basename _buildstring
	% This will now work if the Markdown parser introduces a new kind
        . :kind
        . :line _tag dup /withfname _markextra _commit pop
   } if    
}}

In this case, --_makeTagEntryReflection-<LANG> is better solution. However, --_makeTagEntryNotifycation-<LANG> may be better in many cases other than this.

The real issue is there is no such option. I will add the two options. @rickalex21, do you know how to build the latest version of ctags? _tag operator must be extended to take line:int instead of _mloc.

I will work o this topic after making a pull request for #3017.

masatake avatar May 11 '21 23:05 masatake

@masatake I'm fairly new to ctags, I know enough to get by. I usually build with brew. I'm not sure if file name alone is good for all cases in the future, it works for me right now but what if one day someone wanted to do a count ? I don't want to make things difficult but have you thought of variables? This would be more universal and future proof than just adding a filename.

The only problem with this is when would the variable be reset (re-initialize), it complicates things when you add variables but it would be more universal IMO.

--var--mycount=0
...*/++mycount\ \1 /s/{_file=...

I escaped a space, so not sure if it needs to be quoted "$fname \1" or escaped. but the final tag name would be :tag filename introduction

...*/fname\ \1/s/{_file=...

What ever you think works best and is best for the project.

rickalex21 avatar May 12 '21 00:05 rickalex21

Just adding variables is not enough. ctags has an interpreter implementing a general-purpose programming language called optscript already.

  • https://docs.ctags.io/en/latest/optscript.html#
  • https://ctags.io/blog/

The markdown parser already uses the interpreter. https://github.com/universal-ctags/ctags/blob/master/optlib/markdown.ctags#L41

The interpreter may solve your issue. However, some modifications to ctags are needed to make the solution MORE elegant.

I usually build with brew.

With brew, can you use the latest version of ctags?

$ ./ctags --list-features
#NAME             DESCRIPTION
...
optscript         can use the interpreter
...

If you ctags has the interpreter, you will find optscript in the list.

I will add the modifications to ctags. To utilize the code I will add to solve your issue, you have to find a way to build the latest version of ctags.

masatake avatar May 12 '21 03:05 masatake

I have the latest now, let me know what I have to do next. Thanks

Universal Ctags 5.9.0(63f5d380), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: May 11 2021, 23:03:49
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath, +json, +interactive, +yaml, +packcc, +optscript

rickalex21 avatar May 12 '21 04:05 rickalex21