Skip to content

Commit 148c71f

Browse files
committed
Add support for shell input mode. Support limited curly brace expansion and allow escaping of characters such as space.
1 parent 092b565 commit 148c71f

5 files changed

Lines changed: 99 additions & 3 deletions

File tree

AdvancedNewFile.sublime-settings

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,13 @@
120120
// must either be absolute, or be from the home directory of the user (`~/`). If a
121121
// string is used, or the list contains a single entry, it will be automatically
122122
// inserted into any newly created files.
123-
"file_templates": {}
123+
"file_templates": {},
124+
125+
// Setting this value to true will allow you to escape characters as you normally
126+
// would when using a shell. For example, given the input string "foo\ bar", false
127+
// would result in a file named " bar" in the foo directory. With the value set to
128+
// true, a file named "foo bar" would be created. In addition, setting this value
129+
// to true will allow for curly brace expansion. Currently, only comma separated
130+
// entries are supported.
131+
"shell_input": false
124132
}

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ Setting to control if VCS management is used when moving and removing files.
160160

161161
An object containing information to use for templates when creating new files. The key values for this object should be a file extension. The value may either be a string of the content to be inserted or a list of paths. If a list of paths is specified, the name of the file will be displayed during selection. The paths must either be absolute, or be from the home directory of the user (`~/`). If a string is used, or the list contains a single entry, it will be automatically inserted into any newly created files.
162162

163+
`posix_input`:
164+
165+
Setting this value to true will allow you to escape characters as you normally would when using a shell. For example, given the input string "foo\ bar", false would result in a file named " bar" in the foo directory. With the value set to true, a file named "foo bar" would be created. In addition, setting this value to true will allow for curly brace expansion. Currently, only comma separated entries are supported.
166+
163167
### Project Specific Settings
164168
All of the above settings can also be specified as part of the project specific settings. These values override any previous values set by higher level settings, with aliases being an exception. Alias settings will be merged with higher level configurations for alias. In addition, if the same alias exist for both default/user settings and project settings, the project setting will take precedence.
165169

advanced_new_file/anf_util.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
RENAME_DEFAULT_SETTING = "rename_default"
2828
VCS_MANAGEMENT_SETTING = "vcs_management"
2929
FILE_TEMPLATES_SETTING = "file_templates"
30+
SHELL_INPUT_SETTING = "shell_input"
3031

3132
SETTINGS = [
3233
ALIAS_SETTING,
@@ -53,7 +54,8 @@
5354
FOLDER_PERMISSIONS_SETTING,
5455
RENAME_DEFAULT_SETTING,
5556
VCS_MANAGEMENT_SETTING,
56-
FILE_TEMPLATES_SETTING
57+
FILE_TEMPLATES_SETTING,
58+
SHELL_INPUT_SETTING
5759
]
5860

5961
NIX_ROOT_REGEX = r"^/"

advanced_new_file/commands/command_base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import re
44
import sublime
5+
import shlex
56

67
from ..anf_util import *
78
from ..platform.windows_platform import WindowsPlatform
@@ -124,6 +125,9 @@ def split_path(self, path=""):
124125
root = None
125126
try:
126127
root, path = self.platform.split(path)
128+
if self.settings.get(SHELL_INPUT_SETTING, False) and len(path) > 0:
129+
split_path = shlex.split(path)
130+
path = " ".join(split_path)
127131
# Parse if alias
128132
if TOP_LEVEL_SPLIT_CHAR in path and root is None:
129133
parts = path.rsplit(TOP_LEVEL_SPLIT_CHAR, 1)
@@ -158,6 +162,14 @@ def split_path(self, path=""):
158162

159163
return root, path
160164

165+
def bash_expansion(self, path):
166+
if len(path) == 0:
167+
return path
168+
169+
split_path = shlex.split(path)
170+
new_path = " ".join(split_path)
171+
return new_path
172+
161173
def __translate_alias(self, path):
162174
root = None
163175
split_path = None

advanced_new_file/commands/new_file_command.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sublime
22
import sublime_plugin
33
import os
4+
import re
45
import xml.etree.ElementTree as ET
56

67
from .command_base import AdvancedNewFileBase
@@ -23,6 +24,16 @@ def input_panel_caption(self):
2324
return caption
2425

2526
def entered_file_action(self, path):
27+
if self.settings.get(SHELL_INPUT_SETTING, False):
28+
self.multi_file_action(self.curly_brace_expansion(path))
29+
else:
30+
self.single_file_action(path)
31+
32+
def multi_file_action(self, paths):
33+
for path in paths:
34+
self.single_file_action(path, False)
35+
36+
def single_file_action(self, path, apply_template=True):
2637
attempt_open = True
2738
file_exist = os.path.exists(path)
2839
if not file_exist:
@@ -35,9 +46,68 @@ def entered_file_action(self, path):
3546
print("Exception: %s '%s'" % (e.strerror, e.filename))
3647
if attempt_open:
3748
file_view = self.open_file(path)
38-
if not file_exist:
49+
if not file_exist and apply_template:
3950
file_view.settings().set("_anf_new", True)
4051

52+
def curly_brace_expansion(self, path):
53+
if not self.curly_braces_balanced(path) or "{" not in path:
54+
return [path]
55+
paths = self.expand_single_curly_brace(path)
56+
57+
while True:
58+
path_len = len(paths)
59+
temp_paths = []
60+
for expanded_path in paths:
61+
temp_paths.append(self.expand_single_curly_brace(expanded_path))
62+
paths = self.flatten_list(temp_paths)
63+
if path_len == len(paths):
64+
break
65+
66+
return self.flatten_list(paths)
67+
68+
def flatten_list(self, initial_list):
69+
if isinstance(initial_list, list):
70+
return [flattened for entry in initial_list for flattened in self.flatten_list(entry)]
71+
else:
72+
return [initial_list]
73+
74+
75+
# Assumes curly braces are balanced
76+
def expand_single_curly_brace(self, path):
77+
if "{" not in path:
78+
return [path]
79+
start, end = self.curly_brace_indecies(path)
80+
all_tokens = path[start + 1:end]
81+
paths = []
82+
for token in all_tokens.split(","):
83+
temp = path[0:start] + token + path[end + 1:]
84+
paths.append(temp)
85+
return paths
86+
87+
# Assumes curly braces are balanced.
88+
def curly_brace_indecies(self, path, count=0,open_index=None):
89+
if len(path) == 0:
90+
return None
91+
c = path[0]
92+
if c == "{":
93+
return self.curly_brace_indecies(path[1:], count + 1, count)
94+
elif c == "}":
95+
return open_index, count
96+
else:
97+
return self.curly_brace_indecies(path[1:], count + 1, open_index)
98+
99+
def curly_braces_balanced(self, path, count=0):
100+
if len(path) == 0 or count < 0:
101+
return count == 0
102+
103+
c = path[0]
104+
if c == "{":
105+
return self.curly_braces_balanced(path[1:], count + 1)
106+
elif c == "}":
107+
return self.curly_braces_balanced(path[1:], count - 1)
108+
else:
109+
return self.curly_braces_balanced(path[1:], count)
110+
41111
def update_status_message(self, creation_path):
42112
if self.view is not None:
43113
self.view.set_status("AdvancedNewFile", "Creating file at %s " %

0 commit comments

Comments
 (0)