Browse Source

switch back to old way

master
Randy Lai 4 years ago
parent
commit
9d2c7b97cc
  1. 124
      CHANGELOG.md
  2. 0
      json_file.py
  3. 509
      project_manager.py
  4. 4
      src/__init__.py
  5. 397
      src/project_manager.py
  6. 28
      src/text_commands.py
  7. 114
      src/window_commands.py
  8. 0
      support/Default (Linux).sublime-keymap
  9. 0
      support/Default (OSX).sublime-keymap
  10. 0
      support/Default (Windows).sublime-keymap
  11. 4
      support/Default.sublime-commands
  12. 19
      support/Main.sublime-menu
  13. 0
      support/project_manager.sublime-settings

124
CHANGELOG.md

@ -1,124 +0,0 @@
## CHANGELOG
### [0.7.5](https://github.com/randy3k/ProjectManager/compare/0.7.3...0.7.5)
Changes since 0.7.3:
Other:
- fix CHANGLOG
- need to encode list and trim CR
- execute on_activated callbacks when openning projects
- remove build-in recent project list when cleaning recent projects
- remove fix old settings code
- Update README.md
- simplify exit logic
- add more delay to on_activated events
- use tuple arguments
Contributors:
- Randy Lai
### [0.7.3](https://github.com/randy3k/ProjectManager/compare/0.7.2...0.7.3)
Changes since 0.7.2:
Other:
- Refactor python code
Contributors:
- Randy Lai
- Johannes Rappen
### [0.7.2](https://github.com/randy3k/ProjectManager/compare/0.7.1...0.7.2)
* update README
* add key bindings for windows and linux
* use realpath for detecting window to close
* better name the command as "Add New Project"
### [0.7.1](https://github.com/randy3k/ProjectManager/compare/0.7.0...0.7.1)
* fix #55
### [0.7.0](https://github.com/randy3k/ProjectManager/compare/0.6.11...0.7.0)
* fix typo
* remove show_open_files settings as the bug was fixed
* use re.sub instead of replace to fix #54
* use relative link
* rename as ProjectManager
### [0.6.11](https://github.com/randy3k/ProjectManager/compare/0.6.10...0.6.11)
* redundant caption
* feature: remove dead projects
* change default order of projects list
### [0.6.10](https://github.com/randy3k/ProjectManager/compare/0.6.9...0.6.10)
* cannonicalize projects directories
* update menus and screenshots
* use close_all instead
### [0.6.9](https://github.com/randy3k/ProjectManager/compare/0.6.8...0.6.9)
* close project by window or name
### [0.6.8](https://github.com/randy3k/ProjectManager/compare/0.6.7...0.6.8)
* use try-catch errors
* only when library exists
* no long check close_windows_when_empty
* rename to get_info_from_project_file
* cannonicalize paths to fix #47
### [0.6.7](https://github.com/randy3k/ProjectManager/compare/0.6.6...0.6.7)
* use set_timeout instead of set_timeout_async
* only check library file if it exists
* rename functions for better readability
* only close non-active window
### [0.6.6](https://github.com/randy3k/ProjectManager/compare/0.6.5...0.6.6)
* focus on the original view
### [0.6.5](https://github.com/randy3k/ProjectManager/compare/0.6.4...0.6.5)
* auto refresh folder list
* various updates
* update README
* confirm to clear recent projects
* remove refresh folder functionality
* add emptylink in before / after code block
* fix #2
### [0.6.4](https://github.com/randy3k/ProjectManager/compare/0.6.3...0.6.4)
* show message when project list is empty
### [0.6.3](https://github.com/randy3k/ProjectManager/compare/0.6.2...0.6.3)
* fix window closing behaviour
* fix which_project_dir bug again
### [0.6.2](https://github.com/randy3k/ProjectManager/compare/0.6.1...0.6.2)
* bootstrap manager run function
* resolve symlink
* rename function to expand_folder
* fix which_project_dir
### [0.6.1](https://github.com/randy3k/ProjectManager/compare/0.6.0...0.6.1)
* add `get_project_files()`
* add `get_project_info()`
* don't use timeoout_async
* pep8 fix
### 0.6.0
* first release

0
src/json_file.py → json_file.py

509
project_manager.py

