# ============================================================================== # CallTipFiles.nm # # You need the variable $NEDIT_HOME_DIR set up to run this macro; it is set # up by NEDIT_LOADED.nm macros, if you use them; otherwise, set it here. # ============================================================================== # $NEDIT_HOME_DIR = getenv("NEDIT_HOME") # if ($NEDIT_HOME_DIR == "") # $NEDIT_HOME_DIR = getenv("HOME") "/.nedit" $CALLTIPS[""] = 0 if (!("directory" in $CALLTIPS)) { # default calltip file directory $CALLTIPS["directory"] = $NEDIT_HOME_DIR "/calltips/" } if (!("good file list" in $CALLTIPS)) { $CALLTIPS["good file list"] = 0 } if (!("shell" in $CALLTIPS)) { # we need Bourne shell compatibility! $CALLTIPS["shell"] = "exec /bin/sh -c 'CMD'" shell = shell_command("echo $0", "") shell = replace_in_string(shell, ".*/", "", "regex", "copy") # if we have sh-compatibility, don't bother with a subshell if (search_string(shell, "^(?:bash|ksh|zsh|sh)$", 0, "regex") == 0) $CALLTIPS["shell"] = "CMD" } # ------------------------------------------------------------------------------ # CallTipFile_getList([refresh]): fetch a list of ".ct" files from the calltip # files directory. The resut is stored in $CALLTIPS["file list"] and the # value $CALLTIPS["good file list"] is set to 1 if successful. If refresh # is not supplied or is zero, any previous value of $CALLTIPS["file list"] # is returned. Returns 1 on success, 0 otherwise. # ------------------------------------------------------------------------------ define CallTipFile_getList { refresh = 0 if ($n_args > 0) refresh = $1 dname = $CALLTIPS["directory"] if (!refresh && $CALLTIPS["good file list"]) if ("file list" in $CALLTIPS) return 1 perms = "\\( -perm -u+r -o -perm -g+r -o -perm -o+r \\)" find_cmd = "find . -name \\*.ct -type f " perms " -print 2>/dev/null | sort" chdir_cmd = "cd " dname " 2>/dev/null" find_cmd = "if " chdir_cmd \ "; then " find_cmd " || exit 102" \ "; else exit 103" \ "; fi" find_cmd = replace_in_string($CALLTIPS["shell"], "CMD", find_cmd, "case") flist = shell_command(find_cmd, "") flist = replace_in_string(flist, "^./", "", "regex", "copy") out = "\nCommand: " find_cmd status = $shell_cmd_status if (status != 102 && status != 103) out = "\nStatus: " status if (flist != "") out = out "\nOutput:\n\n" flist error = "" if (status == 102) error = "The calltip find command failed in directory " dname out else if (status == 103) error = "The calltip file directory '" dname "' cannot be found" out else if (status != 0) error = "An error was encountered executing the command\n\n" find_cmd out if (error != "") { dialog(error, "Cancel") $CALLTIPS["good file list"] = 0 return 0 } $CALLTIPS["file list"] = flist $CALLTIPS["good file list"] = 1 return 1 } # ============================================================================== # CallTipFileCreateNew(): prompts the user for a new calltip file name and, if # valid, creates it and opens it for editing. If it already exists, it # prompts the user whether it needs to be edited. # ============================================================================== define CallTipFileCreateNew { if (!CallTipFile_getList()) return dname = $CALLTIPS["directory"] flist = $CALLTIPS["file list"] fname = string_dialog("Calltips file to be created in " dname, "OK", "Cancel") if (fname == "" || $string_dialog_button != 1) return forig = fname fname = replace_in_string(fname, "^./+", "", "regex", "copy") fname = replace_in_string(fname, "/./", "/", "regex", "copy") fname = replace_in_string(fname, "//+", "/", "regex", "copy") # check for valid characters only, please! pos = search_string(fname, "(?n[^-+=,./:\\l\\w])", 0, "regex") if (pos >= 0) { dialog("The filename '" forig "' should not contain '" \ substring(fname, pos, pos + 1) "'", "Cancel") return } # disallow access to parent directories or to root; cannot end with "/" if (search_string(fname, "/../", 0) >= 0 || \ search_string(fname, "^(\\.\\.)?/", 0, "regex") >= 0) { dialog("This macro cannot be used to create files" \ " outside the " dname " subtree\n" \ "The specification\n " forig " (" fname ")\n" \ "contains references to parent directories", "Cancel") return } # we cannot start with a "." nor end with a "/" if (substring(fname, 0, 1) == "." || substring(fname, -1) == "/") { dialog("This macro requires a real, visible file name\n" \ "The specification\n " forig " (" fname ")\n" \ "does not provide this", "Cancel") return } # add the .ct extension if not yet there if (search_string(fname, "\\.ct$", 0, "regex") < 0) fname = fname ".ct" file = dname fname # does the file already exist? if (search_string("\n" flist, "\n" fname "\n", 0) >= 0) { res = dialog("The filename '" forig "' already exists as '" fname "'\n" \ "Open it?", "OK", "Cancel") if (res == 1) open(file) return } # does the path exist? pos = search_string(fname, "/", 0) if (pos > 0) { # prepare a command to check file path components path = replace_in_string(fname, "/[^/]+$", "", "regex") # remove file's name dirs = replace_in_string(path, "/", " ", "copy") mkdir_cmd = "for d in " dirs "; do [ ! -d $a$d ] && mkdir $a$d; a=$a$d/; done" # modern versions of mkdir support the -p argument - that would give # mkdir_cmd = "mkdir -p " path chkdir_cmd = "[ -d " path " ]" touch_cmd = "touch " fname cmd = chdir_cmd "; " mkdir_cmd "; " \ chkdir_cmd "; " touch_cmd cmd = replace_in_string($CALLTIPS["shell"], "CMD", cmd, "case") res = shell_command(cmd, "") if ($shell_cmd_status != 0) { dialog("Could not create full path\n " path \ "\nfor file \n" fname "\nin directory " dname \ "\n\ncommand: " cmd \ "\noutput:\n" res, "Cancel") return } } else { # no file path components: just create the path if (!write_file("", file)) { dialog("Could not create file\n " fname "\nin directory " dname, \ "Cancel") } } open(file) focus_window("last") } # ------------------------------------------------------------------------------ # CallTipFile_getFileName(prompt): used to return the name of a calltip file in # the caltip file directory tree. Fails with an empty string. # ------------------------------------------------------------------------------ define CallTipFile_getFileName { prompt = $1 dname = $CALLTIPS["directory"] if (!CallTipFile_getList()) return "" while ($CALLTIPS["good file list"]) { flist = $CALLTIPS["file list"] if (flist == "" || flist == "\n") { res = dialog(prompt "\n\n", "Refresh list", \ "Cancel") res++ fname = "" } else { fname = list_dialog(prompt, flist, "OK", "Refresh list", "Cancel") res = $list_dialog_button } if (res == 2) { if (!CallTipFile_getList(1)) return "" } else if (fname != "" && res == 1) return dname fname else return "" } return "" } # ============================================================================== # CallTipFileOpen(): asks the user which calltip file to open. # ============================================================================== define CallTipFileOpen { dname = $CALLTIPS["directory"] file = CallTipFile_getFileName("Open which calltip file in " dname "?") if (file != "") open(file) } # ============================================================================== # CallTipFileLoad(): asks the user which calltip file to load. # ============================================================================== define CallTipFileLoad { dname = $CALLTIPS["directory"] file = CallTipFile_getFileName("Load which calltip file in " dname "?") if (file != "") load_tips_file(file) }