blob: 080e61a76824b07539f068e2e6c3757f14dfc4ff [file] [log] [blame]
Michael Walsh61ce3e82019-05-29 17:14:47 -05001#!/bin/bash
2
3# This file contains list-manipulation functions.
4
Michael Walsh410b1782019-10-22 15:56:18 -05005# A list is defined here as a string of items separated by some delimiter. The PATH variable is one such
6# example.
Michael Walsh61ce3e82019-05-29 17:14:47 -05007
8if ! test "${default_delim+defined}" ; then
9 readonly default_delim=" "
10fi
11
Michael Walsh410b1782019-10-22 15:56:18 -050012# Performance note: It is important for these functions to run quickly. One way to increase their speed is
13# to avoid copying function arguments to local variables and to instead use numbered arguments (e.g. ${1},
14# {2}, etc.) to access the arguments from inside the functions. In some trials, this doubled the speed of
15# the functions. The cost of this is that it makes the functions slightly more difficult to read.
Michael Walsh61ce3e82019-05-29 17:14:47 -050016
17
18function add_list_element {
19 # local list_element="${1}"
20 # local list_name="${2}"
21 # local delim="${3:-${default_delim}}"
22 # local position="${4:-back}"
23
24 # Add the list_element to the list named in list_name.
25
26 # Description of argument(s):
27 # list_element The list element to be added.
28 # list_name The name of the list to be modified.
Michael Walsh410b1782019-10-22 15:56:18 -050029 # delim The delimiter used to separate list elements.
30 # position Indicates the position in the list where the new element should be added
Michael Walsh61ce3e82019-05-29 17:14:47 -050031 # ("front"/"back").
32
33 if [ -z "${!2}" ] ; then
34 # The list is blank. Simply assign it the list_element value and return.
35 eval "${2}=\"${1}\""
36 return
37 fi
38
39 if [ "${4:-back}" == "back" ] ; then
40 # Append the list_element to the back of the list and return.
41 eval "${2}=\"\${${2}}\${3-${default_delim}}\${1}\""
42 return
43 fi
44
45 # Append the list_element to the front of the list and return.
46 eval "${2}=\"\${1}\${3-${default_delim}}\${${2}}\""
47
48}
49
50
51function remove_list_element {
52 # local list_element="${1}"
53 # local list_name="${2}"
54 local delim="${3:-${default_delim}}"
55
56 # Remove all occurrences of list_element from the list named in list_name.
57
58 # Description of argument(s):
59 # list_element The list element to be removed.
60 # list_name The name of the list to be modified.
Michael Walsh410b1782019-10-22 15:56:18 -050061 # delim The delimiter used to separate list elements.
Michael Walsh61ce3e82019-05-29 17:14:47 -050062
63 local __rle_new_list__="${!2}"
64
Michael Walsh410b1782019-10-22 15:56:18 -050065 # Special case: The list contains one element which matches the specified list element:
Michael Walsh61ce3e82019-05-29 17:14:47 -050066 if [ "${1}" == "${__rle_new_list__}" ] ; then
67 eval ${2}=\"\"
68 return
69 fi
70
Michael Walsh410b1782019-10-22 15:56:18 -050071 # Replace all occurrences of list_element that are bounded by the delimiter on both sides.
Michael Walsh61ce3e82019-05-29 17:14:47 -050072 __rle_new_list__="${__rle_new_list__//${delim}${1}${delim}/${delim}}"
Michael Walsh410b1782019-10-22 15:56:18 -050073 # Replace list_item if it occurs at the beginning of the string and is bounded on the right by the
74 # delimiter.
Michael Walsh61ce3e82019-05-29 17:14:47 -050075 __rle_new_list__="${__rle_new_list__#${1}${delim}}"
Michael Walsh410b1782019-10-22 15:56:18 -050076 # Replace list_item if it occurs at the end of the string and is bounded on the left by the delimiter.
Michael Walsh61ce3e82019-05-29 17:14:47 -050077 __rle_new_list__="${__rle_new_list__%${delim}${1}}"
78
79 # Set caller's variable to new value.
80 eval ${2}=\"\${__rle_new_list__}\"
81
82}
83
84
85function cleanup_path_slashes {
86 local var_name="${1}" ; shift
87
Michael Walsh410b1782019-10-22 15:56:18 -050088 # For the variable named in var_name, replace all multiple-slashes with single slashes and strip any
89 # trailing slash.
Michael Walsh61ce3e82019-05-29 17:14:47 -050090
91 # Description of argument(s):
Michael Walsh410b1782019-10-22 15:56:18 -050092 # var_name The name of the variable whose contents are to be changed.
Michael Walsh61ce3e82019-05-29 17:14:47 -050093
94 local cmd_buf
95
96 cmd_buf="${var_name}=\$(echo \"\${${var_name}}\" | sed -re 's#[/]+#/#g' -e 's#/\$##g')"
97 eval "${cmd_buf}"
98
99}
100
101
102function remove_path {
103 local dir_path="${1}" ; shift
104 local path_var="${1:-PATH}" ; shift
105
Michael Walsh410b1782019-10-22 15:56:18 -0500106 # Remove all occurrences of dir_path from the path variable named in path_var.
Michael Walsh61ce3e82019-05-29 17:14:47 -0500107
Michael Walsh410b1782019-10-22 15:56:18 -0500108 # Note that this function will remove extraneous slashes from the elements of path_var.
Michael Walsh61ce3e82019-05-29 17:14:47 -0500109
110 # Description of argument(s):
Michael Walsh410b1782019-10-22 15:56:18 -0500111 # dir_path The directory to be removed from the path variable.
112 # path_var The name of a variable containing directory paths separated by colons.
Michael Walsh61ce3e82019-05-29 17:14:47 -0500113
114 cleanup_path_slashes dir_path || return 1
115 cleanup_path_slashes ${path_var} || return 1
116 remove_list_element "${dir_path}" "${path_var}" : || return 1
117
118}