b475ddc8795329be93a783760d7aed704131d479
max
  Wed Feb 17 01:48:32 2021 -0800
adding JSON output to hgBlat, refs #27010

diff --git src/hg/hgBlat/hgBlat.c src/hg/hgBlat/hgBlat.c
index c98a39d..9f8cde9 100644
--- src/hg/hgBlat/hgBlat.c
+++ src/hg/hgBlat/hgBlat.c
@@ -494,30 +494,32 @@
            enum gfType qType, enum gfType tType, 
            char *organism, boolean feelingLucky)
 /* Show all the places that align. */
 {
 boolean useBigPsl = cfgOptionBooleanDefault("useBlatBigPsl", TRUE);
 struct lineFile *lf = pslFileOpen(pslName);
 struct psl *pslList = NULL, *psl;
 char *browserUrl = hgTracksName();
 char *hgcUrl = hgcName();
 char uiState[64];
 char *vis;
 char unhideTrack[64];
 char *sort = cartUsualString(cart, "sort", pslSortList[0]);
 char *output = cartUsualString(cart, "output", outputList[0]);
 boolean pslOut = startsWith("psl", output);
+boolean pslRawOut = sameWord("pslRaw", output);
+boolean jsonOut = sameWord(output, "json");
 
 sprintf(uiState, "%s=%s", cartSessionVarName(), cartSessionId(cart));
 
 /* If user has hidden BLAT track, add a setting that will unhide the 
    track if user clicks on a browser link. */
 vis = cartOptionalString(cart, "hgUserPsl");
 if (vis != NULL && sameString(vis, "hide"))
     snprintf(unhideTrack, sizeof(unhideTrack), "&hgUserPsl=dense");
 else
     unhideTrack[0] = 0;
 
 while ((psl = pslNext(lf)) != NULL)
     {
     if (psl->match >= minMatchShown)
 	slAddHead(&pslList, psl);
@@ -538,37 +540,47 @@
     {
     /* If we found something jump browser to there. */
     if(slCount(pslList) > 0)
 	printLuckyRedirect(browserUrl, pslList, database, pslName, faName, uiState, unhideTrack);
     /* Otherwise call ourselves again not feeling lucky to print empty 
        results. */
     else 
 	{
 	cartWebStart(cart, database, "%s (%s) BLAT Results", trackHubSkipHubName(organism), database);
 	showAliPlaces(pslName, faName, customText, database, qType, tType, organism, FALSE);
 	cartWebEnd();
 	}
     }
 else if (pslOut)
     {
+    if (!pslRawOut)
         printf("<TT><PRE>");
     if (!sameString(output, "psl no header"))
 	pslxWriteHead(stdout, qType, tType);
+
     for (psl = pslList; psl != NULL; psl = psl->next)
 	pslTabOut(psl, stdout);
+
+    if (pslRawOut)
+        exit(0);
+    printf("<TT><PRE>");
     printf("</PRE></TT>");
     }
+else if (jsonOut)  {
+        pslWriteAllJson(pslList, stdout, TRUE);
+        exit(0);
+}
 else  // hyperlink
     {
     printf("<H2>BLAT Search Results</H2>");
     char* posStr = cartOptionalString(cart, "position");
     if (posStr != NULL)
         printf("<P>Go back to <A HREF=\"%s\">%s</A> on the Genome Browser.</P>\n", browserUrl, posStr);
 
     if (useBigPsl)
         {
         char *trackName = NULL;
         char *trackDescription = NULL;
         getCustomName(database, cart, pslList, &trackName, &trackDescription);
         psl = pslList;
         printf( "<DIV STYLE=\"display:block;\"><FORM ACTION=\"%s\"  METHOD=\"POST\" NAME=\"customTrackForm\">\n", hgcUrl);
         printf("<INPUT TYPE=\"hidden\" name=\"o\" value=\"%d\" />\n",psl->tStart);
@@ -1381,32 +1393,35 @@
 boolean qIsProt = FALSE;
 enum gfType qType, tType;
 struct hash *tFileCache = gfFileCacheNew();
 // allGenomes ignores I'm Feeling Lucky for simplicity
 boolean feelingLucky = cgiBoolean("Lucky") && !allGenomes;
 char *xType = NULL; 
 
 if (allGenomes)
     {
     db = database;
     genome = organism;
     }
 else
     getDbAndGenome(cart, &db, &genome, oldVars);
 
+char *output = cgiString("output");
+boolean isJson= sameWordOk(output, "json");
+boolean isPslRaw= sameWordOk(output, "pslRaw");
 
-if(!feelingLucky && !allGenomes)
+if (!feelingLucky && !allGenomes && !isJson && !isPslRaw)
     cartWebStart(cart, db, "%s (%s) BLAT Results",  trackHubSkipHubName(organism), db);
 
 /* Load user sequence and figure out if it is DNA or protein. */
 if (sameWord(type, "DNA"))
     {
     seqList = faSeqListFromMemText(seqLetters, TRUE);
     uToT(seqList);
     isTx = FALSE;
     xType = "dna"; 
     }
 else if (sameWord(type, "translated RNA") || sameWord(type, "translated DNA"))
     {
     seqList = faSeqListFromMemText(seqLetters, TRUE);
     uToT(seqList);
     isTx = TRUE;