strcase-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strcase_cli-0.1.0/LICENSE +21 -0
- strcase_cli-0.1.0/PKG-INFO +57 -0
- strcase_cli-0.1.0/README.md +36 -0
- strcase_cli-0.1.0/pyproject.toml +29 -0
- strcase_cli-0.1.0/setup.cfg +4 -0
- strcase_cli-0.1.0/strcase/__init__.py +2 -0
- strcase_cli-0.1.0/strcase/cli.py +95 -0
- strcase_cli-0.1.0/strcase/converter.py +115 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/PKG-INFO +57 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/SOURCES.txt +12 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/dependency_links.txt +1 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/entry_points.txt +2 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/requires.txt +1 -0
- strcase_cli-0.1.0/strcase_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marcus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: strcase-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more
|
|
5
|
+
Author-email: Marcus <marcus@marcusbuilds.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/marcusbuildsthings-droid/strcase
|
|
8
|
+
Project-URL: Issues, https://github.com/marcusbuildsthings-droid/strcase/issues
|
|
9
|
+
Keywords: cli,string,case,convert,camelCase,snake_case
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Text Processing
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: click>=8.0
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# strcase-cli
|
|
23
|
+
|
|
24
|
+
Convert strings between naming conventions from the command line.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install strcase-cli
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
strcase snake "myVariableName" # my_variable_name
|
|
36
|
+
strcase camel "my_variable_name" # myVariableName
|
|
37
|
+
strcase pascal "my-variable-name" # MyVariableName
|
|
38
|
+
strcase kebab "MyVariableName" # my-variable-name
|
|
39
|
+
strcase screaming "myVar" # MY_VAR
|
|
40
|
+
strcase dot "myVar" # my.var
|
|
41
|
+
strcase title "my_var_name" # My Var Name
|
|
42
|
+
strcase train "myVarName" # My-Var-Name
|
|
43
|
+
strcase cobol "myVarName" # MY-VAR-NAME
|
|
44
|
+
strcase all "myVariableName" # Show all conversions
|
|
45
|
+
strcase detect "my_variable_name" # snake
|
|
46
|
+
strcase types # List all styles
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
|
|
50
|
+
|
|
51
|
+
## For AI Agents
|
|
52
|
+
|
|
53
|
+
See [SKILL.md](SKILL.md) for agent-optimized documentation.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# strcase-cli
|
|
2
|
+
|
|
3
|
+
Convert strings between naming conventions from the command line.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install strcase-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
strcase snake "myVariableName" # my_variable_name
|
|
15
|
+
strcase camel "my_variable_name" # myVariableName
|
|
16
|
+
strcase pascal "my-variable-name" # MyVariableName
|
|
17
|
+
strcase kebab "MyVariableName" # my-variable-name
|
|
18
|
+
strcase screaming "myVar" # MY_VAR
|
|
19
|
+
strcase dot "myVar" # my.var
|
|
20
|
+
strcase title "my_var_name" # My Var Name
|
|
21
|
+
strcase train "myVarName" # My-Var-Name
|
|
22
|
+
strcase cobol "myVarName" # MY-VAR-NAME
|
|
23
|
+
strcase all "myVariableName" # Show all conversions
|
|
24
|
+
strcase detect "my_variable_name" # snake
|
|
25
|
+
strcase types # List all styles
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
|
|
29
|
+
|
|
30
|
+
## For AI Agents
|
|
31
|
+
|
|
32
|
+
See [SKILL.md](SKILL.md) for agent-optimized documentation.
|
|
33
|
+
|
|
34
|
+
## License
|
|
35
|
+
|
|
36
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "strcase-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [{name = "Marcus", email = "marcus@marcusbuilds.ai"}]
|
|
13
|
+
keywords = ["cli", "string", "case", "convert", "camelCase", "snake_case"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Text Processing",
|
|
20
|
+
"Topic :: Utilities",
|
|
21
|
+
]
|
|
22
|
+
dependencies = ["click>=8.0"]
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
strcase = "strcase.cli:cli"
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/marcusbuildsthings-droid/strcase"
|
|
29
|
+
Issues = "https://github.com/marcusbuildsthings-droid/strcase/issues"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""CLI for strcase."""
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from .converter import CONVERTERS, convert_all, detect_case, tokenize
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _read_input(text: str | None, file: str | None) -> list[str]:
|
|
11
|
+
"""Get input strings from args, stdin, or file."""
|
|
12
|
+
if file:
|
|
13
|
+
with open(file) as f:
|
|
14
|
+
return [line.rstrip('\n') for line in f if line.strip()]
|
|
15
|
+
if text:
|
|
16
|
+
return [text]
|
|
17
|
+
if not sys.stdin.isatty():
|
|
18
|
+
return [line.rstrip('\n') for line in sys.stdin if line.strip()]
|
|
19
|
+
raise click.UsageError('Provide TEXT argument, --file, or pipe via stdin.')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _output(results, as_json: bool):
|
|
23
|
+
if as_json:
|
|
24
|
+
click.echo(json.dumps(results, indent=2))
|
|
25
|
+
elif isinstance(results, list):
|
|
26
|
+
for r in results:
|
|
27
|
+
click.echo(r)
|
|
28
|
+
else:
|
|
29
|
+
click.echo(results)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@click.group()
|
|
33
|
+
@click.version_option()
|
|
34
|
+
def cli():
|
|
35
|
+
"""Convert strings between naming conventions."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _make_command(case_name: str, converter):
|
|
39
|
+
@cli.command(name=case_name)
|
|
40
|
+
@click.argument('text', required=False)
|
|
41
|
+
@click.option('-f', '--file', help='Read lines from file')
|
|
42
|
+
@click.option('--json', 'as_json', is_flag=True, help='JSON output')
|
|
43
|
+
def cmd(text, file, as_json):
|
|
44
|
+
f"""Convert to {case_name} case."""
|
|
45
|
+
lines = _read_input(text, file)
|
|
46
|
+
results = [converter(l) for l in lines]
|
|
47
|
+
if as_json:
|
|
48
|
+
_output([{'input': i, 'output': o} for i, o in zip(lines, results)], True)
|
|
49
|
+
else:
|
|
50
|
+
for r in results:
|
|
51
|
+
click.echo(r)
|
|
52
|
+
cmd.__doc__ = f'Convert to {case_name} case.'
|
|
53
|
+
return cmd
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
for _name, _fn in CONVERTERS.items():
|
|
57
|
+
_make_command(_name, _fn)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@cli.command()
|
|
61
|
+
@click.argument('text', required=False)
|
|
62
|
+
@click.option('-f', '--file', help='Read lines from file')
|
|
63
|
+
@click.option('--json', 'as_json', is_flag=True, help='JSON output')
|
|
64
|
+
def all(text, file, as_json):
|
|
65
|
+
"""Convert to all case styles at once."""
|
|
66
|
+
lines = _read_input(text, file)
|
|
67
|
+
if as_json:
|
|
68
|
+
_output([{'input': l, **convert_all(l)} for l in lines], True)
|
|
69
|
+
else:
|
|
70
|
+
for l in lines:
|
|
71
|
+
click.echo(f'Input: {l}')
|
|
72
|
+
for name, val in convert_all(l).items():
|
|
73
|
+
click.echo(f' {name:12s} → {val}')
|
|
74
|
+
click.echo()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@cli.command()
|
|
78
|
+
@click.argument('text')
|
|
79
|
+
@click.option('--json', 'as_json', is_flag=True, help='JSON output')
|
|
80
|
+
def detect(text, as_json):
|
|
81
|
+
"""Detect the case style of a string."""
|
|
82
|
+
style = detect_case(text)
|
|
83
|
+
tokens = tokenize(text)
|
|
84
|
+
if as_json:
|
|
85
|
+
_output({'input': text, 'detected': style, 'tokens': tokens}, True)
|
|
86
|
+
else:
|
|
87
|
+
click.echo(f'{style} (tokens: {tokens})')
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@cli.command()
|
|
91
|
+
def types():
|
|
92
|
+
"""List all supported case styles."""
|
|
93
|
+
examples = convert_all('myVariableName')
|
|
94
|
+
for name, ex in examples.items():
|
|
95
|
+
click.echo(f' {name:12s} {ex}')
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Core conversion logic."""
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def tokenize(s: str) -> list[str]:
|
|
6
|
+
"""Split a string into word tokens regardless of input case style."""
|
|
7
|
+
# Replace common separators with space
|
|
8
|
+
s = re.sub(r'[-_./\\]', ' ', s)
|
|
9
|
+
# Insert space before uppercase letters that follow lowercase (camelCase boundaries)
|
|
10
|
+
s = re.sub(r'([a-z\d])([A-Z])', r'\1 \2', s)
|
|
11
|
+
# Insert space between consecutive uppercase and lowercase (e.g., HTMLParser -> HTML Parser)
|
|
12
|
+
s = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1 \2', s)
|
|
13
|
+
return [w for w in s.split() if w]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def to_snake(s: str) -> str:
|
|
17
|
+
return '_'.join(w.lower() for w in tokenize(s))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def to_camel(s: str) -> str:
|
|
21
|
+
words = tokenize(s)
|
|
22
|
+
if not words:
|
|
23
|
+
return ''
|
|
24
|
+
return words[0].lower() + ''.join(w.capitalize() for w in words[1:])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def to_pascal(s: str) -> str:
|
|
28
|
+
return ''.join(w.capitalize() for w in tokenize(s))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def to_kebab(s: str) -> str:
|
|
32
|
+
return '-'.join(w.lower() for w in tokenize(s))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def to_screaming(s: str) -> str:
|
|
36
|
+
return '_'.join(w.upper() for w in tokenize(s))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def to_dot(s: str) -> str:
|
|
40
|
+
return '.'.join(w.lower() for w in tokenize(s))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def to_path(s: str) -> str:
|
|
44
|
+
return '/'.join(w.lower() for w in tokenize(s))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def to_title(s: str) -> str:
|
|
48
|
+
return ' '.join(w.capitalize() for w in tokenize(s))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def to_sentence(s: str) -> str:
|
|
52
|
+
words = tokenize(s)
|
|
53
|
+
if not words:
|
|
54
|
+
return ''
|
|
55
|
+
return words[0].capitalize() + ' ' + ' '.join(w.lower() for w in words[1:]) if len(words) > 1 else words[0].capitalize()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def to_flat(s: str) -> str:
|
|
59
|
+
return ''.join(w.lower() for w in tokenize(s))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def to_cobol(s: str) -> str:
|
|
63
|
+
return '-'.join(w.upper() for w in tokenize(s))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def to_train(s: str) -> str:
|
|
67
|
+
return '-'.join(w.capitalize() for w in tokenize(s))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
CONVERTERS = {
|
|
71
|
+
'snake': to_snake,
|
|
72
|
+
'camel': to_camel,
|
|
73
|
+
'pascal': to_pascal,
|
|
74
|
+
'kebab': to_kebab,
|
|
75
|
+
'screaming': to_screaming,
|
|
76
|
+
'dot': to_dot,
|
|
77
|
+
'path': to_path,
|
|
78
|
+
'title': to_title,
|
|
79
|
+
'sentence': to_sentence,
|
|
80
|
+
'flat': to_flat,
|
|
81
|
+
'cobol': to_cobol,
|
|
82
|
+
'train': to_train,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def detect_case(s: str) -> str:
|
|
87
|
+
"""Best-effort detection of the current case style."""
|
|
88
|
+
if '_' in s and s == s.upper():
|
|
89
|
+
return 'screaming'
|
|
90
|
+
if '_' in s and s == s.lower():
|
|
91
|
+
return 'snake'
|
|
92
|
+
if '-' in s and s == s.upper():
|
|
93
|
+
return 'cobol'
|
|
94
|
+
if '-' in s and s == s.lower():
|
|
95
|
+
return 'kebab'
|
|
96
|
+
if '-' in s and s[0].isupper():
|
|
97
|
+
return 'train'
|
|
98
|
+
if '.' in s:
|
|
99
|
+
return 'dot'
|
|
100
|
+
if '/' in s:
|
|
101
|
+
return 'path'
|
|
102
|
+
if ' ' in s:
|
|
103
|
+
if s[0].isupper() and all(w[0].isupper() for w in s.split() if w):
|
|
104
|
+
return 'title'
|
|
105
|
+
return 'sentence'
|
|
106
|
+
if s[0].islower() and any(c.isupper() for c in s):
|
|
107
|
+
return 'camel'
|
|
108
|
+
if s[0].isupper() and any(c.isupper() for c in s[1:]):
|
|
109
|
+
return 'pascal'
|
|
110
|
+
return 'unknown'
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def convert_all(s: str) -> dict[str, str]:
|
|
114
|
+
"""Convert to all styles."""
|
|
115
|
+
return {name: fn(s) for name, fn in CONVERTERS.items()}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: strcase-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more
|
|
5
|
+
Author-email: Marcus <marcus@marcusbuilds.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/marcusbuildsthings-droid/strcase
|
|
8
|
+
Project-URL: Issues, https://github.com/marcusbuildsthings-droid/strcase/issues
|
|
9
|
+
Keywords: cli,string,case,convert,camelCase,snake_case
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Text Processing
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: click>=8.0
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# strcase-cli
|
|
23
|
+
|
|
24
|
+
Convert strings between naming conventions from the command line.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install strcase-cli
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
strcase snake "myVariableName" # my_variable_name
|
|
36
|
+
strcase camel "my_variable_name" # myVariableName
|
|
37
|
+
strcase pascal "my-variable-name" # MyVariableName
|
|
38
|
+
strcase kebab "MyVariableName" # my-variable-name
|
|
39
|
+
strcase screaming "myVar" # MY_VAR
|
|
40
|
+
strcase dot "myVar" # my.var
|
|
41
|
+
strcase title "my_var_name" # My Var Name
|
|
42
|
+
strcase train "myVarName" # My-Var-Name
|
|
43
|
+
strcase cobol "myVarName" # MY-VAR-NAME
|
|
44
|
+
strcase all "myVariableName" # Show all conversions
|
|
45
|
+
strcase detect "my_variable_name" # snake
|
|
46
|
+
strcase types # List all styles
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
|
|
50
|
+
|
|
51
|
+
## For AI Agents
|
|
52
|
+
|
|
53
|
+
See [SKILL.md](SKILL.md) for agent-optimized documentation.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
strcase/__init__.py
|
|
5
|
+
strcase/cli.py
|
|
6
|
+
strcase/converter.py
|
|
7
|
+
strcase_cli.egg-info/PKG-INFO
|
|
8
|
+
strcase_cli.egg-info/SOURCES.txt
|
|
9
|
+
strcase_cli.egg-info/dependency_links.txt
|
|
10
|
+
strcase_cli.egg-info/entry_points.txt
|
|
11
|
+
strcase_cli.egg-info/requires.txt
|
|
12
|
+
strcase_cli.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
click>=8.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
strcase
|