@ -1,5 +1,508 @@
#!/usr/bin/env python
# coding: utf-8
import sublime
import sublime_plugin
import subprocess
import os
import platform
import re
from .json_file import JsonFile
from .src import *
def subl(*args):
# learnt from SideBarEnhancements
executable_path = sublime.executable_path()
if sublime.platform() == 'osx':
app_path = executable_path[:executable_path.rfind('.app/') + 5]
executable_path = app_path + 'Contents/SharedSupport/bin/subl'
subprocess.Popen([executable_path] + list(args))
def on_activated():
window = sublime.active_window()
view = window.active_view()
if sublime.platform() == 'windows':
# fix focus on windows
window.run_command('focus_neighboring_group')
window.focus_view(view)
sublime_plugin.on_activated(view.id())
sublime_plugin.on_activated_async(view.id())
sublime.set_timeout(on_activated, 300)
def expand_folder(folder, project_file):
root = os.path.dirname(project_file)
if not os.path.isabs(folder):
folder = os.path.abspath(os.path.join(root, folder))
return folder
def get_node():
if sublime.platform() == 'osx':
node = subprocess.check_output(['scutil', '--get', 'ComputerName']).decode().strip()
else:
node = platform.node().split('.')[0]
return node
def dont_close_windows_when_empty(func):
def f(*args, **kwargs):
s = sublime.load_settings('Preferences.sublime-settings')
close_windows_when_empty = s.get('close_windows_when_empty')
s.set('close_windows_when_empty', False)
func(*args, **kwargs)
if close_windows_when_empty:
s.set('close_windows_when_empty', close_windows_when_empty)
return f
class Manager:
def __init__(self, window):
self.window = window
s = 'project_manager.sublime-settings'
self.settings = sublime.load_settings(s)
default_projects_dir = os.path.join(sublime.packages_path(),
'User',
'Projects')
self.projects_path = self.settings.get(
'projects_path', [self.settings.get('projects_dir', default_projects_dir)])
self.projects_path = [
os.path.normpath(os.path.expanduser(d)) for d in self.projects_path]
node = get_node()
if self.settings.get('use_local_projects_dir', False):
self.projects_path = \
[d + ' - ' + node for d in self.projects_path] + self.projects_path
self.primary_dir = self.projects_path[0]
self.projects_info = self.get_all_projects_info()
def list_project_files(self, folder):
pfiles = []
library = os.path.join(folder, 'library.json')
if os.path.exists(library):
j = JsonFile(library)
for f in j.load([]):
if os.path.exists(f) and f not in pfiles:
pfiles.append(os.path.normpath(f))
pfiles.sort()
j.save(pfiles)
for path, dirs, files in os.walk(folder, followlinks=True):
for f in files:
f = os.path.join(path, f)
if f.endswith('.sublime-project') and f not in pfiles:
pfiles.append(os.path.normpath(f))
# remove empty directories
for d in dirs:
d = os.path.join(path, d)
if len(os.listdir(d)) == 0:
os.rmdir(d)
return pfiles
def get_info_from_project_file(self, pfile):
pdir = self.which_project_dir(pfile)
if pdir:
pname = re.sub('\.sublime-project$',
'',
os.path.relpath(pfile, pdir))
else:
pname = re.sub('\.sublime-project$',
'',
os.path.basename(pfile))
pd = JsonFile(pfile).load()
if pd and 'folders' in pd and pd['folders']:
folder = pd['folders'][0].get('path', '')
else:
folder = ''
star = False
for w in sublime.windows():
if w.project_file_name() == pfile:
star = True
break
return {
pname: {
'folder': expand_folder(folder, pfile),
'file': pfile,
'star': star
}
}
def get_all_projects_info(self):
ret = {}
for pdir in self.projects_path:
pfiles = self.list_project_files(pdir)
for f in pfiles:
ret.update(self.get_info_from_project_file(f))
return ret
def which_project_dir(self, pfile):
for pdir in self.projects_path:
if (os.path.realpath(os.path.dirname(pfile))+os.path.sep).startswith(
os.path.realpath(pdir)+os.path.sep):
return pdir
return None
def display_projects(self):
plist = [[key, key + '*' if value['star'] else key, value['folder'], value['file']]
for key, value in self.projects_info.items()]
plist = sorted(plist)
if self.settings.get('show_recent_projects_first', True):
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
recent = j.load([])
plist = sorted(plist,
key=lambda p: recent.index(p[3]) if p[3] in recent else -1,
reverse=True)
count = 0
for i in range(len(plist)):
if plist[i][0] is not plist[i][1]:
plist.insert(count, plist.pop(i))
count = count + 1
return [item[0] for item in plist], [[item[1], item[2]] for item in plist]
def project_file_name(self, project):
return self.projects_info[project]['file']
def project_workspace(self, project):
return re.sub('\.sublime-project$',
'.sublime-workspace',
self.project_file_name(project))
def update_recent(self, project):
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
recent = j.load([])
pname = self.project_file_name(project)
if pname not in recent:
recent.append(pname)
else:
recent.append(recent.pop(recent.index(pname)))
# only keep the most recent 50 records
if len(recent) > 50:
recent = recent[(50-len(recent)):len(recent)]
j.save(recent)
def clear_recent_projects(self):
def clear_callback():
answer = sublime.ok_cancel_dialog('Clear Recent Projects?')
if answer is True:
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
j.remove()
self.window.run_command("clear_recent_projects_and_workspaces")
sublime.set_timeout(clear_callback, 100)
def get_project_data(self, project):
return JsonFile(self.project_file_name(project)).load()
def check_project(self, project):
wsfile = self.project_workspace(project)
j = JsonFile(wsfile)
if not os.path.exists(wsfile):
j.save({})
elif self.settings.has('show_open_files'):
show_open_files = self.settings.get('show_open_files', False)
data = j.load({})
data['show_open_files'] = show_open_files
df = data.get('distraction_free', {})
df['show_open_files'] = show_open_files
data['distraction_free'] = df
j.save(data)
@dont_close_windows_when_empty
def close_project_by_window(self, window):
window.run_command('close_workspace')
def close_project_by_name(self, project):
pfile = os.path.realpath(self.project_file_name(project))
for w in sublime.windows():
if w.project_file_name():
if os.path.realpath(w.project_file_name()) == pfile:
self.close_project_by_window(w)
if w.id() != sublime.active_window().id():
w.run_command('close_window')
return True
return False
def add_project(self):
@dont_close_windows_when_empty
def close_all_files():
self.window.run_command('close_all')
def add_callback(project):
pd = self.window.project_data()
f = os.path.join(self.primary_dir, '%s.sublime-project' % project)
if pd:
JsonFile(f).save(pd)
else:
JsonFile(f).save({})
JsonFile(re.sub('\.sublime-project$', '.sublime-workspace', f)).save({})
self.close_project_by_window(self.window)
self.window.run_command('close_project')
close_all_files()
# reload projects info
self.__init__(self.window)
self.switch_project(project)
def show_input_panel():
project = 'New Project'
pd = self.window.project_data()
pf = self.window.project_file_name()
try:
path = pd['folders'][0]['path']
if pf:
project = os.path.basename(expand_folder(path, pf))
else:
project = os.path.basename(path)
except:
pass
v = self.window.show_input_panel('Project name:',
project,
add_callback,
None,
None)
v.run_command('select_all')
sublime.set_timeout(show_input_panel, 100)
def import_sublime_project(self):
pfile = self.window.project_file_name()
if not pfile:
sublime.message_dialog('Project file not found!')
return
if self.which_project_dir(pfile):
sublime.message_dialog('This project was created by Project Manager!')
return
answer = sublime.ok_cancel_dialog('Import %s?' % os.path.basename(pfile))
if answer is True:
j = JsonFile(os.path.join(self.primary_dir, 'library.json'))
data = j.load([])
if pfile not in data:
data.append(pfile)
j.save(data)
def append_project(self, project):
self.update_recent(project)
pd = self.get_project_data(project)
paths = [expand_folder(f.get('path'), self.project_file_name(project))
for f in pd.get('folders')]
subl('-a', paths)
def switch_project(self, project):
self.update_recent(project)
self.check_project(project)
self.close_project_by_window(self.window)
self.close_project_by_name(project)
subl(self.project_file_name(project))
def open_in_new_window(self, project):
self.update_recent(project)
self.check_project(project)
self.close_project_by_name(project)
subl('-n', self.project_file_name(project))
def _remove_project(self, project):
answer = sublime.ok_cancel_dialog('Remove "%s" from Project Manager?' % project)
if answer is True:
pfile = self.project_file_name(project)
if self.which_project_dir(pfile):
self.close_project_by_name(project)
os.remove(self.project_file_name(project))
os.remove(self.project_workspace(project))
else:
for pdir in self.projects_path:
j = JsonFile(os.path.join(pdir, 'library.json'))
data = j.load([])
if pfile in data:
data.remove(pfile)
j.save(data)
sublime.status_message('Project "%s" is removed.' % project)
def remove_project(self, project):
sublime.set_timeout(lambda: self._remove_project(project), 100)
def clean_dead_projects(self):
projects_to_remove = []
for pname, pi in self.projects_info.items():
folder = pi['folder']
if not os.path.exists(folder):
projects_to_remove.append(pname)
def remove_projects_iteratively():
pname = projects_to_remove[0]
self._remove_project(pname)
projects_to_remove.remove(pname)
if len(projects_to_remove) > 0:
sublime.set_timeout(remove_projects_iteratively, 100)
if len(projects_to_remove) > 0:
sublime.set_timeout(remove_projects_iteratively, 100)
else:
sublime.message_dialog('No Dead Projects.')
def edit_project(self, project):
def on_open():
self.window.open_file(self.project_file_name(project))
sublime.set_timeout_async(on_open, 100)
def rename_project(self, project):
def rename_callback(new_project):
if project == new_project:
return
pfile = self.project_file_name(project)
wsfile = self.project_workspace(project)
pdir = self.which_project_dir(pfile)
if not pdir:
pdir = os.path.dirname(pfile)
new_pfile = os.path.join(pdir, '%s.sublime-project' % new_project)
new_wsfile = re.sub('\.sublime-project$', '.sublime-workspace', new_pfile)
reopen = self.close_project_by_name(project)
os.rename(pfile, new_pfile)
os.rename(wsfile, new_wsfile)
j = JsonFile(new_wsfile)
data = j.load({})
if 'project' in data:
data['project'] = '%s.sublime-project' % os.path.basename(new_project)
j.save(data)
if not self.which_project_dir(pfile):
for pdir in self.projects_path:
library = os.path.join(pdir, 'library.json')
if os.path.exists(library):
j = JsonFile(library)
data = j.load([])
if pfile in data:
data.remove(pfile)
data.append(new_pfile)
j.save(data)
if reopen:
# reload projects info
self.__init__(self.window)
self.open_in_new_window(new_project)
def show_input_panel():
v = self.window.show_input_panel('New project name:',
project,
rename_callback,
None,
None)
v.run_command('select_all')
sublime.set_timeout(show_input_panel, 100)
def cancellable(func):
def _ret(self, action):
if action >= 0:
func(self, action)
elif action < 0 and self.caller == 'manager':
sublime.set_timeout(self.run, 10)
return _ret
class ProjectManagerCloseWindow(sublime_plugin.WindowCommand):
def run(self):
if self.window.project_file_name():
# if it is a project, close the project
self.window.run_command('close_workspace')
else:
self.window.run_command('close_all')
# exit if there are dirty views
for v in self.window.views():
if v.is_dirty():
return
# close the sidebar
self.window.run_command('close_project')
# close the window
self.window.run_command('close_window')
class ProjectManager(sublime_plugin.WindowCommand):
def show_quick_panel(self, items, on_done):
sublime.set_timeout(
lambda: self.window.show_quick_panel(items, on_done),
10)
def run(self, action=None, caller=None):
self.manager = Manager(self.window)
if action is None:
self.show_options()
elif action == 'add_project':
self.manager.add_project()
elif action == 'import_sublime_project':
self.manager.import_sublime_project()
elif action == 'clear_recent_projects':
self.manager.clear_recent_projects()
elif action == 'remove_dead_projects':
self.manager.clean_dead_projects()
else:
self.caller = caller
callback = eval('self.on_' + action)
self.projects, display = self.manager.display_projects()
if not self.projects:
sublime.message_dialog('Project list is empty.')
return
self.show_quick_panel(display, callback)
def show_options(self):
items = [
['Open Project', 'Open project in the current window'],
['Open Project in New Window', 'Open project in a new window'],
['Append Project', 'Append project to current window'],
['Edit Project', 'Edit project settings'],
['Rename Project', 'Rename project'],
['Remove Project', 'Remove from Project Manager'],
['Add New Project', 'Add current folders to Project Manager'],
['Import Project', 'Import current .sublime-project file'],
['Clear Recent Projects', 'Clear Recent Projects'],
['Remove Dead Projects', 'Remove Dead Projects']
]
def callback(a):
if a < 0:
return
elif a <= 5:
actions = ['switch', 'new', 'append', 'edit', 'rename', 'remove']
self.run(action=actions[a], caller='manager')
elif a == 6:
self.run(action='add_project')
elif a == 7:
self.run(action='import_sublime_project')
elif a == 8:
self.run(action='clear_recent_projects')
elif a == 9:
self.run(action='remove_dead_projects')
self.show_quick_panel(items, callback)
@cancellable
def on_new(self, action):
self.manager.open_in_new_window(self.projects[action])
@cancellable
def on_switch(self, action):
self.manager.switch_project(self.projects[action])
@cancellable
def on_append(self, action):
self.manager.append_project(self.projects[action])
@cancellable
def on_remove(self, action):
self.manager.remove_project(self.projects[action])
@cancellable
def on_edit(self, action):
self.manager.edit_project(self.projects[action])
@cancellable
def on_rename(self, action):
self.manager.rename_project(self.projects[action])

