Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some changes to make it work like Emacs vertical file completion. #185

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AdvancedNewFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

# Make sure all dependencies are reloaded on upgrade
if reloader in sys.modules:
reload(sys.modules[reloader])
reload(sys.modules[reloader]) # type: ignore

if VERSION > 3000:
from .advanced_new_file import reloader
Expand Down
3 changes: 0 additions & 3 deletions AdvancedNewFile.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
// A default initial value to fill the create new file input path with.
"default_initial": "",

// When renaming a file it will we pre populated with the file existing filename.
"autofill_path_the_existing": false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I questioned why the setting was removed, but in hindsight it never made it into a release (a5f062b), the name is questionable, I'm not sure if the code even works, and the behavior is somewhat as well, though I can see the appeal. Regardless, the opposite should have been the default.

A mention of that in the commit message (and having it in a separate comment) would have been nice, though.


// A boolean defining if cursor text should be used. Text bound by single or
// double quotes or within a region will be used. If multiple cursors
// are used, the earliest selection containing a region or existing
Expand Down
14 changes: 13 additions & 1 deletion Default (Linux).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,17 @@
"context": [{
"key": "setting.anf_panel"
}]
}
},
{"keys": ["ctrl+n"],"command": "advanced_new_file_next",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+p"],"command": "advanced_new_file_prev",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
Copy link
Member

@FichteFoll FichteFoll Jun 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why L? Is that how emacs does it? Please add some comments above the binding to explain their inspiration because I (for example) wouldn't know otherwise. Probably to the readme as well.

"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is how tab completion works currently, but I find that questionable when you could instead bind the tab key to a proper command instead.

"context": [{"key": "setting.anf_panel"}]
},
]
14 changes: 13 additions & 1 deletion Default (OSX).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,17 @@
"context": [{
"key": "setting.anf_panel"
}]
}
},
{"keys": ["ctrl+n"],"command": "advanced_new_file_next",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+p"],"command": "advanced_new_file_prev",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
"context": [{"key": "setting.anf_panel"}]
},
]
14 changes: 13 additions & 1 deletion Default (Windows).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,17 @@
"context": [{
"key": "setting.anf_panel"
}]
}
},
{"keys": ["ctrl+n"],"command": "advanced_new_file_next",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+p"],"command": "advanced_new_file_prev",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
"context": [{"key": "setting.anf_panel"}]
},
]
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ Note with either method, you may need to restart Sublime Text 2 for the plugin t
Installation through [package control](http://wbond.net/sublime_packages/package_control) is recommended. It will handle updating your packages as they become available. To install, do the following.

* In the Command Palette, enter `Package Control: Install Package`
* Search for `ANF` to see the list of available commands
* Search for `AdvancedNewFile`

### Manual
Clone or copy this repository into the packages directory. You will need to rename the folder to `AdvancedNewFile` if using this method. By default, the Package directory is located at:

* OS X: ~/Library/Application Support/Sublime Text 2/Packages/
* Windows: %APPDATA%/Sublime Text 2/Packages/
* Windows: %APPDATA%/Roaming/Sublime Text 2/Packages/
* Linux: ~/.config/sublime-text-2/Packages/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit removed ST2 (and Python 2.6) support by changing the super calls and I think that's perfectly fine, but the documentaiton should be updated accordingly.


or

* OS X: ~/Library/Application Support/Sublime Text 3/Packages/
* Windows: %APPDATA%/Sublime Text 3/Packages/
* Windows: %APPDATA%/Roaming/Sublime Text 3/Packages/
* Linux: ~/.config/sublime-text-3/Packages/

Depending on your install on windows, the ST packages path may be `%APPDATA%/Sublime Text 2/...`

## Usage
Simply bring up the AdvancedNewFile input through the appropriate [key binding](https://github.com/skuroda/Sublime-AdvancedNewFile#keymaps). Then, enter the path, along with the file name into the input field. Upon pressing enter, the file will be created. In addition, if the directories specified do not yet exists, they will also be created. For more advanced usage of this plugin, be sure to look at [Advanced Path Usage](https://github.com/skuroda/Sublime-AdvancedNewFile#advanced-path-usage). By default, the path to the file being created will be filled shown in the status bar as you enter the path information.
Simply bring up the AdvancedNewFile input through the appropriate [key binding](https://github.com/skuroda/Sublime-AdvancedNewFile). Then, enter the path, along with the file name into the input field. Upon pressing enter, the file will be created. In addition, if the directories specified do not yet exists, they will also be created. For more advanced usage of this plugin, be sure to look at [Advanced Path Usage](https://github.com/skuroda/Sublime-AdvancedNewFile#advanced-path-usage). By default, the path to the file being created will be filled shown in the status bar as you enter the path information.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the "key binding" link supposed to point to? (needs to be updated for the repo move, too)

A mention of the command palette would also be nice.


**Default directory:**
The default directory is specified by the `default_root` setting. By default, it will be the top directory of the folders listed in the window. If this cannot be resolved, the home directory will be used. See [Settings](https://github.com/skuroda/Sublime-AdvancedNewFile#settings) (`default_root`) for more information.
Expand Down Expand Up @@ -233,7 +233,7 @@ To begin at the home directory simply start with `~/` like you would in the shel
#### Aliases:
You can create an alias to quickly navigate to a directory. Simply type in the alias followed by a colon. Then specify the path as you would normally. Note, in an event a specified alias conflicts with a [predefined alias](https://github.com/skuroda/Sublime-AdvancedNewFile#predefined-aliases), the specified alias will take precedence.

Alias paths may be relative or absolute. If a relative path is specified, the `alias_root` setting will be used as the base. When specifying absolute paths, be sure to use the system specific style (e.g. Windows `C:\\Users\\username\\Desktop`, OS X and Linux `/home/username/desktop/`). In addition, you may specify an alias from the home directory by using `~/`.
Alias paths may be relative or absolute. If a relative path is specified, the `alias_root` setting will be used as the base. When specifying absolute paths, be sure to use the system specific style (e.g. Windows `C:\\Users\\username\\Desktop`, OS X and Linix `/home/username/desktop/`). In addition, you may specify an alias from the home directory by using `~/`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduced a typo.


If an invalid alias is specified, an error pop up will be displayed when trying to create the file.

Expand Down
2 changes: 0 additions & 2 deletions advanced_new_file/anf_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

ALIAS_SETTING = "alias"
DEFAULT_INITIAL_SETTING = "default_initial"
AUTOFILL_RENAME = "autofill_path_the_existing"
USE_CURSOR_TEXT_SETTING = "use_cursor_text"
SHOW_FILES_SETTING = "show_files"
SHOW_PATH_SETTING = "show_path"
Expand Down Expand Up @@ -46,7 +45,6 @@
SETTINGS = [
ALIAS_SETTING,
DEFAULT_INITIAL_SETTING,
AUTOFILL_RENAME,
USE_CURSOR_TEXT_SETTING,
SHOW_FILES_SETTING,
SHOW_PATH_SETTING,
Expand Down
5 changes: 4 additions & 1 deletion advanced_new_file/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .helper_commands import AnfReplaceCommand, AdvancedNewFileCommand, AnfRemoveRegionContentAndRegionCommand
from .new_file_command import AdvancedNewFileNew, AdvancedNewFileNewAtCommand, AdvancedNewFileNewAtFileCommand, AdvancedNewFileNewEventListener
from .new_file_command import AdvancedNewFileNew, AdvancedNewFileNextCommand, AdvancedNewFilePrevCommand, AdvancedNewFileUpdirCommand, AdvancedNewFileNewAtCommand, AdvancedNewFileNewAtFileCommand, AdvancedNewFileNewEventListener
from .delete_file_command import AdvancedNewFileDelete
from .cut_to_file import AdvancedNewFileCutToFile
from .move_file_command import AdvancedNewFileMove, AdvancedNewFileMoveAtCommand
Expand All @@ -9,6 +9,9 @@
"AnfReplaceCommand",
"AdvancedNewFileCommand",
"AdvancedNewFileNew",
"AdvancedNewFileNextCommand",
"AdvancedNewFilePrevCommand",
"AdvancedNewFileUpdirCommand",
"AdvancedNewFileNewAtCommand",
"AdvancedNewFileNewAtFileCommand",
"AdvancedNewFileNewEventListener",
Expand Down
126 changes: 112 additions & 14 deletions advanced_new_file/commands/command_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sublime
import sublime_plugin
import shlex
import json

from ..anf_util import *
from ..platform.windows_platform import WindowsPlatform
Expand All @@ -22,9 +23,12 @@


class AdvancedNewFileBase(object):
static_input_panel_view = None
FichteFoll marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, window):
super(AdvancedNewFileBase, self).__init__(window)
super()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-op. Can be removed or replaced with super().__init__().

self.window = window
self.prev_text = None

if PLATFORM == "windows":
self.platform = WindowsPlatform(window.active_view())
Expand Down Expand Up @@ -91,9 +95,10 @@ def run_setup(self):
def __get_aliases(self):
aliases = self.settings.get(ALIAS_SETTING)
all_os_aliases = self.settings.get(OS_SPECIFIC_ALIAS_SETTING)
for key in all_os_aliases:
if PLATFORM in all_os_aliases.get(key):
aliases[key] = all_os_aliases.get(key).get(PLATFORM)
if all_os_aliases is not None and aliases is not None:
for key in all_os_aliases:
if PLATFORM in all_os_aliases.get(key):
aliases[key] = all_os_aliases.get(key).get(PLATFORM)

return aliases

Expand Down Expand Up @@ -281,28 +286,53 @@ def show_filename_input(self, initial):
self.input_panel_view.settings().set("anf_panel", True)
if self.settings.get(CURSOR_BEFORE_EXTENSION_SETTING):
self.__place_cursor_before_extension(self.input_panel_view)
AdvancedNewFileBase.static_input_panel_view = self.input_panel_view
self.__update_filename_input('')

def __update_filename_input(self, path_in):
new_content = path_in
if self.settings.get(COMPLETION_TYPE_SETTING) == "windows":
if "prev_text" in dir(self) and self.prev_text != path_in:
if self.view is not None:
self.view.erase_status("AdvancedNewFile2")

if path_in.endswith("\t"):
new_content = self.completion.completion(path_in.replace("\t", ""))
if new_content != path_in:
self.input_panel_view.run_command("anf_replace",
{"content": new_content})
creation_path, candidate, completion_list = self.parse_status_line(self.get_status_line()) # type: ignore
print("candidate", candidate, str(completion_list))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug prints.

new_content = self.completion_input(path_in.replace("\t", ""), candidate)
print("new_content", new_content)
# new_content = candidate
else:
base, path = self.split_path(path_in)
completion_list = self.completion.hint(path_in)
if completion_list:
candidate = completion_list[0]
completion_list.remove(candidate)
else:
candidate = ''

creation_path = generate_creation_path(self.settings, base, path,
True)
input_view = AdvancedNewFileBase.static_input_panel_view
if input_view:
input_view.hide_popup()
if input_view and new_content != path_in:
input_view.run_command("anf_replace", {"content": new_content})
else:
base, path = self.split_path(path_in)
status_line = generate_creation_path(self.settings, base, path, True) + '|' + candidate + str(completion_list)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this format. What is the purpose?

if self.settings.get(SHOW_PATH_SETTING, False):
self.update_status_message(creation_path)
self.update_status_message(status_line)
if input_view and candidate and not new_content.endswith(candidate):
input_view.show_popup('<strong>' + candidate + '</strong><br/>' + '<br/>'.join(completion_list))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may be interested to know that normal completions as in the auto-complete popup should also be working in input panels, though that is probably something for later. It might only work for ST4 though, iirc.

Could even make use of the async completion provider API because of having to query the filesystem.


def update_status_message(self, creation_path):
pass
def completion_input(self, path_in, candidate):
pattern = r"(.*[/\\:])(.*)"

match = re.match(pattern, path_in)
if match:
new_content = re.sub(pattern, r"\1", path_in)
new_content += candidate
else:
new_content = candidate
return new_content

def entered_file_action(self, path):
pass
Expand Down Expand Up @@ -364,6 +394,7 @@ def clear(self):
if self.view is not None:
self.view.erase_status("AdvancedNewFile")
self.view.erase_status("AdvancedNewFile2")
AdvancedNewFileBase.static_input_panel_view = None

def create(self, filename):
base, filename = os.path.split(filename)
Expand Down Expand Up @@ -466,3 +497,70 @@ def __place_cursor_before_extension(self, view):
initial_position = len(matcher.group(1))
cursors.clear()
cursors.add(sublime.Region(initial_position, initial_position))

def get_status_line(self):
return self.view.get_status("AdvancedNewFile")

def update_status_message(self, creation_path):
if self.view is not None:
self.view.set_status("AdvancedNewFile", creation_path)
else:
sublime.status_message(creation_path)

def get_status_prefix(self):
pass

def create_status_line(self, creation_path, candidate, completion_list):
return creation_path + '|' + candidate + str(completion_list)

def parse_status_line(self, status_line):
# Creating file at AdvancedNewFile/advanced_new_file/commands/|__init__.py['command_base.py']
FichteFoll marked this conversation as resolved.
Show resolved Hide resolved
if status_line:
status_line = status_line.strip()
index1 = status_line.rindex('[')
completion_list = status_line[index1:]
try:
completion_list = json.loads(completion_list.replace("'", '"'))
except Exception as e:
print("completion_list", completion_list, e)
raise e
index2 = status_line.rindex('|')
candidate = status_line[index2 + 1:index1]
# TODO: prefix_len = len(self.get_status_prefix())
creation_path = status_line[0:index2]
return (creation_path, candidate, completion_list)
else:
return ('', '', [])

def next_candidate(self, candidate, completion_list):
if candidate and completion_list:
# replace the candidate with the first, and append the old candidate to the last
completion_list.append(candidate)
candidate = completion_list[0]
completion_list.remove(candidate)

return (candidate, completion_list)

def prev_candidate(self, candidate, completion_list):
if candidate and completion_list:
# replace the candidate with the last, and insert the old candidate to the first
completion_list.insert(0, candidate)
candidate = completion_list.pop()

return (candidate, completion_list)

def create_next_status_line(self, creation_path, candidate, completion_list):
if candidate and completion_list:
candidate, completion_list = self.next_candidate(candidate, completion_list)
return self.create_status_line(creation_path, candidate, completion_list)
else:
# case1: origin completion_list is empty. case2: origin completion_list contains only 1 item
sublime.status_message("Completion list is empty.")

def create_prev_status_line(self, creation_path, candidate, completion_list):
if candidate and completion_list:
candidate, completion_list = self.prev_candidate(candidate, completion_list)
return self.create_status_line(creation_path, candidate, completion_list)
else:
# case1: origin completion_list is empty. case2: origin completion_list contains only 1 item
sublime.status_message("Completion list is empty.")
2 changes: 1 addition & 1 deletion advanced_new_file/commands/copy_file_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class AdvancedNewFileCopy(DuplicateFileBase):
def __init__(self, window):
super(AdvancedNewFileCopy, self).__init__(window)
super().__init__(window)

def get_default_setting(self):
return COPY_DEFAULT_SETTING
Expand Down
4 changes: 3 additions & 1 deletion advanced_new_file/commands/cut_to_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class AdvancedNewFileCutToFile(AdvancedNewFileBase, sublime_plugin.WindowCommand):
def __init__(self, window):
super(AdvancedNewFileCutToFile, self).__init__(window)
super().__init__(window)

def run(self, is_python=False):
self.is_python = is_python
Expand Down Expand Up @@ -72,6 +72,8 @@ def _open_and_add_content_to_file(self, path):

def is_enabled(self):
view = self.window.active_view()
if view is None:
return False
cursors = view.sel()
for cursor in cursors:
if not cursor.empty():
Expand Down
2 changes: 1 addition & 1 deletion advanced_new_file/commands/delete_file_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class AdvancedNewFileDelete(AdvancedNewFileBase, sublime_plugin.WindowCommand,
GitCommandBase):
def __init__(self, window):
super(AdvancedNewFileDelete, self).__init__(window)
super().__init__(window)

def run(self, current=False):
self.run_setup()
Expand Down
Loading