-
Notifications
You must be signed in to change notification settings - Fork 0
/
printenv.py
213 lines (179 loc) · 7.4 KB
/
printenv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/usr/bin/env python3
#
# Copyright 2021 Shay Gordon
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""
Display colorized environment variable names and values in name order.
Run with -h or --help command line option to print usage.
Available on GiHub at https://github.com/moebius-rex/printenv.
Possible enhancements:
* Customizable ANSI color themes
* Generate HTML instead of plain text output
"""
__author__ = "Shay Gordon"
__email__ = "[email protected]"
# to discover what type of platform we're running on
import platform
# colors used in ANSI escape sequences
colors = {
'black': 0, 'red': 1, 'green': 2, 'yellow': 3, 'blue': 4, 'magenta': 5,
'cyan': 6, 'white': 7
}
# command line arguments dictionary, populated by parse_args()
args = None
# is script running under windows os?
windows = platform.system() == 'Windows'
# default separator for multi-value variables
sep = ';' if windows else ':'
# turn off ANSI escape sequences, modified by parse_args()
off = '\033[0m'
def esc(color, bright=True):
"""Return ANSI escape sequence for supplied color and brightness."""
return '' if windows or args.unformatted else \
'\033[%dm' % (colors[color] + (90 if bright else 30))
def parse_args():
"""Parse command line arguments into global dictionary."""
import argparse
description = """description:
Display environment variable names and values in name order.
Features:
* Name-sorted, colorized (Unix only) version of Unix 'env'/'printenv'
and Windows 'set' commands.
* Command line options provide convenient, formatted alternative to
piping output to grep-like commands.
* Variables containing multiple values may be printed on multiple
lines, one per value, by providing the value separator string as
a command line option."""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=description)
parser.add_argument('match', metavar='char-sequence', nargs='?',
help="print only those variable names/values that contain this \
character sequence")
parser.add_argument('-c', '--clear', action='store_true',
help="clear terminal before printing")
parser.add_argument('-e', '--exact-match', action='store_true',
help="print only those variable names/values that exactly match the \
character sequence provided")
parser.add_argument('-i', '--ignore', action='store_true',
help="ignore case in character sequence if provided")
parser.add_argument('-n', '--no-name-repeat', action='store_true',
help="when used with -s option, suppress printing of variable \
name on all but first line of multiple value variables")
parser.add_argument('-r', '--reset', action='store_true',
help="reset terminal before printing")
parser.add_argument('-s', '--split', metavar='sep',
type=str, nargs='?', const=sep,
help="split multiple value variables by supplied 'sep' (separator, " +
"default '" + sep + "') string and print one value per line")
parser.add_argument('-u', '--unformatted', action='store_true',
help="sort by name but disable all output formatting to produce \
output similar to that of native operating system commands")
parser.add_argument('-w', '--wait', action='store_true',
help="prompt user to exit script (useful when launching a terminal \
window to run this command)")
global args
args = parser.parse_args()
if windows or args.unformatted:
global off
off = ''
def clear():
"""Clear or reset terminal based on command line arguments."""
if args.reset:
print('\033c', end='')
elif args.clear:
print('\033[H\033[J', end='')
def wait():
"""Wait for user to press enter before exiting script."""
if args.wait:
input('\nPress return to exit')
def search():
"""
Return a dictionary of all environment variable names and/or values
containing the character sequence supplied on the command line, or all
environment variables if no sequence was provided.
"""
import os
env = os.environ
if args.match:
import re
p = re.compile(args.match, flags=re.IGNORECASE if args.ignore else 0)
for key, value in list(env.items()):
if args.exact_match:
if key != args.match and value != args.match:
# key2 = '%s$' % key
# value2 = '%s$' % value
# print('key: ' + key2 + ', value: ' + value2)
# if not p.search(key2) and not p.search(value2):
del env[key]
else:
if not p.search(key) and not p.search(value):
del env[key]
# return potentially empty dictionary of environment variables
return env
def print_one(key, value, fmt):
"""
Print one environment variable name and value(s). Output format is
controlled by the '--split' and '--key' command line arguments.
"""
# select value color
if value.startswith('/'):
# show unix path values in different color
fg = 'cyan'
else:
try:
# show integer values in different color
int(value)
fg = 'white'
except ValueError:
# show all other values in default color
fg = 'green'
# print multivalue variables on separate lines
if args.split and not args.unformatted:
values = value.split(args.split)
if len(values) > 1:
for index, value in enumerate(values):
if value:
bright = True if index == 0 else False
key = key if not args.no_name_repeat or index == 0 else ''
print(fmt % (esc('blue', bright), key, off,
esc(fg), value, off))
return
# print single value variable or unseparated multivalue variable
print(fmt % (esc('blue'), key, off, esc(fg), value, off))
def print_env():
"""
Print colorized environment variables and values in alphabetical order.
Variable values have different colors depending on whether they are
integers or start with a forward slash.
"""
env = search()
if env:
# generate print format string of the form:
# <color>[padding] key<color off> <color>value<color off>
if args.unformatted:
fmt = '%s%s%s=%s%s%s'
else:
longest_key = max(env.keys(), key=len)
fmt = '%%s%%%ds%%s %%s%%s%%s' % len(longest_key)
for key, value in sorted(env.items()):
print_one(key, value, fmt)
def main():
parse_args()
clear()
print_env()
wait()
if __name__ == '__main__':
main()