4
src/__init__.py

@ -1,4 +0,0 @@
__pkg_name__ = 'ProjectManager'
from .text_commands import *
from .window_commands import *

397
src/project_manager.py

@ -1,397 +0,0 @@
import sublime
import sublime_plugin
import subprocess
import os
import platform
import re
from .json_file import JsonFile
def subl(*args):
# learnt from SideBarEnhancements
executable_path = sublime.executable_path()
if sublime.platform() == 'osx':
app_path = executable_path[:executable_path.rfind('.app/') + 5]
executable_path = app_path + 'Contents/SharedSupport/bin/subl'
subprocess.Popen([executable_path] + list(args))
def on_activated():
window = sublime.active_window()
view = window.active_view()
if sublime.platform() == 'windows':
# fix focus on windows
window.run_command('focus_neighboring_group')
window.focus_view(view)
sublime_plugin.on_activated(view.id())
sublime_plugin.on_activated_async(view.id())
sublime.set_timeout(on_activated, 300)
def expand_folder(folder, project_file):
root = os.path.dirname(project_file)
if not os.path.isabs(folder):
folder = os.path.abspath(os.path.join(root, folder))
return folder
def get_node():
if sublime.platform() == 'osx':
node = subprocess.check_output(['scutil', '--get', 'ComputerName']).decode().strip()
else:
node = platform.node().split('.')[0]
return node
def dont_close_windows_when_empty(func):
def f(*args, **kwargs):
s = sublime.load_settings('Preferences.sublime-settings')
close_windows_when_empty = s.get('close_windows_when_empty')
s.set('close_windows_when_empty', False)
func(*args, **kwargs)
if close_windows_when_empty:
s.set('close_windows_when_empty', close_windows_when_empty)
return f
class Manager:
def __init__(self, window):
self.window = window
s = 'project_manager.sublime-settings'
self.settings = sublime.load_settings(s)
default_projects_dir = os.path.join(sublime.packages_path(),
'User',
'Projects')
self.projects_path = self.settings.get(
'projects_path', [self.settings.get('projects_dir', default_projects_dir)])
self.projects_path = [
os.path.normpath(os.path.expanduser(d)) for d in self.projects_path]
node = get_node()
if self.settings.get('use_local_projects_dir', False):
self.projects_path = \
[d + ' - ' + node for d in self.projects_path] + self.projects_path
self.primary_dir = self.projects_path[0]
self.projects_info = self.get_all_projects_info()
def list_project_files(self, folder):
pfiles = []
library = os.path.join(folder, 'library.json')
if os.path.exists(library):
j = JsonFile(library)
for f in j.load([]):
if os.path.exists(f) and f not in pfiles:
pfiles.append(os.path.normpath(f))
pfiles.sort()
j.save(pfiles)
for path, dirs, files in os.walk(folder, followlinks=True):
for f in files:
f = os.path.join(path, f)
if f.endswith('.sublime-project') and f not in pfiles:
pfiles.append(os.path.normpath(f))
# remove empty directories
for d in dirs:
d = os.path.join(path, d)
if len(os.listdir(d)) == 0:
os.rmdir(d)
return pfiles
def get_info_from_project_file(self, pfile):
pdir = self.which_project_dir(pfile)
if pdir:
pname = re.sub('\.sublime-project$',
'',
os.path.relpath(pfile, pdir))
else:
pname = re.sub('\.sublime-project$',
'',
os.path.basename(pfile))
pd = JsonFile(pfile).load()
if pd and 'folders' in pd and pd['folders']:
folder = pd['folders'][0].get('path', '')
else:
folder = ''
star = False
for w in sublime.windows():
if w.project_file_name() == pfile:
star = True
break
return {
pname: {
'folder': expand_folder(folder, pfile),
'file': pfile,
'star': star
}
}
def get_all_projects_info(self):
ret = {}
for pdir in self.projects_path:
pfiles = self.list_project_files(pdir)
for f in pfiles:
ret.update(self.get_info_from_project_file(f))
return ret
def which_project_dir(self, pfile):
for pdir in self.projects_path:
if (os.path.realpath(os.path.dirname(pfile))+os.path.sep).startswith(
os.path.realpath(pdir)+os.path.sep):
return pdir
return None
def display_projects(self):
plist = [[key, key + '*' if value['star'] else key, value['folder'], value['file']]
for key, value in self.projects_info.items()]
plist = sorted(plist)
if self.settings.get('show_recent_projects_first', True):
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
recent = j.load([])
plist = sorted(plist,
key=lambda p: recent.index(p[3]) if p[3] in recent else -1,
reverse=True)
count = 0
for i in range(len(plist)):
if plist[i][0] is not plist[i][1]:
plist.insert(count, plist.pop(i))
count = count + 1
return [item[0] for item in plist], [[item[1], item[2]] for item in plist]
def project_file_name(self, project):
return self.projects_info[project]['file']
def project_workspace(self, project):
return re.sub('\.sublime-project$',
'.sublime-workspace',
self.project_file_name(project))
def update_recent(self, project):
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
recent = j.load([])
pname = self.project_file_name(project)
if pname not in recent:
recent.append(pname)
else:
recent.append(recent.pop(recent.index(pname)))
# only keep the most recent 50 records
if len(recent) > 50:
recent = recent[(50-len(recent)):len(recent)]
j.save(recent)
def clear_recent_projects(self):
def clear_callback():
answer = sublime.ok_cancel_dialog('Clear Recent Projects?')
if answer is True:
j = JsonFile(os.path.join(self.primary_dir, 'recent.json'))
j.remove()
self.window.run_command("clear_recent_projects_and_workspaces")
sublime.set_timeout(clear_callback, 100)
def get_project_data(self, project):
return JsonFile(self.project_file_name(project)).load()
def check_project(self, project):
wsfile = self.project_workspace(project)
j = JsonFile(wsfile)
if not os.path.exists(wsfile):
j.save({})
elif self.settings.has('show_open_files'):
show_open_files = self.settings.get('show_open_files', False)
data = j.load({})
data['show_open_files'] = show_open_files
df = data.get('distraction_free', {})
df['show_open_files'] = show_open_files
data['distraction_free'] = df
j.save(data)
@dont_close_windows_when_empty
def close_project_by_window(self, window):
window.run_command('close_workspace')
def close_project_by_name(self, project):
pfile = os.path.realpath(self.project_file_name(project))
for w in sublime.windows():
if w.project_file_name():
if os.path.realpath(w.project_file_name()) == pfile:
self.close_project_by_window(w)
if w.id() != sublime.active_window().id():
w.run_command('close_window')
return True
return False
def add_project(self):
@dont_close_windows_when_empty
def close_all_files():
self.window.run_command('close_all')
def add_callback(project):
pd = self.window.project_data()
f = os.path.join(self.primary_dir, '%s.sublime-project' % project)
if pd:
JsonFile(f).save(pd)
else:
JsonFile(f).save({})
JsonFile(re.sub('\.sublime-project$', '.sublime-workspace', f)).save({})
self.close_project_by_window(self.window)
self.window.run_command('close_project')
close_all_files()
# reload projects info
self.__init__(self.window)
self.switch_project(project)
def show_input_panel():
project = 'New Project'
pd = self.window.project_data()
pf = self.window.project_file_name()
try:
path = pd['folders'][0]['path']
if pf:
project = os.path.basename(expand_folder(path, pf))
else:
project = os.path.basename(path)
except:
pass
v = self.window.show_input_panel('Project name:',
project,
add_callback,
None,
None)
v.run_command('select_all')
sublime.set_timeout(show_input_panel, 100)
def import_sublime_project(self):
pfile = self.window.project_file_name()
if not pfile:
sublime.message_dialog('Project file not found!')
return
if self.which_project_dir(pfile):
sublime.message_dialog('This project was created by Project Manager!')
return
answer = sublime.ok_cancel_dialog('Import %s?' % os.path.basename(pfile))
if answer is True:
j = JsonFile(os.path.join(self.primary_dir, 'library.json'))
data = j.load([])
if pfile not in data:
data.append(pfile)
j.save(data)
def append_project(self, project):
self.update_recent(project)
pd = self.get_project_data(project)
paths = [expand_folder(f.get('path'), self.project_file_name(project))
for f in pd.get('folders')]
subl('-a', paths)
def switch_project(self, project):
self.update_recent(project)
self.check_project(project)
self.close_project_by_window(self.window)
self.close_project_by_name(project)
subl(self.project_file_name(project))
def open_in_new_window(self, project):
self.update_recent(project)
self.check_project(project)
self.close_project_by_name(project)
subl('-n', self.project_file_name(project))
def _remove_project(self, project):
answer = sublime.ok_cancel_dialog('Remove "%s" from Project Manager?' % project)
if answer is True:
pfile = self.project_file_name(project)
if self.which_project_dir(pfile):
self.close_project_by_name(project)
os.remove(self.project_file_name(project))
os.remove(self.project_workspace(project))
else:
for pdir in self.projects_path:
j = JsonFile(os.path.join(pdir, 'library.json'))
data = j.load([])
if pfile in data:
data.remove(pfile)
j.save(data)
sublime.status_message('Project "%s" is removed.' % project)
def remove_project(self, project):
sublime.set_timeout(lambda: self._remove_project(project), 100)
def clean_dead_projects(self):
projects_to_remove = []
for pname, pi in self.projects_info.items():
folder = pi['folder']
if not os.path.exists(folder):
projects_to_remove.append(pname)
def remove_projects_iteratively():
pname = projects_to_remove[0]
self._remove_project(pname)
projects_to_remove.remove(pname)
if len(projects_to_remove) > 0:
sublime.set_timeout(remove_projects_iteratively, 100)
if len(projects_to_remove) > 0:
sublime.set_timeout(remove_projects_iteratively, 100)
else:
sublime.message_dialog('No Dead Projects.')
def edit_project(self, project):
def on_open():
self.window.open_file(self.project_file_name(project))
sublime.set_timeout_async(on_open, 100)
def rename_project(self, project):
def rename_callback(new_project):
if project == new_project:
return
pfile = self.project_file_name(project)
wsfile = self.project_workspace(project)
pdir = self.which_project_dir(pfile)
if not pdir:
pdir = os.path.dirname(pfile)
new_pfile = os.path.join(pdir, '%s.sublime-project' % new_project)
new_wsfile = re.sub('\.sublime-project$', '.sublime-workspace', new_pfile)
reopen = self.close_project_by_name(project)
os.rename(pfile, new_pfile)
os.rename(wsfile, new_wsfile)
j = JsonFile(new_wsfile)
data = j.load({})
if 'project' in data:
data['project'] = '%s.sublime-project' % os.path.basename(new_project)
j.save(data)
if not self.which_project_dir(pfile):
for pdir in self.projects_path:
library = os.path.join(pdir, 'library.json')
if os.path.exists(library):
j = JsonFile(library)
data = j.load([])
if pfile in data:
data.remove(pfile)
data.append(new_pfile)
j.save(data)
if reopen:
# reload projects info
self.__init__(self.window)
self.open_in_new_window(new_project)
def show_input_panel():
v = self.window.show_input_panel('New project name:',
project,
rename_callback,
None,
None)
v.run_command('select_all')
sublime.set_timeout(show_input_panel, 100)

