I’d like to find the function declarations from text obtained from Apps Script API

When one makes a request from the App Script API to return all of the files and functions for a given project this is what a source file looks like.

"function traverse(o, func) {n  for (var i in o) {n    func.apply(this, [i, o[i]]);n    if (o[i] !== null && typeof (o[i]) == "object") {n      traverse(o[i], func);n    }n  }n}nnfunction daysInMonth(m = 0) {n  return new Date(new Date().getFullYear(), m + 1, 0).getDate();n}nnfunction getMyDataURI(fileId) {n  const file = DriveApp.getFileById(fileId);n  return file.getBlob().getDataAsString();n}nnfunction dataFromGSheets() {n  const ss = SpreadsheetApp.getActive();n  const sheet = ss.getSheetByName("Sheet1");n  const [header, ...data] = sheet.getDataRange().getDisplayValues();n  const choices = {};n  header.forEach((title, index) =u003e {n    choices[title] = data.map(row =u003e row[index]).filter(e =u003e e)n  });n  return choices;n}nnfunction boldMyWords() {n  const red = SpreadsheetApp.newTextStyle().setForegroundColor('red').setBold(true).build();n  const bold = SpreadsheetApp.newTextStyle().setBold(true).build();n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getActiveSheet();n  const dsr = 3;n  const rg = sh.getRange(3, 1, sh.getLastRow() - dsr + 1, sh.getLastColumn());n  rg.clearFormat().setWrap(true);n  let vs = rg.getDisplayValues();n  let r = SpreadsheetApp.getUi().prompt('Enter words to search for separated by commas', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL);n  if (r.getSelectedButton() == SpreadsheetApp.getUi().Button.OK) {n    let wordA = r.getResponseText().split(',');n    vs.forEach((r, i) =u003e {n      r.forEach((c, j) =u003e {n        let idxObj = { pA: [] };n        wordA.forEach(w =u003e {n          let re = new RegExp('(\\W|^)' + w.trim().toLowerCase() + '(\\W|$)', 'g');n          let found = [...c.toLowerCase().matchAll(re)];n          found.forEach(f =u003e {n            if (!idxObj.hasOwnProperty(w)) {n              idxObj[w] = [];n              idxObj[w].push((f.index u003e 0) ? f.index + 1 : f.index);n              idxObj.pA.push(w);n            } else {n              idxObj[w].push((f.index));n            }n          })n        });n        if (idxObj.pA.length u003e 0) {n          let cell = sh.getRange(i + dsr, j + 1);n          let val = SpreadsheetApp.newRichTextValue().setText(c);n          idxObj.pA.forEach((p, k) =u003e {n            idxObj[p].forEach(idx =u003e {n              val.setTextStyle(idx, idx + p.length, red);n              val.setTextStyle(idx, idx + p.length, bold);n            });n          });n          cell.setRichTextValue(val.build());n        }n      });n    });n  }n  ss.toast('EOF')n}nnfunction boldMyName() {n  const bold = SpreadsheetApp.newTextStyle().setBold(true).build();n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getActiveSheet();n  const dsr = 3;n  const rg = sh.getRange(3, 1, sh.getLastRow() - dsr + 1, sh.getLastColumn());n  rg.clearFormat().setWrap(true);n  let vs = rg.getDisplayValues();n  vs.forEach((r, i) =u003e {n    r.forEach((c, j) =u003e {n      let idx = c.indexOf(':');n      if (~idx) {n        let cell = sh.getRange(i + dsr, j + 1);n        let val = SpreadsheetApp.newRichTextValue().setText(c);n        val.setTextStyle(0, idx, bold);n        cell.setRichTextValue(val.build());n      }n    });n  });n}nnfunction monthArray() {n  const mA = [...Array.from(new Array(12).keys(), x =u003e Utilities.formatDate(new Date(2021, x, 15), Session.getScriptTimeZone(), "MMMM"))];n  Logger.log(mA.join(','));n}nnvar level = 1;nfunction getFnF(folder = DriveApp.getRootFolder()) {n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getSheetByName('Sheet0')n  const files = folder.getFiles();n  sh.getRange(sh.getLastRow() + 1, level).setValue(folder.getName()).setFontWeight('bold');n  if (files.hasNext()) {n    sh.getRange(sh.getLastRow() + 1, level).setValue('Files:');n  }n  while (files.hasNext()) {n    let file = files.next();n    let firg = sh.getRange(sh.getLastRow() + 1, level + 1);n    firg.setValue(Utilities.formatString(file.getName()));n  }n  const subfolders = folder.getFolders()n  while (subfolders.hasNext()) {n    let subfolder = subfolders.next();n    level++;n    getFnF(subfolder);n  }n  level--;n}nnfunction getFilesAndFolders() {n  const fldr = DriveApp.getRootFolder();n  SpreadsheetApp.getActive().getSheetByName('Sheet0').clearContents();n  SpreadsheetApp.getActive().toast('Entry');n  getFnF(fldr);n  SpreadsheetApp.getActive().toast('EOF');n}nnfunction getFnF1(folder = DriveApp.getRootFolder()) {n  let tree = JSON.parse(PropertiesService.getScriptProperties().getProperty('FnF'));n  //Logger.log(JSON.stringify(tree));n  if (tree.level u003c level) {n    tree.level = level;n    PropertiesService.getScriptProperties().setProperty('FnF', JSON.stringify(tree));n  }n  const files = folder.getFiles();n  let row = Array.from([...Array(level).keys()], ((x, i) =u003e { if (i == level - 1) { x = folder.getName(); } else { x = ''; } return x; }));n  tree.txt.push(row);n  row = Array.from([...Array(level).keys()], ((x, i) =u003e { if (i == level - 1) { x = 'bold'; } else { x = 'normal'; } return x; }));n  tree.fwt.push(row);n  PropertiesService.getScriptProperties().setProperty('FnF', JSON.stringify(tree));n  if (files.hasNext()) {n    let row = Array.from([...Array(level).keys()], ((x, i) =u003e { if (i == level - 1) { x = 'Files:'; } else { x = ''; } return x; }));n    tree.txt.push(row);n    tree.fwt.push(['normal']);n    PropertiesService.getScriptProperties().setProperty('FnF', JSON.stringify(tree));n  }n  while (files.hasNext()) {n    let file = files.next();n    let row = Array.from([...Array(level + 1).keys()], ((x, i) =u003e { if (i == level) { x = file.getName(); } else { x = ''; } return x; }));n    tree.txt.push(row);n    tree.fwt.push(['normal']);n    PropertiesService.getScriptProperties().setProperty('FnF', JSON.stringify(tree));n  }n  const subfolders = folder.getFolders()n  while (subfolders.hasNext()) {n    let subfolder = subfolders.next();n    level++;n    getFnF1(subfolder);n  }n  level--;n}nnfunction getFilesAndFolders1() {n  const fldr = null;n  const ss = SpreadsheetApp.getActive();n  ss.toast("Entry");n  const sh = ss.getSheetByName('Sheet1');n  sh.clearContents();n  SpreadsheetApp.flush();n  PropertiesService.getScriptProperties().setProperty('FnF', JSON.stringify({ txt: [], fwt: [], level: 0 }));n  getFnF1();n  //Logger.log(PropertiesService.getScriptProperties().getProperty('FnF'));n  let tree = JSON.parse(PropertiesService.getScriptProperties().getProperty('FnF'));n  const l = tree.level + 1n  tree.txt.forEach(r =u003e {n    if (r.length u003c l) {n      //Array.from(Array(l - r.length).keys()).forEach(e =u003e r.push(''));n      r.splice(r.length, 0, ...Array(l - r.length).fill(''));n    }n  });n  tree.fwt.forEach(r =u003e {n    if (r.length u003c l) {n      //Array.from(Array(l - r.length).keys()).forEach(e =u003e r.push('normal'));n      r.splice(r.length, 0, ...Array(l - r.length).fill('normal'));n    }n  });n  //Logger.log(JSON.stringify(tree));n  sh.getRange(1, 1, tree.txt.length, tree.level + 1).setValues(tree.txt);n  sh.getRange(1, 1, tree.fwt.length, tree.level + 1).setFontWeights(tree.fwt);n  PropertiesService.getScriptProperties().deleteProperty('FnF');n  ss.toast("EOF");n}nnfunction calendarMonthlyForYear() {n  var dA = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];n  var oA = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];//you can change the first day of the week by shifting the arrayn  //var oA=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];n  var dObj = {};n  oA.forEach(function (e, i) { dObj[e] = i });n  var mA = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];n  var cA = [];n  var bA = [];n  var wA = [null, null, null, null, null, null, null];n  var ss = SpreadsheetApp.getActive();n  var sh = ss.getSheetByName("Cal");n  if (!sh) { var sh = ss.insertSheet('Cal'); }n  sh.clear();n  var year = new Date().getFullYear();n  for (var i = 0; i u003c 12; i++) {n    var month = new Date(year, i, 1).getMonth();n    var dates = new Date(year, i + 1, 0).getDate();n    cA.push([mA[month], dates, '', '', '', '', '']);n    bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n    cA.push(oA)n    bA.push(['#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00']);n    var d = [];n    var ddd = [];n    for (var j = 0; j u003c dates; j++) {n      var day = new Date(year, i, j + 1).getDay();n      var date = new Date(year, i, j + 1).getDate();n      if (day u003c wA.length) {n        wA[dObj[dA[day]]] = date;n      }n      //if(day==wA.length-1 || date==dates) {n      if (dA[day] == oA[wA.length - 1] || date == dates) {n        cA.push(wA);n        bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n        wA = ['', '', '', '', '', '', ''];n      }n    }n  }n  sh.getRange(1, 1, cA.length, cA[0].length).setValues(cA);n  //sh.getRange(1,1,cA.length,cA[0].length).setBackgrounds(bA);n  sh.getRange(1, 1, cA.length, cA[0].length).setBackground('#ffffff');n}nnfunction monthlyCalendar(m, wsd, ret) {n  var m = m || new Date().getMonth();n  var wsd = wsd || 1;//defaults to Mondayn  var ret = ret || false;n  const td = new Date();n  const [cy, cm, cd] = [td.getFullYear(), td.getMonth(), td.getDate()];n  const dA = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];n  const oA = [...Array.from(Array(7).keys(), idx =u003e dA[(idx + wsd) % 7])]n  let dObj = {};n  let midx = {};n  let rObj = { cA: null, roff: null, coff: null };n  oA.forEach(function (e, i) { dObj[e] = i; });n  const mA = [...Array.from(new Array(12).keys(), x =u003e Utilities.formatDate(new Date(2021, x, 15), Session.getScriptTimeZone(), "MMM"))];n  mA.forEach((e, i) =u003e { midx[i] = i; })n  let cA = [];n  let bA = [];n  let wA = [null, null, null, null, null, null, null];n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getActiveSheet();n  sh.clear();n  const year = new Date().getFullYear();n  let i = midx[m % 12];n  let month = new Date(year, i, 1).getMonth();n  let dates = new Date(year, i + 1, 0).getDate();n  cA.push([mA[month], dates, '', '', '', '', '']);n  bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n  cA.push(oA)n  //bA.push(['#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00']);n  let d = [];n  let ddd = [];n  for (let j = 0; j u003c dates; j++) {n    let day = new Date(year, i, j + 1).getDay();n    let date = new Date(year, i, j + 1).getDate();n    if (day u003c wA.length) {n      wA[dObj[dA[day]]] = date;n    }n    if (cy == year && cm == month && cd == date) {n      rObj.roff = cA.length;n      rObj.coff = dObj[dA[day]];n    }n    if (dA[day] == oA[wA.length - 1] || date == dates) {n      cA.push(wA);n      //bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n      wA = ['', '', '', '', '', '', ''];n    }n  }n  if (!ret) {n    rObj.cA = cA;n    sh.getRange(1, 1, rObj.cA.length, rObj.cA[0].length).setValues(cA);n    if (rObj.roff && rObj.coff) {n      sh.getRange(1, 1).offset(rObj.roff, rObj.coff).setFontWeight('bold').setFontColor('red');n    }n  } else {n    rObj.cA = cA;n    return rObj;n  }n}nnfunction monthlyCalendarWithEvents(obj) {n  var m = obj.m || new Date().getMonth();n  var wsd = obj.wsd || 1;//defaults to Mondayn  const calids = obj.calids || CalendarApp.getAllOwnedCalendars().map(c =u003e c.getId());n  const cals = calids.map(id =u003e CalendarApp.getCalendarById(id));n  const td = new Date();n  const [cy, cm, cd] = [td.getFullYear(), td.getMonth(), td.getDate()];n  const dA = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];n  const oA = [...Array.from(Array(7).keys(), idx =u003e dA[(idx + wsd) % 7])]n  let dObj = {};n  let midx = {};n  let rObj = { cA: null, roff: null, coff: null };n  oA.forEach(function (e, i) { dObj[e] = i; });n  const mA = [...Array.from(new Array(12).keys(), x =u003e Utilities.formatDate(new Date(2021, x, 15), Session.getScriptTimeZone(), "MMM"))];n  mA.forEach((e, i) =u003e { midx[i] = i; })n  let cA = [];n  let bA = [];n  let wA = [null, null, null, null, null, null, null];n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getActiveSheet();n  sh.clear();n  const rtvnull = sh.getRange("A1").getRichTextValue();n  const year = new Date(new Date().getFullYear(), m, 1).getFullYear();n  let i = midx[m % 12];n  let month = new Date(year, i, 1).getMonth();n  let ldom = new Date(year, i + 1, 0).getDate();n  var events = { pA: [] };n  cals.forEach(c =u003e {n    let evs = c.getEvents(new Date(year, month, 1), new Date(year, month, ldom, 23, 59, 59));n    evs.forEach(ev =u003e {n      let st = ev.getStartTime();n      let dd = st.getDate();n      let hh = st.getHours();n      let mm = st.getMinutes();n      let sts = `${hh}:${mm}`;n      if (!events.hasOwnProperty(dd)) {n        events[dd] = [];n        events[dd].push(`${ev.getTitle()} - ${sts}`);n        events.pA.push(dd);n      } else {n        events[dd].push(`${ev.getTitle()} - ${sts}`);n      }n    });n  });n  cA.push([mA[month], ldom, '', '', '', '', '']);n  bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n  cA.push(oA)n  //bA.push(['#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00', '#ffff00']);n  let d = [];n  let ddd = [];n  for (let j = 0; j u003c ldom; j++) {n    let day = new Date(year, i, j + 1).getDay();n    let date = new Date(year, i, j + 1).getDate();n    if (day u003c wA.length) {n      if (events.hasOwnProperty(date)) {n        wA[dObj[dA[day]]] = events[date].join('\n') + '\n' + date;n      } else {n        wA[dObj[dA[day]]] = date;n      }n    }n    if (cy == year && cm == month && cd == date) {n      rObj.roff = cA.length;n      rObj.coff = dObj[dA[day]];n    }n    if (dA[day] == oA[wA.length - 1] || date == ldom) {n      cA.push(wA);n      //bA.push(['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff']);n      wA = ['', '', '', '', '', '', ''];n    }n  }n  const dtnotcur = SpreadsheetApp.newTextStyle().setBold(true).setForegroundColor('black').build();n  const dtcur = SpreadsheetApp.newTextStyle().setBold(true).setForegroundColor('red').build();n  const evsty = SpreadsheetApp.newTextStyle().setFontSize(8).setForegroundColor('black').build();n  rObj.cA = cA;n  rObj.crtA = cA.map((r, i) =u003e {n    let row = [];n    r.map((c, j) =u003e {n      if (c == '' || c == null) {n        row.push(rtvnull);n        return;n        //c = ' ';//heres the current solutionn      }n      if (typeof c != 'string') {n        c = c.toString();n      }n      let idx = c.lastIndexOf('\n');n      let rtv = SpreadsheetApp.newRichTextValue().setText(c);n      if (rObj.roff == i && rObj.coff == j) {n        if (~idx) {n          rtv.setTextStyle(idx + 1, c.length, dtcur);n          rtv.setTextStyle(0, idx, evsty);n          row.push(rtv.build());n        } else {n          rtv.setTextStyle(0, c.length, dtcur);n          row.push(rtv.build());n        }n      } else {n        if (~idx) {n          rtv.setTextStyle(idx + 1, c.length, dtnotcur);n          rtv.setTextStyle(0, idx, evsty);n          row.push(rtv.build());n        } else {n          if (c.length u003e 0) {n            rtv.setTextStyle(0, c.length, dtnotcur);n            row.push(rtv.build());n          } else {n            row.push(rtv.build());n          }n        }n      }n    });n    return row;n  });n  return rObj;n}nnfunction quarterlyCalendarWithEvents() {n  const ss = SpreadsheetApp.getActive()n  const sh = ss.getActiveSheet();n  sh.clear();n  const dt = new Date();n  let oA = [];n  let ids = ['[email protected]', '[email protected]', '[email protected]'];n  oA.push(monthlyCalendarWithEvents({ m: new Date().getMonth() - 2, wsd: null, calids: ids }));n  oA.push(monthlyCalendarWithEvents({ m: new Date().getMonth() - 1, wsd: null, calids: ids }));n  oA.push(monthlyCalendarWithEvents({ m: new Date().getMonth(), wsd: null, calids: ids }));n  oA.push(monthlyCalendarWithEvents({ m: new Date().getMonth() + 1, wsd: null, calids: ids }));n  oA.push(monthlyCalendarWithEvents({ m: new Date().getMonth() + 2, wsd: null, calids: ids }));n  oA.forEach((obj, i) =u003e {n    if (i == 0) {n      sh.getRange(1, 1, obj.crtA.length, obj.crtA[0].length).setRichTextValues(obj.crtA);n    } else {n      let lr = sh.getLastRow();n      sh.getRange(lr + 1, 1, 1, obj.crtA[0].length).setBackground('#c2bbc9');n      let sr = lr + 2;n      sh.getRange(sr, 1, obj.crtA.length, obj.crtA[0].length).setRichTextValues(obj.crtA);n    }n  });n  SpreadsheetApp.flush();n  sh.getDataRange().setWrap(true).setHorizontalAlignment('left');n  sh.setColumnWidths(1, sh.getLastColumn(), 85);n}nnfunction colToletters(num) {n  let a = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";n  if (num u003c 27) return a[num % a.length];n  if (num u003e 26) {n    num--;n    let letters = '';n    while (num u003e= 0) {n      letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[num % 26] + lettersn      num = Math.floor(num / 26) - 1;n    }n    return letters;n  }n}nnfunction copyto() {n  const dssid = "1Trccc5IszA2cLpUHKr2_I826e216u6is7ZWbD8ecx2U";n  const ss = SpreadsheetApp.getActive()n  const sssid = ss.getId();n  const sh = ss.getSheetByName('Sheet0')n  const sshid = sh.getSheetId();n  const options = { "method": "post", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, "payload": { "destinationSpreadsheetId": "" + dssid } };n  const url = `https://sheets.googleapis.com/v4/spreadsheets/${sssid}/sheets/${sshid}:copyTo`;n  let r = UrlFetchApp.fetch(url, options);n  let title = JSON.parse(r.getContentText()).title;n  const dss = SpreadsheetApp.openById(dssid);n  let s = dss.getSheetByName(sh.getName());n  if (s) dss.deleteSheet(s);n  dss.getSheetByName(title).setName(sh.getName());n}nnfunction breakUpRangeList(ss = SpreadsheetApp.getActive(), sh = ss.getSheetByName("Sheet0"), rgl) {n  let b = [];n  rgl.getRanges().forEach(rg =u003e {n    rg.getValues().forEach((r, i) =u003e {n      let row = rg.getRow() + i;n      r.forEach((c, j) =u003e {n        let col = rg.getColumn() + j;n        b.push(sh.getRange(row, col).getA1Notation())n      })n    })n  })n  b = [...new Set(b)];n  //Logger.log(JSON.stringify(b));n  return sh.getRangeList(b);n}nnfunction flattenRangeArray(rangeArray) {n  const ss = SpreadsheetApp.getActive()n  const sh = ss.getActiveSheet();n  let rgl = sh.getRangeList(rangeArray);n  let b = [];n  rgl.getRanges().forEach(rg =u003e {n    rg.getValues().forEach((r, i) =u003e {n      let row = rg.getRow() + i;n      r.forEach((c, j) =u003e {n        let col = rg.getColumn() + j;n        b.push(sh.getRange(row, col).getA1Notation())n      })n    })n  })n  b = [...new Set(b)];n  //Logger.log(JSON.stringify(b));n  return b;n}nnnn//Drive.Files.update({"parents": [{"id": folder.getId()}]}, file.getId());nnfunction createPDFFromDoc(fileid, folderid) {n  const folder = DriveApp.getFolderById(folderid);n  const file = DriveApp.getFileById(fileid);n  const blob = file.getAs('application/pdf').setName(file.getName());n  const pdffile = DriveApp.createFile(blob);n  Drive.Files.update({ "parents": [{ "id": folder.getId() }] }, pdffile.getId());n}nnfunction makeCopy() {n  var folderid = gobj.globals.folder1id;n  var fileid = "1lITNKyzlyLOWTla9c27x76GRAlAegF68";n  var folder = Drive.Files.get(folderid, { "supportsAllDrives": true });n  var newFile = { "fileId": fileid, "parents": [folder] };n  var args = { "resource": { "parents": [folder], "title": "new Title" }, "supportsAllDrives": true };n  Drive.Files.copy(newFile, fileid, args);n}nnfunction addingcharttoemaildraft() {n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getSheetByName("Sheet0");n  const c = sh.getCharts()[0];n  const img = c.getAs("image/png").setName("myimage");n  const f = DriveApp.getFolderById(gobj.globals.testfolderid).createFile(img);n  let htmltemp = HtmlService.createTemplateFromFile('ah2');n  htmltemp.filename = "myimage";n  let imgObj = { img0: f.getBlob() };n  let html = htmltemp.evaluate().getContent();n  GmailApp.createDraft(gobj.globals.emailpub, "Test File", '', { htmlBody: html, inlineImages: imgObj });n}nnfunction openUrl() {n  let html = 'u003ch1u003eDummy Dialogu003c/h1u003eu003cscriptu003ewindow.onload = function(){google.script.run.withSuccessHandler(function(url){window.open(url,"_blank");google.script.host.close();}).getMyUrl();}u003c/scriptu003e';n  SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Dummy Dialog");n}nnfunction getMyUrl() {n  console.log('getting url');n  return "http://www.google.com";n}nnfunction sheetToCsv() {n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getSheetByName("Sheet0")n  const params = { "method": "GET", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } };n  const url = "https://docs.google.com/spreadsheets/d/" + ss.getId() + "/export?gid=" + sh.getSheetId() + "&format=csv";n  const r = UrlFetchApp.fetch(url, params);n  const csv = r.getContentText();n  return csv;n}nnfunction unravelpara() {n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getActiveSheet();n  const lists = 12;//number of lists to break it inton  let v = [...Array.from(Array(lists).keys(), x =u003e [''])];n  sh.getRange("A1").getDisplayValue().replace(/([ ]{2,})/g, " ").split(/\s/).forEach((e, i) =u003e {n    v[i % lists][0] += `, ${e}`;n  });n  let a = v.map(r =u003en    r[0].slice(2).split(', ')n  );n  let t = Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });n  sh.getRange(2, 2, t.length, t[0].length).setValues(t);n}nnfunction groceryList() {n  const ss = SpreadsheetApp.getActive();n  const sh = ss.getSheetByName("Purchase");n  const vs = sh.getDataRange().getValues().filter(r =u003e r[1] == true).map(r =u003e [r[2],r[3]]);n  n  const osh = ss.getSheetByName("Sheet0");n  osh.clear();n  if(vs && vs.length u003e 0) {n    vs.unshift(["Description","Quantity"]);n    osh.getRange(1, 1, vs.length,vs[0].length).setValues(vs);n    osh.getRange(1,1,1,osh.getLastColumn()).setFontWeight("bold");n    osh.autoResizeColumns(1,2);n  }n}nnfunction groceryListEdit(e) {n  const sh = e.range.getSheet();n  if (sh.getName() == "Purchase" && e.range.columnStart u003e 1) {n    if(e.value == "FALSE") {n      e.range.offset(0,2).setValue("");n    }n    groceryList();n  }n}nnnn" 

This one is fairly large. I’ve been using the code for a while but recently I noticed some of the functions were missing so I began to search for a better solution.

I can get an array of objects from the functionSet of the same return from the API so I can loop through the functionSet and recover the exact function names but this one function named breakUpRangeList is giving me problems that I’m having trouble resolving.

This version only contains the function before and the function after:

"function copyto() {n  const dssid = "1Trccc5IszA2cLpUHKr2_I826e216u6is7ZWbD8ecx2U";n  const ss = SpreadsheetApp.getActive()n  const sssid = ss.getId();n  const sh = ss.getSheetByName('Sheet0')n  const sshid = sh.getSheetId();n  const options = { "method": "post", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, "payload": { "destinationSpreadsheetId": "" + dssid } };n  const url = `https://sheets.googleapis.com/v4/spreadsheets/${sssid}/sheets/${sshid}:copyTo`;n  let r = UrlFetchApp.fetch(url, options);n  let title = JSON.parse(r.getContentText()).title;n  const dss = SpreadsheetApp.openById(dssid);n  let s = dss.getSheetByName(sh.getName());n  if (s) dss.deleteSheet(s);n  dss.getSheetByName(title).setName(sh.getName());n}nnfunction breakUpRangeList(ss = SpreadsheetApp.getActive(), sh = ss.getSheetByName("Sheet0"), rgl) {n  let b = [];n  rgl.getRanges().forEach(rg =u003e {n    rg.getValues().forEach((r, i) =u003e {n      let row = rg.getRow() + i;n      r.forEach((c, j) =u003e {n        let col = rg.getColumn() + j;n        b.push(sh.getRange(row, col).getA1Notation())n      })n    })n  })n  b = [...new Set(b)];n  //Logger.log(JSON.stringify(b));n  return sh.getRangeList(b);n}nnfunction flattenRangeArray(rangeArray) {n  const ss = SpreadsheetApp.getActive()n  const sh = ss.getActiveSheet();n  let rgl = sh.getRangeList(rangeArray);n  let b = [];n  rgl.getRanges().forEach(rg =u003e {n    rg.getValues().forEach((r, i) =u003e {n      let row = rg.getRow() + i;n      r.forEach((c, j) =u003e {n        let col = rg.getColumn() + j;n        b.push(sh.getRange(row, col).getA1Notation())n      })n    })n  })n  b = [...new Set(b)];n  //Logger.log(JSON.stringify(b));n  return b;n}nnnn//Drive.Files.update({"parents": [{"id": folder.getId()}]}, file.getId());nn"

The following function is the function I use to load a spreadsheet that makes it easier to find functions I want but I’ve noticed that some are missing and that’s what I’d like to fix.

GS:

function getAllProjectFunctions() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("ProjectFunctions");
  const file = DriveApp.getFileById(gobj.globals.SOFJSONId);
  var jOb = JSON.parse(file.getBlob().getDataAsString());
  let files = jOb.files;
  if (files && files.length > 0) {
    var cOb = files.reduce((a, f, i) => {
      //Logger.log(f.name);
      a.table.push([f.name, f.type, "", ""]);
      if (f.type == "SERVER_JS" && f.source != null) {
        //a.source = JSON.stringify(f.source);//The is where I stringified the file source code
        a.source = f.source;
        //Logger.log('a.source: %s',a.source);
      }
      if (f.functionSet && f.functionSet.values) {
        f.functionSet.values.forEach(obj => {
          //let re = new RegExp(`function\s+${obj.name}\([^)]*\)\s*\{.*?\\n\}\\n`, "g");
          //let re = new RegExp(`function.*?${obj.name}.*?\(.*\).*\{(.|\n)*?\n\}`, "g");

This is the line I’m working on:

          let re = new RegExp(`function\s+${obj.name}\([^)]*\)[ rn]*\{(.|\n)*?\n\}`, "g");//This is the regex that I wish to replace


          if (a.source.match(re)) {
            let src = a.source.match(re)[0];//once I began to stringy from above then this start functioning
            a.table.push([f.name, f.type, obj.name, src])
          }
        });
      }
      if((f.type == "HTML" || f.type == "JSON")&& f.source != null) {
        a.table.push([f.name,f.type,f.name,f.source])
      }
      return a;
    }, { source: "", table: [["File Name", "File Type", "Function Name", "Source"]] });
  }
  if (cOb.table && cOb.table.length > 0) {
    sh.clearContents();
    sh.getRange(1, 1, cOb.table.length, cOb.table[0].length).setValues(cOb.table);
  }
}

This is the line I wish to replace:

let re = new RegExp(`function\s+${obj.name}\([^)]*\)[ rn]*\{(.|\n)*?\n\}`, "g");

This is the regex I’ve been working on:

functions+breakUpRangeList(?!n}nn)[^]*n}nn

I have not been able to get either the negative look behind nor the negative look ahead to operate in this application. So I haven’t gotten to the point of converting it to be used in a RegExp.

So the question I’m trying to ask is how to get everything from the end of the function name to the end of the declaration which ends with n}nn

This is what the function looks like in the project source file:

function breakUpRangeList(ss = SpreadsheetApp.getActive(), sh = ss.getSheetByName("Sheet0"), rgl) {
  let b = [];
  rgl.getRanges().forEach(rg => {
    rg.getValues().forEach((r, i) => {
      let row = rg.getRow() + i;
      r.forEach((c, j) => {
        let col = rg.getColumn() + j;
        b.push(sh.getRange(row, col).getA1Notation())
      })
    })
  })
  b = [...new Set(b)];
  //Logger.log(JSON.stringify(b));
  return sh.getRangeList(b);
}