# ============================================================================== # This file contains the following functions: # make_columns # make_columns_dialog # ============================================================================== NEDIT_require_macro_file("redetab.nm") # ============================================================================== # make_columns(text, colsep, new_sep, match_type, just, notidy, maxcol, force): # returns the text passed modified so that all occurrences of colsep # (column separator) are replaced by spaces, in such a way that the text # is formatted as columns separated by the string passed as new_sep. If # new_sep is a number, its value is used as the number of spaces to # guarantee between the resultant columns. match_type should be one of # "literal", "case", "regex". just can be one of "left", "right" or # "middle" and specifies how the column data should be written into the # column. The text is assumed to consist of complete lines, and the column # data are assumed not to contain tabs. If the notidy parameter is # "notidy", no spaces will be stripped from either side of the column # data. Normally the space is stripped. If the force parameter is "force", # each line which does not have the full complement of columns will have # empty columns added. # ============================================================================== define make_columns { text_in = $1 colsep = "\t" new_sep = " " match_type = "case" just = "left" tidy = 1 maxcolno = 0 force = 0 if ($n_args >= 2) colsep = $2 if ($n_args >= 3) new_sep = $3 if ($n_args >= 4) match_type = $4 if ($n_args >= 5) just = $5 if ($n_args >= 6) tidy = ($6 != "notidy") if ($n_args >= 7) maxcolno = $7 + 0 if ($n_args >= 8) force = ($8 == "force") if (colsep == "") colsep = "\t" if (maxcolno < 0) maxcolno = 0 min_dist = length(new_sep) if (min_dist == 0) min_dist = 1 if (search_string(match_type, "<(literal|case|regex)>", 0, "regex") == -1) match_type = "case" if (search_string(just, "<(left|right|middle)>", 0, "regex") == -1) just = "left" col_space_sep = new_sep # is new_sep numeric? if (search_string(new_sep, "[0-9]+", 0, "regex") == 0 && \ $search_end == length(new_sep)) { col_space_sep = " " min_dist = new_sep + 0 for (i = length(col_space_sep); i < min_dist; i = length(col_space_sep)) col_space_sep = col_space_sep col_space_sep col_space_sep = substring(col_space_sep, 0, min_dist) } max_col = 0 # max columns required col_widths = "" # an array of column widths col_spaces = "" # a string of spaces as wide as the widest column entry max_width = 0 # width of the widest column entry # evaluate requirements: ---------------------------------------------------- # loop for each line is_last = 0 SoL = 0 for (EoL = search_string(text_in, "\n", 0); \ !is_last; \ EoL = search_string(text_in, "\n", EoL + 1)) { if (EoL == -1) { EoL = length(text_in) is_last = 1 } line = substring(text_in, SoL, EoL) # for each line, count the columns, and assess widths line_col_count = 0 tmp_col_widths = "" colno = maxcolno while (line != "") { len = length(line) if (maxcolno > 0) colno-- else colno = 1 # have we reached the column limit? if (colno > 0) { pos = search_string(line, colsep, 0, match_type) end = $search_end } else pos = -1 if (pos == -1) { pos = len end = len } col_data = substring(line, 0, pos) while (tidy && search_string(col_data, "(^ )|( $)", 0, "regex") != -1) col_data = replace_in_string(col_data, "(^ *)|( *$)", "", "regex") width = length(col_data) if (width > max_width) { max_width = width col_spaces = replace_in_string(col_data, ".", " ", "regex") } # pick off the first value from col_widths into old_width split_pos = search_string(col_widths, "\n", 0) if (split_pos != -1) { old_width = substring(col_widths, 0, split_pos) + 0 col_widths = substring(col_widths, split_pos + 1) } else old_width = 0 width = max(width, old_width) tmp_col_widths = tmp_col_widths width "\n" line_col_count++ line = substring(line, end) } col_widths = tmp_col_widths col_widths max_col = max(max_col, line_col_count) SoL = EoL + 1 } # now start creating the output text: -------------------------------------- # loop for each line text_out = "" is_last = 0 is_empty_last = 0 SoL = 0 for (EoL = search_string(text_in, "\n", 0); \ !is_last; \ EoL = search_string(text_in, "\n", EoL + 1)) { if (EoL == -1) { EoL = length(text_in) is_last = 1 if (SoL == EoL) is_empty_last = 1 } line = substring(text_in, SoL, EoL) tmp_col_widths = col_widths # for each line, assemble the columns, and add spaces line_col_count = 0 left = "" right = "" colno = maxcolno if (!is_empty_last) { while (line != "" || (force && line_col_count < max_col)) { # pick off the first value from col_widths into old_width split_pos = search_string(tmp_col_widths, "\n", 0) if (split_pos != -1) { want_width = substring(tmp_col_widths, 0, split_pos) + 0 tmp_col_widths = substring(tmp_col_widths, split_pos + 1, \ length(tmp_col_widths)) } else want_width = 0 # shouldn't happen... len = length(line) if (maxcolno > 0) colno-- else colno = 1 # have we reached the column limit? if (colno > 0) { pos = search_string(line, colsep, 0, match_type) end = $search_end } else pos = -1 if (pos == -1) { pos = len end = len } line_col_count++ col_data = substring(line, 0, pos) while (tidy && search_string(col_data, "(^ )|( $)", 0, "regex") != -1) col_data = replace_in_string(col_data, "(^ *)|( *$)", "", "regex") width = length(col_data) # calculate spaces left = right # right was calculated for the previous column if (just == "left") right = substring(col_spaces, 0, want_width - width) col_space_sep else if (just == "right") { left = left substring(col_spaces, 0, want_width - width) right = col_space_sep } else # if (just == "middle") { half = (want_width - width) / 2 left = left substring(col_spaces, 0, half) right = substring(col_spaces, 0, want_width-half-width) col_space_sep } text_out = text_out left col_data line = substring(line, end) } if (!is_last) text_out = text_out "\n" } SoL = EoL + 1 } return text_out } # ============================================================================== # make_columns_dialog(): converts selected text into columns. If the selection # is not rectangular, it is extended to include whole lines. Parameters # to make_columns() are prompted for. Uses the detab() macro function. # ============================================================================== define make_columns_dialog { rectangular = ($selection_left != -1) keeptrailing = "" if (!rectangular) { # make sure that the selection starts at the start of the line beginning_of_selection() if ($column != 0) beginning_of_line("extend") } text = get_selection() if (!rectangular) { # make sure that the selection end at the end of the line len = length(text) if (substring(text, len - 1, len) != "\n") { end_of_selection() end_of_line("extend") text = get_selection() } } beginning_of_selection() # Ask the user for the column separator match_type = "case" sep = string_dialog("Field separator", \ "Literal", "Case", "Regex", "Tab", "Cancel") tabsep = 0 if ($string_dialog_button == 1) match_type = "literal" else if ($string_dialog_button == 2) match_type = "case" else if ($string_dialog_button == 3) match_type = "regex" else if ($string_dialog_button == 4) { sep = "\t" tabsep = 1 } else return if (!tabsep) tabsep = (sep == "\t") if (!tabsep) tabsep = (sep == "\\t" && match_type == "regex") if (!tabsep) text = detab(text, 0, 0) # Ask for new column separator new_sep = string_dialog("Inter-column string", "OK", "Tab", "Cancel") if ($string_dialog_button == 1) { if (new_sep == "") new_sep = 4 } else if ($string_dialog_button == 2) new_sep = "\t" else return # Ask for justification type just = "left" n_just = dialog("Justify Text In Columns", "Left", "Right", "Mid", "Cancel") if (n_just == 1) just = "left" else if (n_just == 2) just = "right" else if (n_just == 3) just = "middle" else return # tidy? notidy = "" # limit columns to how many? maxcol = string_dialog("Maximum columns", "Indefinite", "OK", "Cancel") if ($string_dialog_button == 1) maxcol = 0 else if ($string_dialog_button == 2) maxcol = maxcol + 0 else return # force row completion of columns? f = dialog("Force complete columns?", "Yes", "No", "Cancel") if (f == 1) force = "force" else if (f == 2) force = "" else return r = make_columns(text, sep, new_sep, match_type, just, notidy, maxcol, force) replace_selection(r) }