28
src/text_commands.py

@ -1,28 +0,0 @@
import sublime
import sublime_plugin
from . import __pkg_name__
class PmReadmeCommand(sublime_plugin.TextCommand):
def run(self, edit):
v = self.view.window().new_file()
v.set_name(__pkg_name__ + ': Readme')
v.settings().set('gutter', False)
v.insert(edit, 0, sublime.load_resource('Packages/' + __pkg_name__ + '/README.md'))
v.set_syntax_file('Packages/Markdown/Markdown.sublime-syntax')
v.set_read_only(True)
v.set_scratch(True)
class PmChangelogCommand(sublime_plugin.TextCommand):
def run(self, edit):
v = self.view.window().new_file()
v.set_name(__pkg_name__ + ': Changelog')
v.settings().set('gutter', False)
v.insert(edit, 0, sublime.load_resource('Packages/' + __pkg_name__ + '/CHANGELOG.md'))
v.set_syntax_file('Packages/Markdown/Markdown.sublime-syntax')
v.set_read_only(True)
v.set_scratch(True)

114
src/window_commands.py

@ -1,114 +0,0 @@
import sublime
import sublime_plugin
from .project_manager import Manager
def cancellable(func):
def _ret(self, action):
if action >= 0:
func(self, action)
elif action < 0 and self.caller == 'manager':
sublime.set_timeout(self.run, 10)
return _ret
class ProjectManagerCloseWindow(sublime_plugin.WindowCommand):
def run(self):
if self.window.project_file_name():
# if it is a project, close the project
self.window.run_command('close_workspace')
else:
self.window.run_command('close_all')
# exit if there are dirty views
for v in self.window.views():
if v.is_dirty():
return
# close the sidebar
self.window.run_command('close_project')
# close the window
self.window.run_command('close_window')
class ProjectManager(sublime_plugin.WindowCommand):
def show_quick_panel(self, items, on_done):
sublime.set_timeout(
lambda: self.window.show_quick_panel(items, on_done),
10)
def run(self, action=None, caller=None):
self.manager = Manager(self.window)
if action is None:
self.show_options()
elif action == 'add_project':
self.manager.add_project()
elif action == 'import_sublime_project':
self.manager.import_sublime_project()
elif action == 'clear_recent_projects':
self.manager.clear_recent_projects()
elif action == 'remove_dead_projects':
self.manager.clean_dead_projects()
else:
self.caller = caller
callback = eval('self.on_' + action)
self.projects, display = self.manager.display_projects()
if not self.projects:
sublime.message_dialog('Project list is empty.')
return
self.show_quick_panel(display, callback)
def show_options(self):
items = [
['Open Project', 'Open project in the current window'],
['Open Project in New Window', 'Open project in a new window'],
['Append Project', 'Append project to current window'],
['Edit Project', 'Edit project settings'],
['Rename Project', 'Rename project'],
['Remove Project', 'Remove from Project Manager'],
['Add New Project', 'Add current folders to Project Manager'],
['Import Project', 'Import current .sublime-project file'],
['Clear Recent Projects', 'Clear Recent Projects'],
['Remove Dead Projects', 'Remove Dead Projects']
]
def callback(a):
if a < 0:
return
elif a <= 5:
actions = ['switch', 'new', 'append', 'edit', 'rename', 'remove']
self.run(action=actions[a], caller='manager')
elif a == 6:
self.run(action='add_project')
elif a == 7:
self.run(action='import_sublime_project')
elif a == 8:
self.run(action='clear_recent_projects')
elif a == 9:
self.run(action='remove_dead_projects')
self.show_quick_panel(items, callback)
@cancellable
def on_new(self, action):
self.manager.open_in_new_window(self.projects[action])
@cancellable
def on_switch(self, action):
self.manager.switch_project(self.projects[action])
@cancellable
def on_append(self, action):
self.manager.append_project(self.projects[action])
@cancellable
def on_remove(self, action):
self.manager.remove_project(self.projects[action])
@cancellable
def on_edit(self, action):
self.manager.edit_project(self.projects[action])
@cancellable
def on_rename(self, action):
self.manager.rename_project(self.projects[action])

