0
# English Language Helpers
1
2
English language string joining utilities with Oxford comma support, customizable conjunctions, and proper grammatical formatting. This module provides functions for generating human-readable lists and messages with correct English grammar conventions.
3
4
## Capabilities
5
6
### List Joining with Grammar Support
7
8
Join lists of words with proper English grammar, including Oxford comma support and customizable conjunctions.
9
10
```python { .api }
11
def join(l, conj='and', im_a_moron=False, separator=','):
12
"""
13
Join lists of words with Oxford comma and proper English grammar.
14
15
Args:
16
l (list): List of strings to join
17
conj (str): Conjunction word to use (default: 'and')
18
im_a_moron (bool): Whether to disable Oxford comma (default: False)
19
separator (str): Separator character between items (default: ',')
20
21
Returns:
22
str: Properly formatted English list string
23
24
Grammar Rules:
25
- Two items: "item1 and item2" (no comma)
26
- Three+ items: "item1, item2, and item3" (Oxford comma)
27
- im_a_moron=True: "item1, item2 and item3" (no Oxford comma)
28
"""
29
```
30
31
**Usage Examples:**
32
33
```python
34
from clint.eng import join
35
36
# Basic list joining
37
colors = ['red', 'green', 'blue']
38
result = join(colors)
39
# Returns: "red, green, and blue"
40
41
# Two items (no comma needed)
42
pair = ['apple', 'orange']
43
result = join(pair)
44
# Returns: "apple and orange"
45
46
# Single item
47
single = ['banana']
48
result = join(single)
49
# Returns: "banana"
50
51
# Custom conjunction
52
options = ['save', 'load', 'quit']
53
result = join(options, conj='or')
54
# Returns: "save, load, or quit"
55
56
# Disable Oxford comma
57
items = ['Tom', 'Dick', 'Harry']
58
result = join(items, im_a_moron=True)
59
# Returns: "Tom, Dick and Harry"
60
61
# Custom separator
62
files = ['file1.txt', 'file2.txt', 'file3.txt']
63
result = join(files, separator=';')
64
# Returns: "file1.txt; file2.txt; and file3.txt"
65
```
66
67
### Grammar Constants
68
69
Pre-defined constants for consistent formatting across the module.
70
71
```python { .api }
72
MORON_MODE = False # Default Oxford comma setting
73
COMMA = ',' # Default separator character
74
CONJUNCTION = 'and' # Default conjunction word
75
SPACE = ' ' # Space character constant
76
```
77
78
**Usage with Constants:**
79
80
```python
81
from clint.eng import join, CONJUNCTION, COMMA
82
83
# Using module constants
84
tasks = ['compile', 'test', 'deploy']
85
86
# Standard format
87
result = join(tasks, conj=CONJUNCTION, separator=COMMA)
88
# Returns: "compile, test, and deploy"
89
90
# Alternative conjunctions
91
result = join(tasks, conj='then')
92
# Returns: "compile, then test, then deploy"
93
```
94
95
## Usage Patterns
96
97
### CLI Help Messages
98
99
```python
100
from clint.eng import join
101
102
def show_help():
103
commands = ['start', 'stop', 'restart', 'status']
104
options = ['--verbose', '--quiet', '--config']
105
106
print(f"Available commands: {join(commands, conj='or')}")
107
print(f"Common options: {join(options)}")
108
109
# Output:
110
# Available commands: start, stop, restart, or status
111
# Common options: --verbose, --quiet, and --config
112
```
113
114
### Error Messages
115
116
```python
117
from clint.eng import join
118
119
def validate_required_fields(data, required_fields):
120
missing = [field for field in required_fields if field not in data]
121
if missing:
122
if len(missing) == 1:
123
raise ValueError(f"Missing required field: {missing[0]}")
124
else:
125
raise ValueError(f"Missing required fields: {join(missing)}")
126
127
# Usage
128
try:
129
validate_required_fields({'name': 'John'}, ['name', 'email', 'age'])
130
except ValueError as e:
131
print(e) # "Missing required fields: email and age"
132
```
133
134
### Status Reports
135
136
```python
137
from clint.eng import join
138
139
def system_status(services):
140
running = [s for s in services if s['status'] == 'running']
141
stopped = [s for s in services if s['status'] == 'stopped']
142
143
if running:
144
names = [s['name'] for s in running]
145
print(f"Running services: {join(names)}")
146
147
if stopped:
148
names = [s['name'] for s in stopped]
149
print(f"Stopped services: {join(names, conj='and')}")
150
151
# Usage
152
services = [
153
{'name': 'nginx', 'status': 'running'},
154
{'name': 'postgresql', 'status': 'running'},
155
{'name': 'redis', 'status': 'stopped'}
156
]
157
system_status(services)
158
# Output:
159
# Running services: nginx and postgresql
160
# Stopped services: redis
161
```
162
163
### Configuration Summaries
164
165
```python
166
from clint.eng import join
167
168
def summarize_config(config):
169
enabled_features = [k for k, v in config.items() if v is True]
170
disabled_features = [k for k, v in config.items() if v is False]
171
172
if enabled_features:
173
print(f"Enabled: {join(enabled_features)}")
174
175
if disabled_features:
176
print(f"Disabled: {join(disabled_features)}")
177
178
# Usage
179
config = {
180
'logging': True,
181
'caching': True,
182
'debugging': False,
183
'profiling': False
184
}
185
summarize_config(config)
186
# Output:
187
# Enabled: logging and caching
188
# Disabled: debugging and profiling
189
```
190
191
### List Processing with Different Formats
192
193
```python
194
from clint.eng import join
195
196
def format_file_list(files, action='process'):
197
if not files:
198
return f"No files to {action}"
199
200
if action == 'delete':
201
return f"Will delete: {join(files)}"
202
elif action == 'backup':
203
return f"Choose files to backup: {join(files, conj='or')}"
204
else:
205
return f"Processing: {join(files)}"
206
207
# Usage
208
files = ['document.pdf', 'image.jpg', 'data.csv']
209
print(format_file_list(files, 'delete'))
210
# Output: "Will delete: document.pdf, image.jpg, and data.csv"
211
212
print(format_file_list(files[:2], 'backup'))
213
# Output: "Choose files to backup: document.pdf or image.jpg"
214
```
215
216
### Interactive Prompts
217
218
```python
219
from clint.eng import join
220
from clint.textui import prompt
221
222
def select_from_options(options, prompt_text="Choose an option"):
223
option_list = join(options, conj='or')
224
question = f"{prompt_text} ({option_list}):"
225
226
while True:
227
choice = prompt.query(question).lower()
228
if choice in [opt.lower() for opt in options]:
229
return choice
230
print(f"Please choose {option_list}")
231
232
# Usage
233
environments = ['development', 'staging', 'production']
234
env = select_from_options(environments, "Select environment")
235
# Prompt: "Select environment (development, staging, or production):"
236
```
237
238
### Advanced Formatting
239
240
```python
241
from clint.eng import join
242
243
def format_permission_summary(permissions):
244
"""Format permissions with different conjunctions for different contexts."""
245
246
if len(permissions) <= 2:
247
return f"Permissions: {join(permissions, conj='and')}"
248
else:
249
# For longer lists, group by type
250
read_perms = [p for p in permissions if 'read' in p.lower()]
251
write_perms = [p for p in permissions if 'write' in p.lower()]
252
admin_perms = [p for p in permissions if 'admin' in p.lower()]
253
254
parts = []
255
if read_perms:
256
parts.append(f"read ({join(read_perms)})")
257
if write_perms:
258
parts.append(f"write ({join(write_perms)})")
259
if admin_perms:
260
parts.append(f"admin ({join(admin_perms)})")
261
262
return f"Permissions: {join(parts)}"
263
264
# Usage
265
perms = ['read_users', 'read_posts', 'write_posts', 'admin_settings']
266
print(format_permission_summary(perms))
267
# Output: "Permissions: read (read_users and read_posts), write (write_posts), and admin (admin_settings)"
268
```