NEDIT_require_macro_file("extensions.nm") NEDIT_require_macro_file("array_utils.nm") NEDIT_require_macro_file("cygwin.nm") $OpenMultipleFiles[""] = 0 Title = "Open multiple files\n" T = Title E = "" # error lsmatch = "" lsopts = "" if ("lsopts" in $OpenMultipleFiles) lsopts = $OpenMultipleFiles["lsopts"] if ("lsmatch" in $OpenMultipleFiles) lsmatch = $OpenMultipleFiles["lsmatch"] openmodes = make_array("New Windows", make_arraylist1("window", "window"), \ "New Group", make_arraylist1("window", "tab"), \ "This Group", make_arraylist1("tab", "tab")) buttons = make_arraylist1("New Windows", "New Group", "This Group", \ "Options", "Filter", "Set Path", "Up", "Back") dbuttons = make_arraylist1("Enter", "Options", "Filter", "Set Path", \ "Up", "Back") opt = $empty_array ocwd = $empty_array cwd = $file_path oldwindow = $file_path $file_name if (cwd == "") { # remove any trailing / (only at root level?) from pwd result cwd = chomp(shell_command("pwd", ""), "/?\n") if ($shell_cmd_status != 0) cwd = "" else # now add a trailing / (again) cwd = cwd "/" } if (cwd == "") return dialog(T "Could not determine current directory", "Dismiss") find_d = "find . -type d '!' -name . -print -prune | sort" find_f = "find . -type d '!' -name . -prune -o -type f -print" # ============================================================================== for (;;) # until happy { T = Title "In directory " cwd "\n" if (ocwd[]) T = T "(previous directory " ocwd[ocwd[] - 1] ", ["ocwd[]"])\n\n" if (E != "") E = "\nERROR: " E "\n\n" cwds = quote_literal_for_shell_esc(cwd) aa = " && " cd_cwd = "cd " cwds aa echo = aa "echo '///'" aa # the /// will separate output from commands dirns = "" files = "" ls = "" # call ls, find dirns and find files cmd = cd_cwd "ls " lsopts lsmatch out = shell_command(cmd echo find_d echo find_f, "") if ($shell_cmd_status != 0) { # the ls command failed: execute the command again, picking up only stderr # (assumes find always works) EE = "FAILED " cmd "\n" chomp(shell_command(cmd "> /dev/null", ""), "\n+") } else { # save options/match-filters for next time $OpenMultipleFiles["lsopts"] = lsopts $OpenMultipleFiles["lsmatch"] = lsmatch # get the lists of plain files and directories directories pieces = split(out, "///\n") ls = pieces[0] dirns = "\n" replace_in_string(pieces[1], "^\\./(.*)$", "\\1/", "regex") files = "\n" replace_in_string(pieces[2], "./", "") if ($shell_cmd_status != 0) { ls = "" } } list = "" n_files = 0 end = 0 for (pos = search_string(ls, "^.+\n", end, "regex"); \ pos >= 0; \ pos = search_string(ls, "^.+\n", end, "regex")) { end = $search_end # keep ending \n filename = substring(ls, pos, end) if (search_string(files, "\n" filename, 0, "case") < 0) continue # skip: not a plain file else if (substring(filename, 0, 1) == "~" && \ search_string(lsopts, " ?-A ", 0, "regex") < 0) continue # skip: this is (probably) a NEdit backup file # however, show it if we're looking for all files list = list filename ++n_files } list = chomp(dirns list) # we have our list of files if (list == "") { E = "No files or directories found in directory " cwd i = ocwd[] - 1 if (i < 0) # nowhere to go back to return dialog(T "\nERROR: " E, "Dismiss") newcwd = ocwd[i] E = E "\nReturning from directory " cwd E = E "\nto directory " newcwd cwd = newcwd delete ocwd[i] continue } # ask for filenames ---------------------------------------------------------- F = "[command ' ls " lsopts lsmatch "' found " n_files " files]\n" if (n_files == 0) { # ask for a single directory res = list_dialog(T E F "Select a directory to enter", \ list, \ dbuttons[1], dbuttons[2], dbuttons[3], \ dbuttons[4], dbuttons[5], dbuttons[6], \ "Cancel") if (!($list_dialog_button in dbuttons)) return sbtn = dbuttons[$list_dialog_button] } else { if (ocwd[] == 0) res = list_multisel_dialog(T E F "Select files or a single directory", \ list, \ buttons[1], buttons[2], buttons[3], \ buttons[4], buttons[5], buttons[6], \ buttons[7], "Cancel") else res = list_multisel_dialog(T E F "Select files or a single directory", \ list, \ buttons[1], buttons[2], buttons[3], \ buttons[4], buttons[5], buttons[6], \ buttons[7], buttons[8], "Cancel") limit = buttons[] - (ocwd[] == 0) if ($list_dialog_button > limit || !($list_dialog_button in buttons)) return sbtn = buttons[$list_dialog_button] } # now what? E = "" isdir = 0 if (sbtn in openmodes) # ----------------------------------------------------- { if (res == "") E = "No files selected" isdir = (search_string(res, "/", 0) >= 0) if (isdir && search_string(res, "\n", 0) > 0) E = "Cannot include directories in mutiple selections" if (E != "") continue if (isdir) { ocwd[ocwd[]] = cwd cwd = cwd res continue } openmode = openmodes[sbtn] newopt = 1 filenames = split(res, "\n") for (i = 0; i in filenames; ++i) { filename = filenames[i] EE = "" if (focus_window(cwd filename) != "") { EE = "\n file already opened: " filenames[i] } else { read_file(cwd filename) if ($read_status) { new(openmode[newopt]) if (newopt < openmode[]) ++newopt focus_window("last") open(cwd filename) } else EE = "\n failed to open " filenames[i] } E = E EE } focus_window(oldwindow) raise_window() } else if (sbtn == "Enter") # -------------------------------------------------- { if (res == "") E = "No directory selected" else { ocwd[ocwd[]] = cwd cwd = cwd res } } else if (sbtn == "Set Path") # ----------------------------------------------- { # pick up selection, clipboard etc clip = clipboard_to_string() sel = get_selection("any") prompt = T "Enter new directory path" i = 0 name = "Cancel" btns[i++] = name val[name] = "" btns[i++] = "OK" if (clip != "") { prompt = prompt "\n clipboard: '" clip "'" name = "Clipboard" btns[i++] = name val[name] = clip } if (sel != "") { prompt = prompt "\n selection: '" sel "'" name = "Selection" btns[i++] = name val[name] = sel } btns[i++] = btns[0] if (i == 3) str = string_dialog(prompt, btns[1], btns[2]) else if (i == 4) str = string_dialog(prompt, btns[1], btns[2], btns[3]) else if (i == 5) str = string_dialog(prompt, btns[1], btns[2], btns[3], btns[4]) val["OK"] = str choice = btns[$string_dialog_button] str = val[choice] if (str == "") continue newcwd = str if (Cygwin_isCygwin()) { if (search_string(str, "/", 0) < 0 || \ search_string(str, "^\\l:[\\\\/]", 0, "regex") >= 0) { # no "/"s or starts with eg "c:\" - may be a Windows/DOS path str = Cygwin_convertDOSpath(str) if (str != "") newcwd = str } } str = newcwd newcwd = quote_literal_for_shell_esc(newcwd) newcwd = chomp(shell_command("cd " newcwd " && pwd", ""), "/?\n") if ($shell_cmd_status != 0) newcwd = "" else # now add a trailing / (again) newcwd = newcwd "/" if (newcwd == "") E = "Could not move to directory " str else if (newcwd != cwd) { ocwd[ocwd[]] = cwd cwd = newcwd } } else if (sbtn == "Up") # ----------------------------------------------------- { newcwd = quote_literal_for_shell_esc(cwd) newcwd = chomp(shell_command("cd " newcwd ".. && pwd", ""), "/?\n") if ($shell_cmd_status != 0) newcwd = "" else # now add a trailing / (again) newcwd = newcwd "/" if (newcwd == "") E = "Could not move up to parent directory of " cwd else if (newcwd != cwd) { ocwd[ocwd[]] = cwd cwd = newcwd } } else if (sbtn == "Back") # --------------------------------------------------- { i = ocwd[] - 1 if (i < 0) # nowhere to go back to return dialog(T "\nERROR: Invalid Back button: check macro code", \ "Dismiss") cwd = ocwd[i] delete ocwd[i] } else if (sbtn == "Options") # ------------------------------------------------ { if (!opt[]) { opt["Show hidden files"] = make_array("", "Off", \ "On", "-A ", \ "Off", "") opt["Reverse Sort"] = make_array("", "Off", \ "On", "-r ", \ "Off", "") opt["Sort"] = make_array("", "alphabetically", \ "alphabetically", "", \ "by extension", "-X ", \ "by size", "-S ", \ "by time (access)", "-u ", \ "by time (modification)", "-t ") } # build the list of allowed options, marking selected ones with >> optslist = "" EE = "" for (anopt in opt) { partlist = "" thename = opt[anopt][""] thepart = anopt ": " thename for (aname in opt[anopt]) { if (aname == "") continue apart = anopt ": " aname partlist = partlist " " apart "\n" if (search_string(lsopts, opt[anopt][aname], 0) >= 0) { thename = aname thepart = apart } } partlist = replace_in_string(partlist, " " thepart, \ ">> " thepart, "case") optslist = optslist partlist } # get new ones newlist = list_multisel_dialog("Choose file list options,\n" \ "no more than one per group", \ optslist) "\n" newopts = "" for (anopt in opt) { re_opt = "^(?!.. " anopt ": ).*\\n" re_old = "^(?!\\>\\> " anopt ": ).*\\n" grepped = replace_in_string(newlist, re_opt, "", "regex", "copy") nGrepped = length(replace_in_string(grepped, "[^\n]*", "", "regex")) if (nGrepped > 1) EE = EE "\n - more than one option selected for " anopt if (nGrepped != 1) # use previous instance, marked with >> { grepped = replace_in_string(optslist, re_old, "", "regex", "copy") } # get option value name, at end of the line grepped = replace_in_string(grepped, "^.*: (.*)\n", "\\1", "regex") value = opt[anopt][grepped] newopts = newopts value } if (EE == "") lsopts = newopts else E = "Failed to change list options:" EE } else if (sbtn == "Filter") # ------------------------------------------------- { EE = "" for (;;) { M = T if (lsmatch != "") M = T "Current filter: " lsmatch "\n" newmatch = string_dialog(M EE "Enter file patterns to match", \ "OK", "Clear", "Cancel") btn = $string_dialog_button if (btn == 1) { if (newmatch == "") break newmatch = newmatch " " if (search_string(newmatch, "[;$`'\"~&|\x01-\x1F]", 0, "regex") >= 0) { EE = "Requested matches contain invalid characters\n" } else { str = shell_command("exec sh", "for i in " newmatch "; do :; done") if ($shell_cmd_status == 0 && str == "") { # looks OK lsmatch = newmatch break } EE = "Cannot use given patterns\nShell replies:\n" str "\n" } } else if (btn == 2) { lsmatch = "" break } else break } } else # ----------------------------------------------------------------------- { E = sbtn " not implemented" } }