# ============================================================================== # This file contains the following functions: # open_include # Based on work by Rusty Ballinger # ============================================================================== # ============================================================================== # Globals: # $open_include_path_default: a useful default path, "/usr/include" # $open_include_path: the contents of the $NEDIT_INCLUDE_PATH environment # variable, or the value of $open_include_path_default. # ============================================================================== NEDIT_require_macro_file("extensions.nm") NEDIT_require_macro_file("array_utils.nm") NEDIT_require_macro_file("ModeString.nm") $open_include_path_default = "/usr/include" # useful default $open_include_path = $open_include_path_default # attempt to get an environment path... paths = getenv("NEDIT_INCLUDE_PATH") if (paths == "") paths = $open_include_path if (paths != "") { # convert ":"s to "\n"s, remove duplicates and leading or trailing "\n"s paths = replace_in_string(paths, ":+", "\n", "regex", "copy") paths = replace_in_string(paths, "\n+", "\n", "regex", "copy") paths = replace_in_string(paths, "^\n", "", "regex", "copy") paths = replace_in_string(paths, "\n$", "", "regex", "copy") $open_include_path = paths } # ============================================================================== # open_ModeStringInterpret(filename, search_path): opens the file somewhere on # the given search path and checks its content for tabstop directives. It # then sets tabbing accordingly. # ============================================================================== define open_ModeStringInterpret { filename = $1 search_path = $2 fullfilename = NEDIT_find_file_in_pathlist(filename, search_path) if (fullfilename == "") return 0 open(fullfilename) focus_window("last") ModeStringInterpret() return 1 } # ============================================================================== # open_include_errorMsg(include_path, [expected]): returns an error string. # ============================================================================== define open_include_errorMsg { include_path = $1 expected = "" if ($n_args == 2) expected = $2 # assemble an error message reason = "Looking for or \"filename\"\n" if (expected != "") reason = reason "Found file name: " expected "\n" reason = reason "Path is\n-----------------------\n" \ replace_in_string(include_path, ":", "\n", "copy") \ "\n-----------------------\n" return reason } # ============================================================================== # open_include([filename]): attempts to find an "#include"d file name in the # current line and search for it in the global include path, as # appropriate to C and C++ source files. If a filename is supplied as a # parameter, use it, otherwise examine the current line. # # Filenames are expected to be between < and > (in which case the # $open_include_path is used "as is") or between " and " (in which case # the current file's directory path, given by $file_path, is added to the # front of the $open_include_path before searching). # ============================================================================== define open_include { include_path = $open_include_path filename = "" if ($n_args == 0) { # Try to get the filename from the current line. bpos = search("^", $cursor, "regex", "backward") epos = search("$", $cursor, "regex", "forward") line = get_range(bpos, epos) } else filename = $1 if (filename == "") { # See if we can find a filename delimited by <>. filename = replace_in_string(line, "^[^<]*\\<([^>]+)\\>.*$", "\\1", "regex") } if (filename == "") { # OK, see if we can find a filename delimited by "" filename = replace_in_string(line, "^[^\"]*\"([^\"]+)\".*$", "\\1", "regex") # put the current file's directory at the start of the search list include_path = $file_path "\n" include_path } if (filename == "") { # OK, see if we can find a filename delimited by spaces under the cursor bpos = search("\n|\\s", $cursor, "regex", "backward") epos = search("\n|\\s", $cursor, "regex", "forward") if (bpos < 0) bpos = 0 if (epos < 0) epos = $text_length filename = get_range(bpos, epos) # put the current file's directory at the end of the search list include_path = include_path "\n" $file_path } # assemble an error message reason = open_include_errorMsg(include_path, filename) if (filename == "") { if ($n_args > 0) { reason = "No filename found in line " $line ":\n\"" line "\"!\n" reason if (dialog(reason, "Quit", "Change search paths") == 2) open_include_addPath() return 0 } else { reason = "No filename found in line " $line ":\n\"" line "\"!\n" reason filename = string_dialog(reason "\nEnter filename", \ "OK", "Change search paths", "Quit") if (filename != "" && $string_dialog_button == 1) return open_include(filename) else if ($string_dialog_button == 2) { open_include_addPath(filename) return 0 } else return 0 } } # We have a filename; now see if we can open the file. current = $file_path $file_name if (!open_ModeStringInterpret(filename, include_path)) { res = string_dialog(reason "\nEnter filename", \ "OK", "File Dialog", "Change search paths", "Quit") button = $string_dialog_button if (button < 1 || button > 3) return 0 if (button == 2 || (button == 1 && res == "")) open_dialog(filename) else if (button == 3) open_include_changePath() else return open_include(res) focus_window("last") raise_window() if (current != ($file_path $file_name)) { ModeStringInterpret() return 1 } return 0 } return 1 } # ============================================================================== # open_include_addPath([path]): adds a path to $open_include_path. If no # parameter is supplied, a string dialog prompts for one. The path is # added at the end of the list (if not already there). # ============================================================================== define open_include_addPath { path = "" pathres = "" if ($n_args > 0) path = $1 noReorder = $n_args > 1 envRE = "(\\$(?:\\w+|\\(\\w+\\)|\\{\\w+\\}))" while (path == "") { prompt = "Enter directory path(s) to add to the open include path\n" \ "(colon-separated lists are accepted):\n" \ "currently\n" \ replace_in_string($open_include_path, "^", " ", \ "regex", "copy") \ "\nor add the current file's path:\n\t" $file_path path = string_dialog(prompt, "Add path", "Add file's path", "Cancel") b = $string_dialog_button if (b == 0 || b > 2) return if (b == 2) path = $file_path # allow for ":" separated components paths = split(path, ":") errors = "" added = "" count = 0 for (i = 0; i < paths[]; i++) { path = paths[i] if (path != "") { # look for env var expansion expnpath = path epos = 0 eend = 0 for (epos = search_string(expnpath, envRE, 0, "regex"); \ epos >= 0; \ epos = search_string(expnpath, envRE, eend, "regex")) { eend = $search_end exp = substring(expnpath, epos, eend) exp = replace_in_string(exp, "[${}()]", "", "regex", "copy") if (exp != "") exp = getenv(exp) expnpath = substring(expnpath, 0, epos) \ exp \ substring(expnpath, eend, length(expnpath)) } if (expnpath != path) { b = dialog("Environment variable expansion has given\n" \ " " expnpath "\nfrom\n " path, \ "Use expansion", "Use original") if (b == 1) path = expnpath } # test directory path s = shell_command("test -d `cat`", path) pathres = "" if ($shell_cmd_status == 0) { pathres = replace_in_string(shell_command("cd `cat`; pwd", path), \ "\n", "", "copy") } if (pathres == "") { errors = errors path " not found\n" continue } path = pathres } # now we have a valid path - try adding it in if (search_string("\n"$open_include_path"\n", "\n"path"\n", 0) >= 0) { errors = errors path " already added\n" continue } # add it $open_include_path = $open_include_path"\n"path added = added path "\n" count++ } # report errors if (errors != "") { leadin = "" if (added != "") leadin = leadin "The following paths were added:\n\n" added "\n" if (errors != "") leadin = leadin "The following problems were encountered:\n\n" errors if (noReorder) { dialog(leadin, "Cancel") return } if (1 == dialog(leadin, "Reorder paths", "Cancel")) { path = "" open_include_changePath() } else return } } } # ============================================================================== # open_include_changePath([path]): allows reordering of $open_include_path. # ============================================================================== define open_include_changePath { btns = make_arraylist("", "Up", "Down", "Top", "Bottom", \ "Remove", "Add New", "Reset", "Cancel") for (;;) { sp = list_dialog("Change the open include search path", \ $open_include_path"\n", \ btns[1], btns[2], btns[3], btns[4], \ btns[5], btns[6], btns[7], btns[8]) btn = $list_dialog_button b = btns[btn] s = quote_literal_as_regex(sp) p = "\n" $open_include_path "\n" if (1 <= btn && btn <= 5 && s == "" && \ dialog("No path selected", "Retry", "Cancel") != 1) return if (b == "Up") # move up { p = replace_in_string(p, "\n(.*)\n("s")\n", "\n\\2\n\\1\n", \ "regex", "copy") $open_include_path = substring(p, 1, length(p) - 1) } else if (b == "Down") # move down { p = replace_in_string(p, "\n("s")\n(.*)\n", "\n\\2\n\\1\n", \ "regex", "copy") $open_include_path = substring(p, 1, length(p) - 1) } else if (b == "Top") # move to top { p = "\n" sp replace_in_string(p, "\n"sp"\n", "\n", "case", "copy") $open_include_path = substring(p, 1, length(p) - 1) } else if (b == "Bottom") # move to bottom { p = replace_in_string(p, "\n"sp"\n", "\n", "case", "copy") sp "\n" $open_include_path = substring(p, 1, length(p) - 1) } else if (b == "Remove") { p = replace_in_string(p, "\n"sp"\n", "\n", "case", "copy") $open_include_path = substring(p, 1, length(p) - 1) } else if (b == "Add New") { open_include_addPath("", "") } else if (b == "Reset") { # reset $open_include_path = $open_include_path_default # attempt to get an environment path... paths = getenv("NEDIT_INCLUDE_PATH") if (paths == "") paths = $open_include_path if (paths != "") { # convert ":"s to "\n"s, remove duplicates and leading/trailing "\n"s paths = replace_in_string(paths, ":+", "\n", "regex", "copy") paths = replace_in_string(paths, "\n+", "\n", "regex", "copy") paths = replace_in_string(paths, "^\n", "", "regex", "copy") paths = replace_in_string(paths, "\n$", "", "regex", "copy") $open_include_path = paths } } else return } }