def find_git_working_directory(self): '''Return the git working directory.''' path = g.os_path_abspath('.') while path: if g.os_path_exists(g.os_path_finalize_join(path, '.git')): return path path = g.os_path_finalize_join(path, '..') return None
def get_icon_fn(self, fn): '''Resolve fn relative to the Icons directory.''' dir_ = g.os_path_finalize_join(g.app.loadDir, '..', 'Icons') path = g.os_path_finalize_join(dir_, fn) if g.os_path_exists(path): return path else: g.trace('does not exist: %s' % (path)) return None
def find_git_working_directory(self, directory): '''Return the git working directory, starting at directory.''' assert directory while directory: if g.os_path_exists(g.os_path_finalize_join(directory, '.git')): return directory path2 = g.os_path_finalize_join(directory, '..') if path2 == directory: break directory = path2 return None
def get_rc_file(self): '''Return the path to the pylint configuration file.''' base = 'pylint-leo-rc.txt' table = ( g.os_path_finalize_join(g.app.homeDir, '.leo', base), # In ~/.leo g.os_path_finalize_join(g.app.loadDir, '..', '..', 'leo', 'test', base), # In leo/test ) for fn in table: fn = g.os_path_abspath(fn) if g.os_path_exists(fn): return fn g.es_print('no pylint configuration file found in\n%s' % ( '\n'.join(table))) return None
def listenToLog(self, event=None): ''' A socket listener, listening on localhost. See: https://docs.python.org/2/howto/logging-cookbook.html#sending-and-receiving-logging-events-across-a-network Start this listener first, then start the broadcaster. leo/plugins/cursesGui2.py is a typical broadcaster. ''' # Kill any previous listener. if g.app.log_listener: g.es_print('Killing previous listener') try: g.app.log_listener.kill() except Exception: g.es_exception() g.app.log_listener = None # Start a new listener. g.es_print('Starting log_listener.py') path = g.os_path_finalize_join(g.app.loadDir, '..', 'external', 'log_listener.py') g.app.log_listener = subprocess.Popen( [sys.executable, path], shell=False, universal_newlines=True, )
def getPluginsList(): '''Return a list of all important plugins.''' aList = [] # g.app.loadDir does not exist: use '.' instead. for theDir in ('','importers','writers'): pattern = g.os_path_finalize_join('.','leo','plugins',theDir,'*.py') for fn in glob.glob(pattern): sfn = g.shortFileName(fn) if sfn != '__init__.py': sfn = os.sep.join([theDir,sfn]) if theDir else sfn aList.append(sfn) remove = [ 'free_layout.py', # Gui-related. 'gtkDialogs.py', # Many errors, not important. 'leofts.py', # Not (yet) in leoPlugins.leo. 'nested_splitter.py', # Gui-related. 'qtGui.py', # Dummy file 'qt_main.py', # Created automatically. ] aList = sorted([z for z in aList if z not in remove]) # Remove all gui related items. for z in sorted(aList): if z.startswith('qt_'): aList.remove(z) # g.trace('\n'.join(aList)) return aList
def getPluginsList(): """Return a list of all important plugins.""" aList = [] # g.app.loadDir does not exist: use '.' instead. for theDir in ("", "importers", "writers"): pattern = g.os_path_finalize_join(".", "leo", "plugins", theDir, "*.py") for fn in glob.glob(pattern): sfn = g.shortFileName(fn) if sfn != "__init__.py": sfn = os.sep.join([theDir, sfn]) if theDir else sfn aList.append(sfn) remove = [ "free_layout.py", # Gui-related. "gtkDialogs.py", # Many errors, not important. "leofts.py", # Not (yet) in leoPlugins.leo. "nested_splitter.py", # Gui-related. "qtGui.py", # Dummy file "qt_main.py", # Created automatically. ] aList = sorted([z for z in aList if z not in remove]) # Remove all gui related items. for z in sorted(aList): if z.startswith("qt_"): aList.remove(z) # g.trace('\n'.join(aList)) return aList
def onIconDoubleClick(tag, keywords): """ Read or write a bibtex file when the node is double-clicked. Write the @bibtex tree as bibtex file when the root node is double-clicked. If it has no child nodes, read bibtex file. """ p = keywords.get("p") or keywords.get("v") c = keywords.get("c") if not c or not p: return h = p.h.strip() if g.match_word(h, 0, "@bibtex"): fn = g.os_path_finalize_join(g.os_path_dirname(c.fileName() or ""), h[8:]) if p.hasChildren(): bibFile = open(fn, "w") writeTreeAsBibTex(bibFile, p, c) bibFile.close() g.es("wrote: %s" % fn) else: try: bibFile = open(fn, "r") except IOError: g.es("not found: %s" % fn, color="red") return g.es("reading: " + fn) readBibTexFileIntoTree(bibFile, c) bibFile.close()
def getCommandList(): '''Return list of all command modules in leo/commands.''' pattern = g.os_path_finalize_join('.', 'leo', 'commands', '*.py') return sorted([ g.shortFileName(fn) for fn in glob.glob(pattern) if g.shortFileName(fn) != '__init__.py'])
def run(self): '''Run Pylint on all Python @<file> nodes in c.p's tree.''' c, root = self.c, self.c.p rc_fn = self.get_rc_file() if not rc_fn: return # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) # Run lint on all Python @<file> nodes in root's tree. t1 = time.time() found = False for p in root.self_and_subtree(): found |= self.check(p, rc_fn) # Look up the tree if no @<file> nodes were found. if not found: for p in root.parents(): if self.check(p, rc_fn): found = True break # If still not found, expand the search if root is a clone. if not found: isCloned = any([p.isCloned() for p in root.self_and_parents()]) # g.trace(isCloned,root.h) if isCloned: for p in c.all_positions(): if p.isAnyAtFileNode(): isAncestor = any([z.v == root.v for z in p.self_and_subtree()]) # g.trace(isAncestor,p.h) if isAncestor and self.check(p, rc_fn): break if self.wait: g.es_print('pylint done %s' % g.timeSince(t1))
def run(self, p=None, force=False, pyflakes_errors_only=False): '''Run Pyflakes on all Python @<file> nodes in c.p's tree.''' c = self.c root = p or c.p # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) t1 = time.time() roots = g.findRootsWithPredicate(c, root, predicate=None) if root: paths = [self.finalize(z) for z in roots] # These messages are important for clarity. log_flag = not force total_errors = self.check_all(log_flag, paths, pyflakes_errors_only, roots=roots) if total_errors > 0: g.es('ERROR: pyflakes: %s error%s' % ( total_errors, g.plural(total_errors))) elif force: g.es('OK: pyflakes: %s file%s in %s' % ( len(paths), g.plural(paths), g.timeSince(t1))) elif not pyflakes_errors_only: g.es('OK: pyflakes') ok = total_errors == 0 else: ok = True return ok
def run(self, p=None): '''Run flake8 on all Python @<file> nodes in c.p's tree.''' c = self.c root = p or c.p # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) # Run flake8 on all Python @<file> nodes in root's tree. t1 = time.time() found = False for p in root.self_and_subtree(): found |= self.find(p) # Look up the tree if no @<file> nodes were found. if not found: for p in root.parents(): if self.find(p): found = True break # If still not found, expand the search if root is a clone. if not found: isCloned = any([p.isCloned() for p in root.self_and_parents()]) # g.trace(isCloned,root.h) if isCloned: for p in c.all_positions(): if p.isAnyAtFileNode(): isAncestor = any([z.v == root.v for z in p.self_and_subtree()]) # g.trace(isAncestor,p.h) if isAncestor and self.find(p): break paths = list(set(self.seen)) if paths: self.check_all(paths) g.es_print('flake8: %s file%s in %s' % ( len(paths), g.plural(paths), g.timeSince(t1)))
def make_stub_file(self, p): '''Make a stub file in ~/stubs for the @<file> node at p.''' import ast import leo.core.leoAst as leoAst assert p.isAnyAtFileNode() c = self.c fn = p.anyAtFileNodeName() if not fn.endswith('.py'): g.es_print('not a python file', fn) return abs_fn = g.fullPath(c, p) if not g.os_path_exists(abs_fn): g.es_print('not found', abs_fn) return if g.os_path_exists(self.output_directory): base_fn = g.os_path_basename(fn) out_fn = g.os_path_finalize_join(self.output_directory, base_fn) else: g.es_print('not found', self.output_directory) return out_fn = out_fn[:-3] + '.pyi' out_fn = os.path.normpath(out_fn) self.output_fn = out_fn # compatibility with stand-alone script s = open(abs_fn).read() node = ast.parse(s,filename=fn,mode='exec') leoAst.StubTraverser(controller=self).run(node)
def get_fn (self,s,tag): pc = self c = pc.c fn = s or c.p.h[len(tag):] fn = fn.strip() # Similar to code in g.computeFileUrl if fn.startswith('~'): # Expand '~' and handle Leo expressions. fn = fn[1:] fn = g.os_path_expanduser(fn) fn = g.os_path_expandExpression(fn,c=c) fn = g.os_path_finalize(fn) else: # Handle Leo expressions. fn = g.os_path_expandExpression(fn,c=c) # Handle ancestor @path directives. if c and c.openDirectory: base = c.getNodePath(c.p) fn = g.os_path_finalize_join(c.openDirectory,base,fn) else: fn = g.os_path_finalize(fn) ok = g.os_path_exists(fn) return ok,fn
def files_in_dir(self, theDir, recursive=True, extList=None, excludeDirs=None): """ Return a list of all Python files in the directory. Include all descendants if recursiveFlag is True. Include all file types if extList is None. """ import glob import os # if extList is None: extList = ['.py'] if excludeDirs is None: excludeDirs = [] result = [] if recursive: for root, dirs, files in os.walk(theDir): for z in files: fn = g.os_path_finalize_join(root, z) junk, ext = g.os_path_splitext(fn) if not extList or ext in extList: result.append(fn) if excludeDirs and dirs: for z in dirs: if z in excludeDirs: dirs.remove(z) else: for ext in extList: result.extend(glob.glob("%s.*%s" % (theDir, ext))) return sorted(list(set(result)))
def getPluginsList(): '''Return a list of all important plugins.''' aList = [] # g.app.loadDir does not exist: use '.' instead. for theDir in ('importers','writers'): pattern = g.os_path_finalize_join('.','leo','plugins',theDir,'*.py') for fn in glob.glob(pattern): sfn = g.shortFileName(fn) if sfn != '__init__.py': aList.append(os.sep.join([theDir,sfn])) aList.extend([ 'baseNativeTree', 'bookmarks', 'contextmenu', 'leoOPML', 'lineNumbers', # 'mod_http', 'mod_scripting', 'nav_qt', 'quicksearch', 'todo', 'vim.py', 'viewrendered.py', 'xemacs.py', ]) return aList
def project_files(self, name, force_all=False): '''Return a list of all files in the named project.''' # Ignore everything after the first space. i = name.find(' ') if i > -1: name = name[: i].strip() leo_path, junk = g.os_path_split(__file__) d = { # Change these paths as required for your system. 'coverage': ( r'C:\Python26\Lib\site-packages\coverage-3.5b1-py2.6-win32.egg\coverage', ['.py'], ['.bzr', 'htmlfiles']), 'leo': ( r'C:\leo.repo\leo-editor\leo\core', ['.py'], ['.git']), # ['.bzr'] 'lib2to3': ( r'C:\Python26\Lib\lib2to3', ['.py'], ['tests']), 'pylint': ( r'C:\Python26\Lib\site-packages\pylint', ['.py'], ['.bzr', 'test']), 'rope': ( r'C:\Python26\Lib\site-packages\rope-0.9.4-py2.6.egg\rope\base', ['.py'], ['.bzr']), # 'test': ( # g.os_path_finalize_join(leo_path,'test-proj'), # ['.py'],['.bzr']), } data = d.get(name.lower()) if not data: g.trace('bad project name: %s' % (name)) return [] theDir, extList, excludeDirs = data files = self.files_in_dir(theDir, recursive=True, extList=extList, excludeDirs=excludeDirs) if files: if name.lower() == 'leo': for exclude in ['__init__.py', 'format-code.py']: files = [z for z in files if not z.endswith(exclude)] table = ( r'C:\leo.repo\leo-editor\leo\commands', # r'C:\leo.repo\leo-editor\leo\plugins\importers', # r'C:\leo.repo\leo-editor\leo\plugins\writers', ) for dir_ in table: files2 = self.files_in_dir(dir_, recursive=True, extList=['.py',], excludeDirs=[]) files2 = [z for z in files2 if not z.endswith('__init__.py')] # g.trace(g.os_path_exists(dir_), dir_, '\n'.join(files2)) files.extend(files2) files.extend(glob.glob(r'C:\leo.repo\leo-editor\leo\plugins\qt_*.py')) fn = g.os_path_finalize_join(theDir, '..', 'plugins', 'qtGui.py') if fn and g.os_path_exists(fn): files.append(fn) if g.app.runningAllUnitTests and len(files) > 1 and not force_all: return [files[0]] if not files: g.trace(theDir) if g.app.runningAllUnitTests and len(files) > 1 and not force_all: return [files[0]] else: return files
def __init__(self, c): """Ctor for EnchantClass class.""" self.c = c language = g.toUnicode(c.config.getString("enchant_language")) # Set the base language if language and not enchant.dict_exists(language): g.warning("Invalid language code for Enchant", repr(language)) g.es_print('Using "en_US" instead') language = "en_US" # Compute fn, the full path to the local dictionary. fn = c.config.getString("enchant_local_dictionary") if not fn: fn = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", "spellpyx.txt") # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join(g.app.homeDir, ".leo", "spellpyx.txt") self.open_dict(fn, language)
def find_user_dict(self): '''Return the full path to the local dictionary.''' c = self.c fn = c.config.getString('enchant_local_dictionary') if not fn: fn = g.os_path_finalize_join( g.app.loadDir, "..", "plugins", 'spellpyx.txt', ) # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join( g.app.homeDir, '.leo', 'spellpyx.txt') return fn
def completeFileName(self, fileName): g = self.g if not (fileName and fileName.strip()): return '' import os fileName = g.os_path_finalize_join(os.getcwd(), fileName) head, ext = g.os_path_splitext(fileName) if not ext: fileName = fileName + ".leo" return fileName
def openUnittest(self, event=None): '''Open unittest.leo.''' c = self fileName = g.os_path_finalize_join(g.app.loadDir, '..', 'test', 'unitTest.leo') if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', fileName)
def get_session_path (self): '''Return the path to the session file.''' for path in (g.app.homeLeoDir,g.app.homeDir): if g.os_path_exists(path): return g.os_path_finalize_join(path,'leo.session') return None
def __init__(self, c): """Ctor for EnchantClass class.""" # pylint: disable=super-init-not-called self.c = c language = g.toUnicode(c.config.getString('enchant_language')) # Set the base language if language and not enchant.dict_exists(language): g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') language = 'en_US' # Compute fn, the full path to the local dictionary. fn = c.config.getString('enchant_local_dictionary') if not fn: fn = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", 'spellpyx.txt') # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join(g.app.homeDir, '.leo', 'spellpyx.txt') self.open_dict(fn, language)
def openLeoDist(self, event=None): '''Open leoDist.leo in a new Leo window.''' c = self name = "leoDist.leo" fileName = g.os_path_finalize_join(g.app.loadDir, "..", "dist", name) if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es("not found:", name)
def getGuiPluginsList(): pattern = g.os_path_finalize_join(".", "leo", "plugins", "qt_*.py") aList = [g.shortFileName(fn) for fn in glob.glob(pattern) if g.shortFileName(fn) != "__init__.py"] aList.extend(["free_layout", "nested_splitter"]) if "qt_main.py" in aList: # Auto-generated file. aList.remove("qt_main.py") return sorted(aList)
def leoQuickStart(self, event=None): '''Open quickstart.leo in a new Leo window.''' c = self; name = "quickstart.leo" fileName = g.os_path_finalize_join(g.app.loadDir, "..", "doc", name) # Bug fix: 2012/04/09: only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es("not found:", name)
def openLeoScripts(self, event=None): '''Open scripts.leo.''' c = self fileName = g.os_path_finalize_join(g.app.loadDir, '..', 'scripts', 'scripts.leo') # Bug fix: 2012/04/09: only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', fileName)
def main(): '''External entry point for Leo's beautifier.''' t1 = time.time() base = g.os_path_abspath(os.curdir) files, options = scan_options() for path in files: path = g.os_path_finalize_join(base, path) beautify(options, path) print('beautified %s files in %4.2f sec.' % (len(files), time.time() - t1))
def md_write_files(event): '''writes all md nodes. A md node is node whose headline starts with 'md:' followed by file name.''' c = event.get('c') #@+others #@+node:vitalije.20180804180150.1: *3* hl def hl(v, lev): return '#' * (lev + 1) + ' ' + v.h + '\n' #@+node:vitalije.20180804180104.1: *3* mdlines def mdlines(v, lev=0): if lev > 0 and not v.b.startswith('#'): yield hl(v, lev) yield '' for line in v.b.splitlines(False): m = pat.match(line) if m: v1 = c.fileCommands.gnxDict.get(m.group(2)) if not v1: g.es('gnx not found:[%s]'%m.group(2)) else: for x in v1.b.splitlines(False): yield m.group(1) + x continue yield line yield '' for v1 in v.children: for line in mdlines(v1, lev + 1): yield line yield '' #@+node:vitalije.20180804180749.1: *3* process def process(v, fname): with open(fname, 'w', encoding='utf-8') as out: out.write('\n'.join(mdlines(v, 0))) g.es(fname, 'ok') #@-others seen = set() p = c.rootPosition() while p: v = p.v if v.gnx in seen: p.moveToNodeAfterTree() else: seen.add(v.gnx) if v.isAtIgnoreNode(): p.moveToNodeAfterTree() continue h = v.h if h.startswith('md:'): pth = c.getNodePath(p) fname = g.os_path_finalize_join(pth, h[3:].strip()) if not fname.endswith('.md'): fname = fname + '.md' process(v, fname) p.moveToNodeAfterTree() else: p.moveToThreadNext()
def find_main_dict(self): '''Return the full path to the global dictionary.''' c = self.c fn = c.config.getString('main_spelling_dictionary') if fn and g.os_path_exists(fn): return fn # Default to ~/.leo/main_spelling_dict.txt fn = g.os_path_finalize_join( g.app.homeDir, '.leo', 'main_spelling_dict.txt') return fn if g.os_path_exists(fn) else None
def leoQuickStart(self, event=None): """Open quickstart.leo in a new Leo window.""" c = self name = "quickstart.leo" fileName = g.os_path_finalize_join(g.app.loadDir, "..", "doc", name) # Bug fix: 2012/04/09: only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es("not found:", name)
def openLeoScripts(self, event=None): """Open scripts.leo.""" c = self fileName = g.os_path_finalize_join(g.app.loadDir, '..', 'scripts', 'scripts.leo') # Bug fix: 2012/04/09: only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', fileName)
def regularizeName(self, fn): """Return the name used as a key to this modules dictionaries.""" if not fn.endswith('.py'): return fn # # Allow .leo/plugins path = g.os_path_finalize_join('~', '.leo', 'plugins', fn) if g.os_path_exists(path): return fn[: -3] # Return the default module for leo plugins. return "leo.plugins." + fn[: -3]
def openDesktopIntegration(self, event=None): """Open Desktop-integration.leo.""" c = self fileName = g.os_path_finalize_join(g.app.loadDir, '..', 'scripts', 'desktop-integration.leo') # only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', fileName)
def getCoreList(): pattern = g.os_path_finalize_join('.', 'leo', 'core', 'leo*.py') # pattern = g.os_path_finalize_join('leo','core','leo*.py') aList = [ g.shortFileName(fn) for fn in glob.glob(pattern) if g.shortFileName(fn) != '__init__.py' ] aList.extend([ 'runLeo.py', ]) return sorted(aList)
def openLeoPlugins(self, event=None): '''Open leoPlugins.leo in a new Leo window.''' c = self names = ('leoPlugins.leo', 'leoPluginsRef.leo',) # Used in error message. for name in names: fileName = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", name) # Bug fix: 2012/04/09: only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', ', '.join(names))
def compute_opath(self, i_path): """ Neither asciidoctor nor pandoc handles extra extentions well. """ c = self.c for i in range(3): i_path, ext = os.path.splitext(i_path) if not ext: break # #1373. base_dir = os.path.dirname(c.fileName()) return g.os_path_finalize_join(base_dir, i_path + '.html')
def open_theme_file(self, event): '''Open a theme file and apply the theme.''' c = event and event.get('c') if not c: return themes_dir = g.os_path_finalize_join(g.app.loadDir, '..', 'themes') fn = g.app.gui.runOpenFileDialog(c, title="Open Theme File", filetypes=[ g.fileFilters("LEOFILES"), ("All files", "*"), ], defaultextension=g.defaultLeoFileExtension(c), startpath=themes_dir, ) if not fn: return leo_dir = g.os_path_finalize_join(g.app.loadDir, '..', '..') os.chdir(leo_dir) command = 'python launchLeo.py "%s"' % fn os.system(command) os.chdir(leo_dir)
def openCheatSheet(self, event=None): """Open leo/doc/cheatSheet.leo""" c = self fn = g.os_path_finalize_join(g.app.loadDir, '..', 'doc', 'CheatSheet.leo') if not g.os_path_exists(fn): g.es(f"file not found: {fn}") return c2 = g.openWithFileName(fn, old_c=c) p = g.findNodeAnywhere(c2, "Leo's cheat sheet") if p: c2.selectPosition(p) p.expand() c2.redraw()
def completeFileName (self,fileName): g = self.g if not (fileName and fileName.strip()): return '' import os fileName = g.os_path_finalize_join(os.getcwd(),fileName) head,ext = g.os_path_splitext(fileName) if not ext: fileName = fileName + ".leo" return fileName
def run(self): '''Run Pylint on all Python @<file> nodes in c.p's tree.''' c, root = self.c, self.c.p rc_fn = self.get_rc_file() if not rc_fn: return # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) roots = g.findRootsWithPredicate(c, root, predicate=None) for p in roots: self.check(p, rc_fn)
def show(self): """ Convert the outline to xhtml and display the results in a browser. If browser_command is set, this command will be used to launch the browser. If it is not set, or if the command fails, the default browser will be used. Setting browser_command to a bad command will slow down browser launch. """ tempdir = g.os_path_finalize_join(tempfile.gettempdir(), 'leo_show') if not g.os_path_exists(tempdir): os.mkdir(tempdir) filename = g.sanitize_filename(self.myFileName) filepath = g.os_path_finalize_join(tempdir, filename + '.html') self.write(filepath, self.xhtml, basedir='', path='') url = "file://%s" % filepath msg = '' if self.browser_command: g.trace(self.browser_command) try: subprocess.Popen([self.browser_command, url]) return True except Exception: msg = 'can\'t open browser using \n %s\n'%self.browser_command + \ 'Using default browser instead.' if msg: self.announce_fail(msg) webbrowser.open(url)
def getGuiPluginsList(): pattern = g.os_path_finalize_join('.', 'leo', 'plugins', 'qt_*.py') aList = [ g.shortFileName(fn) for fn in glob.glob(pattern) if g.shortFileName(fn) != '__init__.py' ] aList.extend([ 'free_layout', 'nested_splitter', ]) if 'qt_main.py' in aList: # Auto-generated file. aList.remove('qt_main.py') return sorted(aList)
def openLeoPy(self, event=None): """Open leoPy.leo in a new Leo window.""" c = self names = ( 'leoPy.leo', 'LeoPyRef.leo', ) # Used in error message. for name in names: fileName = g.os_path_finalize_join(g.app.loadDir, "..", "core", name) # Only call g.openWithFileName if the file exists. if g.os_path_exists(fileName): c2 = g.openWithFileName(fileName, old_c=c) if c2: return g.es('not found:', ', '.join(names))
def jinja_act_on_node(c, p, event): h = p.h #print "try act" if not h.startswith('@jinja '): raise leoPlugins.TryNext #print "act" tail = h[7:].strip() pth = c.getNodePath(p) fullpath = g.os_path_finalize_join(pth, tail) g.es("Rendering " + fullpath) body = untangle(c, p) jinja_render(body, fullpath, c.vs)
def run (self,event=None): fn = self.defaultOptionsDict.get('output-file-name','format-code.rst.txt') self.outputFileName = g.os_path_finalize_join(g.app.loadDir,fn) self.outputFile = StringIO() # Not a binary file. print('\n\n\n==========') self.writeTree(self.p.copy()) s = self.outputFile.getvalue() self.outputFile = open(self.outputFileName,'w') self.outputFile.write(s) self.outputFile.close() g.es('rst-format: wrote',self.outputFileName)
def find(self, p): '''Return True and add p's path to self.seen if p is a Python @<file> node.''' c = self.c found = False if p.isAnyAtFileNode(): aList = g.get_directives_dict_list(p) path = c.scanAtPathDirectives(aList) fn = p.anyAtFileNodeName() if fn.endswith('.py'): fn = g.os_path_finalize_join(path, fn) if fn not in self.seen: self.seen.append(fn) found = True return found
def run(self, p): """Run mypy on all Python @<file> nodes in c.p's tree.""" c = self.c if not mypy: print('install mypy with `pip install mypy`') return root = p.copy() # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) roots = g.findRootsWithPredicate(c, root, predicate=None) g.printObj([z.h for z in roots], tag='mypy.run') self.check_all(roots)
def open_theme_file(self, event): """Open a theme file in a new session and apply the theme.""" c = event and event.get('c') if not c: return themes_dir = g.os_path_finalize_join(g.app.loadDir, '..', 'themes') fn = g.app.gui.runOpenFileDialog( c, title="Open Theme File", filetypes=[ ("Leo files", "*.leo *.db"), ("All files", "*"), ], defaultextension=g.defaultLeoFileExtension(c), startpath=themes_dir, ) if not fn: return leo_dir = g.os_path_finalize_join(g.app.loadDir, '..', '..') os.chdir(leo_dir) #--/start: Opening a theme file locks the initiating Leo session #1425 #command = f'python launchLeo.py "{fn}"' #os.system(command) # fix idea 1: command = f'{g.sys.executable} {g.app.loadDir}/runLeo.py "{fn}"' # # fix idea 2: # if g.sys.argv[0].endswith('.py'): # command = f'{g.sys.executable} {g.sys.argv[0]} "{fn}"' # else: # command = f'{g.sys.argv[0]} "{fn}"' # g.es_print(command) g.subprocess.Popen(command) # --/end os.chdir(leo_dir)
def diff_file(self, fn, directory=None, rev1='HEAD', rev2=''): """ Create an outline describing the git diffs for fn. """ # Common code. c = self.c if not self.set_directory(directory): return path = g.os_path_finalize_join(self.repo_dir, fn) # #1781: bug fix. if not os.path.exists(path): g.trace('NOT FOUND', path) return s1 = self.get_file_from_rev(rev1, fn) s2 = self.get_file_from_rev(rev2, fn) lines1 = g.splitLines(s1) lines2 = g.splitLines(s2) diff_list = list( difflib.unified_diff( lines1, lines2, rev1 or 'uncommitted', rev2 or 'uncommitted', )) diff_list.insert(0, '@ignore\n@nosearch\n@language patch\n') self.file_node = self.create_file_node(diff_list, fn) # #1777: The file node will contain the entire added/deleted file. if not s1: self.file_node.h = f"Added: {self.file_node.h}" return if not s2: self.file_node.h = f"Deleted: {self.file_node.h}" return # Finish. c1 = c2 = None if fn.endswith('.leo'): c1 = self.make_leo_outline(fn, path, s1, rev1) c2 = self.make_leo_outline(fn, path, s2, rev2) else: root = self.find_file(fn) if c.looksLikeDerivedFile(path): c1 = self.make_at_file_outline(fn, s1, rev1) c2 = self.make_at_file_outline(fn, s2, rev2) elif root: c1 = self.make_at_clean_outline(fn, root, s1, rev1) c2 = self.make_at_clean_outline(fn, root, s2, rev2) if c1 and c2: self.make_diff_outlines(c1, c2, fn, rev1, rev2) self.file_node.b = (f"{self.file_node.b.rstrip()}\n" f"@language {c2.target_language}\n")
def openCheatSheet(self, event=None, redraw=True): '''Open leo/doc/cheatSheet.leo''' c = self fn = g.os_path_finalize_join(g.app.loadDir, '..', 'doc', 'CheatSheet.leo') # g.es_debug(g.os_path_exists(fn),fn) if g.os_path_exists(fn): c2 = g.openWithFileName(fn, old_c=c) if redraw: p = g.findNodeAnywhere(c2, "Leo's cheat sheet") if p: c2.selectPosition(p) p.expand() c2.redraw() return c2 g.es('file not found: %s' % fn) return None
def runMainLoop(self, fileName=None): '''The main loop for the browser gui.''' # pylint: disable=arguments-differ if fileName: print('LeoWapp running: %s...' % g.shortFileName(fileName)) else: print('LeoWapp running...') if 0: # Run all unit tests. path = g.os_path_finalize_join(g.app.loadDir, '..', 'test', 'unittest.leo') c = g.openWithFileName(path, gui=self) c.findCommands.ftm = g.NullObject() # A hack. Maybe the NullGui should do this. c.debugCommands.runAllUnitTestsLocally() print('calling sys.exit(0)') sys.exit(0)
def check(self, p, rc_fn): '''Check a single node. Return True if it is a Python @<file> node.''' c = self.c found = False if p.isAnyAtFileNode(): # Fix bug: https://github.com/leo-editor/leo-editor/issues/67 aList = g.get_directives_dict_list(p) path = c.scanAtPathDirectives(aList) fn = p.anyAtFileNodeName() if fn.endswith('.py'): fn = g.os_path_finalize_join(path, fn) if p.v not in self.seen: self.seen.append(p.v) self.run_pylint(fn, rc_fn) found = True return found
def update_pyplot(self, s, keywords): '''Get the pyplot script at c.p.b and show it.''' c = self.c # To do: show plot in the VR area. if not self.pyplot_imported: self.pyplot_imported = True backend = g.os_path_finalize_join(g.app.loadDir, '..', 'plugins', 'pyplot_backend.py') if g.os_path_exists(backend): try: # The order of these statements is important... import matplotlib matplotlib.use('module://leo.plugins.pyplot_backend') if trace: g.trace('===== LOADED: pyplot.backend') except ImportError: g.trace('===== FAIL: pyplot.backend') else: g.trace('===== MISSING: pyplot.backend') try: import matplotlib # Make *sure* this is imported. import matplotlib.pyplot as plt import numpy as np import matplotlib.animation as animation plt.ion() # Automatically set interactive mode. namespace = { 'animation': animation, 'matplotlib': matplotlib, 'numpy': np, 'np': np, 'pyplot': plt, 'plt': plt, } except ImportError: g.es_print('matplotlib imports failed') namespace = {} self.embed_pyplot_widget() c.executeScript(event=None, args=None, p=None, script=None, useSelectedText=False, define_g=True, define_name='__main__', silent=False, namespace=namespace, raiseFlag=False)
def run(self, p=None, force=False): '''Run Pyflakes on all Python @<file> nodes in c.p's tree.''' c = self.c root = p or c.p # Make sure Leo is on sys.path. leo_path = g.os_path_finalize_join(g.app.loadDir, '..') if leo_path not in sys.path: sys.path.append(leo_path) # Run pyflakes on all Python @<file> nodes in root's tree. t1 = time.time() found = False for p in root.self_and_subtree(): found |= self.find(p) # Look up the tree if no @<file> nodes were found. if not found: for p in root.parents(): if self.find(p): found = True break # If still not found, expand the search if root is a clone. if not found: isCloned = any([p.isCloned() for p in root.self_and_parents()]) if isCloned: for p in c.all_positions(): if p.isAnyAtFileNode(): isAncestor = any( [z.v == root.v for z in p.self_and_subtree()]) if isAncestor and self.find(p): break paths = list(set(self.seen)) if paths: # These messages are important for clarity. log_flag = not force total_errors = self.check_all(log_flag, paths) if total_errors > 0: g.es('ERROR: pyflakes: %s error%s' % (total_errors, g.plural(total_errors))) elif force: g.es('OK: pyflakes: %s file%s in %s' % (len(paths), g.plural(paths), g.timeSince(t1))) else: g.es('OK: pyflakes') ok = total_errors == 0 else: ok = True return ok
def get_lines_from_rev(self, rev, fn): '''Get the file from the given rev, or the working directory if None.''' if rev: command = 'git show %s:%s' % (rev, fn) lines = g.execGitCommand(command, self.repo_dir) else: # Get the file from the working directory. path = g.os_path_finalize_join(self.repo_dir, fn) if g.os_path_exists(path): with open(path, 'r') as f: s = f.read().replace('\r','') s = g.toUnicode(s) lines = g.splitLines(s) else: g.trace('not found:', path) lines = [] return lines
def get_fn(self, p): ''' Finalize p's file name. Return if p is not an @file node for a python file. ''' c = self.c if not p.isAnyAtFileNode(): g.trace('not an @<file> node: %r' % p.h) return None # #67. aList = g.get_directives_dict_list(p) path = c.scanAtPathDirectives(aList) fn = p.anyAtFileNodeName() if not fn.endswith('.py'): g.trace('not a python file: %r' % p.h) return None return g.os_path_finalize_join(path, fn)
def open_theme_file_helper(event, closeFlag, fn): '''Open a theme file and apply the theme.''' trace = False and not g.unitTesting c = event and event.get('c') if not c: return old_dir = g.os_path_abspath(os.curdir) themes_dir = g.os_path_finalize_join(g.app.loadDir, '..', 'themes') if fn: fn = c.styleSheetManager.find_theme_file(fn) if not fn: return else: fn = g.app.gui.runOpenFileDialog(c, title="Open Theme", filetypes=[ g.fileFilters("LEOFILES"), ("All files", "*"), ], defaultextension=g.defaultLeoFileExtension(c), startpath=themes_dir, ) c.bringToFront() c.init_error_dialogs() # Adapted from c.open(). if fn and g.app.loadManager.isLeoFile(fn): # Close the file if it is already open, provided there is another. aList = g.app.commanders() if len(aList) > 1: for c2 in aList: if trace: g.trace('COMPARE\n%s\n%s' % (fn, c2.fileName())) if fn == c2.fileName(): if trace: g.trace('===== CLOSING', fn) c2.close(new_c=c) break c2 = g.openWithFileName(fn, old_c=c) if c2: c2.k.makeAllBindings() g.chdir(fn) g.setGlobalOpenDir(fn) if closeFlag: g.app.destroyWindow(c2.frame) g.app.windowList.remove(c2.frame) os.chdir(old_dir) c.raise_error_dialogs(kind='write') g.app.runAlreadyOpenDialog(c) c.initialFocusHelper()
def get_flake8_config(): '''Return the path to the flake8 configuration file.''' join = g.os_path_finalize_join homeDir = get_home() loadDir = g.os_path_finalize_join(g.__file__, '..', '..') base_table = ('flake8', 'flake8.txt') dir_table = ( homeDir, join(homeDir, '.leo'), join(loadDir, '..', '..', 'leo', 'test'), ) for base in base_table: for path in dir_table: fn = g.os_path_abspath(join(path, base)) if g.os_path_exists(fn): return fn print('no flake8 configuration file found in\n%s' % ('\n'.join(dir_table))) return None
def shadowPathName(self, filename): """Return the full path name of filename, resolved using c.fileName()""" x = self; c = x.c baseDir = x.baseDirName() fileDir = g.os_path_dirname(filename) # 2011/01/26: bogomil: redirect shadow dir if self.shadow_in_home_dir: # Each .leo file has a separate shadow_cache in base dir fname = "_".join([os.path.splitext(os.path.basename(c.mFileName))[0], "shadow_cache"]) # On Windows incorporate the drive letter to the private file path if os.name == "nt": fileDir = fileDir.replace(':', '%') # build the chache path as a subdir of the base dir fileDir = "/".join([baseDir, fname, fileDir]) return baseDir and g.os_path_finalize_join( # 1341 baseDir, fileDir, # Bug fix: honor any directories specified in filename. x.shadow_subdir, x.shadow_prefix + g.shortFileName(filename))