0
keybinds/Default (Linux).sublime-keymap → support/Default (Linux).sublime-keymap

0
keybinds/Default (OSX).sublime-keymap → support/Default (OSX).sublime-keymap

0
keybinds/Default (Windows).sublime-keymap → support/Default (Windows).sublime-keymap

4
commands/Default.sublime-commands → support/Default.sublime-commands

@ -56,7 +56,7 @@
"command": "edit_settings",
"args":
{
"base_file": "${packages}/ProjectManager/settings/project_manager.sublime-settings",
"base_file": "${packages}/ProjectManager/support/project_manager.sublime-settings",
"default": "{\n\t$0\n}\n"
}
},
@ -65,7 +65,7 @@
"command": "edit_settings",
"args":
{
"base_file": "${packages}/ProjectManager/keybinds/Default (${platform}).sublime-keymap",
"base_file": "${packages}/ProjectManager/support/Default (${platform}).sublime-keymap",
"default": "[\n\t$0\n]\n"
}
}

19
menus/Main.sublime-menu → support/Main.sublime-menu

@ -70,27 +70,12 @@
"caption": "Project Manager",
"children":
[
{
"caption": "Documentation",
"children":
[
{
"caption": "Readme",
"command": "pm_readme"
},
{
"caption": "Changelog",
"command": "pm_changelog"
}
]
},
{ "caption": "-" },
{
"caption": "Settings",
"command": "edit_settings",
"args":
{
"base_file": "${packages}/ProjectManager/settings/project_manager.sublime-settings",
"base_file": "${packages}/ProjectManager/support/project_manager.sublime-settings",
"default": "{\n\t$0\n}\n"
}
},
@ -99,7 +84,7 @@
"command": "edit_settings",
"args":
{
"base_file": "${packages}/ProjectManager/input-maps/Default (${platform}).sublime-keymap",
"base_file": "${packages}/ProjectManager/support/Default (${platform}).sublime-keymap",
"default": "[\n\t$0\n]\n"
}
}

0
settings/project_manager.sublime-settings → support/project_manager.sublime-settings

Loading…
Cancel
Save