ultisnips icon indicating copy to clipboard operation
ultisnips copied to clipboard

Detecting conflicting snippet triggers

Open TryerGit opened this issue 1 year ago • 1 comments

Hello,

Is there a way to detect incompatible snippet triggers?

Say:

snippet st "superscript" iA
<---snippet body--->
endsnippet

vs

snippet bst "binary spanning tree data" iA
<---snippet body--->
endsnippet

vs

snippet bs "basis information" iA
<---snippet body--->
endsnippet

In the above case, bs would fire when bst is typed, so from the plugin POV there is no conflict, per se.

But from the user POV, bst will never fire. Is there a way to possibly call a function in UltiSnips that will detect and report such cases?

Thanks.

TryerGit avatar Nov 20 '22 08:11 TryerGit

One way to achieve this seems to be the following (seems a bit hackish so, perhaps there is a better way.)

Note that it is the snippets with A in their option list cause this problem. So, the following awk command processes the .snippets file and stores in a separate file the snippet triggers associated with option containing A:

awk '{if($1 == "snippet" && match($NF, "A"))printf ("%-50s\t%-d\n",$(2),NR)}' tex.snippets > keywords.txt

Then, it is a matter of processing these trigger keywords to see which pairs are subsets of each other. That can be accomplished via the following C++ code:

#include <string>
#include <vector>
#include <sstream>
#include <fstream>
std::vector<std::string> keywords;
std::vector<int> linenumbers;

// Returns -1 if s1 is not a substring of s2
int isSubstring(std::string s1, std::string s2)
{
	int M = s1.length();
	int N = s2.length();
  if (N < M)
    return -1;
    /* A loop to slide pat[] one by one */
	for (int i = 0; i <= N - M; i++) {
		int j;
		/* For current index i, check for
pattern match */
		for (j = 0; j < M; j++)
			if (s2[i + j] != s1[j])
				break;

		if (j == M)
			return i;
	}
	return -1;
}

int main() {
  std::ifstream ifile("keywords.txt");
  std::ofstream ofile("Processed_output.txt");
  std::string line;
  while (getline(ifile, line)) {
    std::istringstream ss(line);
      int lineno;
    while (!ss.eof()) {
      std::string hname;
      ss >> hname; 
      if (hname.length() > 0) {
        keywords.push_back(hname);
        ss >> lineno;
        linenumbers.push_back(lineno);
      }
    }
  }
  for (int i = 0; i < keywords.size(); i++) {
    for (int j = 0; j < keywords.size(); j++) {
      if (i == j)
        continue;
      if (isSubstring(keywords[i], keywords[j]) == -1) {
      }
      else {
        printf("Clash between %s [%d] and %s [%d]\n", keywords[i].c_str(), linenumbers[i], keywords[j].c_str(), linenumbers[j]);
        ofile << "Clash between " << keywords[i] << " ["<<linenumbers[i]<<"] and " << keywords[j] << " ["<<linenumbers[j]<<"]"<<std::endl; 
      }
    }
  }
  ifile.close();
  ofile.close();
}

This shows all the "clashes" for further analysis/correction.

TryerGit avatar Nov 20 '22 16:11 TryerGit