def __init__(self, file): """Create a new instance of LocalHistory. File must be an instance of GPS.File""" self.file = file.path project = file.project(default_to_root=False) if project: dir = project.object_dirs(recursive=False)[0] elif Preference("Plugins/local_history/when_no_prj").get(): dir = os.path.dirname(self.file) else: return self.rcs_dir = os.path.join( dir, Preference("Plugins/local_history/rcsdir").get()) self.rcs_file = os.path.join(self.rcs_dir, os.path.basename( self.file)) + ",v" # convert all \ to / for Cygwin toolset, note that forward # slashes are handled by the native Win32 API. So it is safe to # do that on Windows. self.file = self.file.replace("\\", "/") self.rcs_file = self.rcs_file.replace("\\", "/")
def backtrace(self, bt): self.clear() cmd = "addr2line -e " + self.executable + " " + \ Preference("Plugins/addr2line/args").get() self.write(cmd + "\n") Process(["addr2line", "-e", self.executable] + Preference("Plugins/addr2line/args").get().split() + bt.split(), ".+", on_exit=self.on_exit, on_match=self.on_output)
def on_gps_started(hook): # Set the preferences. You can adjust them at your convenience. Preference("Doc-Process-Body").set(True) Preference("Doc-Show-Private").set(True) Preference("Doc-References").set(True) Preference("Doc-Up-To-Date-Only").set(False) # Generate documentation for the root projects and all subprojects. Project.root().generate_doc(recursive=True) # Try to exit every 10 seconds. delayed_exit(10000)
def add_dependency(self, dependency, newdep=True, removed=False): """Indicate a new GPS.Project dependency for the current project""" show_diff = Preference("Plugins/dependencies/show_diff").get() if removed and show_diff: Console().write(" - " + dependency.path + "\n") elif newdep or not show_diff: Console().write(" + " + dependency.path + "\n")
def explain_dependency(self, file, depends_on): """Explains the last add_dependency: file depends on depends_on""" if Preference("Plugins/dependencies/show_source").get(): Console().write( " => {} depends on {}\n".format( os.path.basename(file.path), os.path.basename(depends_on.path) ) )
def cleanup_history(self): """Remove the older revision histories for self""" if not self.rcs_dir: return max_days = Preference("Plugins/local_history/maxdays").get() older = datetime.datetime.now() - datetime.timedelta(days=max_days) older = older.strftime("%Y.%m.%d.%H.%M.%S") revisions = self.get_revisions() max_revisions = Preference("Plugins/local_history/maxrevisions").get() if revisions: version = max(0, revisions[0][0] - max_revisions) for r in revisions: if r[1] < older: version = max(version, r[0]) break if version >= 1: Logger("LocalHist").log("Truncating file %s to revision %s" % (self.rcs_file, version)) proc = Process("rcs -o:1.%s %s" % (version, self.rcs_file)) proc.wait()
def add_breakpoint_exception(): context = current_context() global autocont_br # Only consider base names of files, since the debugger does not always # show the full name in the "frame" command f = "%s:%s" % (os.path.basename( context.file().path), context.location().line()) if f in autocont_br: autocont_br.remove(f) else: autocont_br.add(f) if Preference("Plugins/debugger/save_autocont_br").get(): Project.root().set_property("autocont_br", "--".join(autocont_br), True)
def insert_overlays(self): highlight_next_matches = Preference( 'Plugins/isearch/highlightnext').get() if highlight_next_matches: input = self.read() self.overlay_loc = self.loc if input != '': if has_pygtk: self.insert_overlays_id = GLib.idle_add( self.insert_next_overlay, input) elif len(input) > 2: while self.insert_next_overlay(input): pass
def __init__(self): try: self.loc = EditorBuffer.get().current_view().cursor() CommandWindow.__init__(self, prompt=self.prompt(), on_cancel=self.on_cancel, on_key=self.on_key, on_activate=self.on_activate) self.set_background(Preference("Plugins/vi/bgcolor").get()) self.current_in_history = -1 self.current_cmd_line = "" # Before moving in the history except: pass
def show_diff(self, revision, date): """Show, in a console, the diff between the current version and revision""" if self.rcs_dir and os.path.isdir(self.rcs_dir): pwd = os.getcwd() os.chdir(os.path.dirname(self.file)) diff_switches = Preference( "Plugins/local_history/diff_switches").get() proc = Process("rcsdiff " + diff_switches + " -r" + revision + " " + self.rcs_file) diff = proc.get_result() os.chdir(pwd) Console("Local History").clear() Console("Local History").write("Local history at " + date + "\n") Console("Local History").write(diff)
def compute_project_dependencies(output): try: depends_on = dict() current_deps = dict() for p in Project.root().dependencies(recursive=True): current_deps[p] = [cur for cur in p.dependencies(recursive=False)] tmp = dict() previous = p for s in p.sources(recursive=False): for imp in s.imports(include_implicit=True, include_system=False): ip = imp.project(default_to_root=False) if ip and ip != p: if show_single_file: if ip != previous: tmp[ip] = [(s, imp)] else: try: tmp[ip].append((s, imp)) except KeyError: tmp[ip] = [(s, imp)] previous = ip depends_on[p] = tmp no_source_projects = [ s.strip().lower() for s in Preference( "Plugins/dependencies/no_src_prj").get().split(",") ] for p in depends_on: output.set_current_project(p) for dep in depends_on[p]: output.add_dependency(dep, newdep=dep not in current_deps[p]) for reason in depends_on[p][dep]: output.explain_dependency(reason[0], reason[1]) try: current_deps[p].remove(dep) except: pass for dep in current_deps[p]: if dep.path.lower() not in no_source_projects: output.add_dependency(dep, newdep=False, removed=True) output.close() except: Console().write("Unexpected exception " + traceback.format_exc())
def fmt_selection(): """Process the current selection through the "fmt" command to reformat paragraphs """ width = Preference("Src-Editor-Highlight-Column").get() buffer = EditorBuffer.get() prefix = None if buffer.file().language() == "ada": prefix = "--" loc = buffer.selection_start().beginning_of_line() while loc.get_char() == ' ': loc = loc + 1 prefix = '-p """' + (' ' * (loc.column() - 1)) + prefix + '"""' sel_pipe("fmt " + prefix + " -w " + repr(width), buffer)
def do_replace(arg, loc, maxloc): buffer = loc.buffer() params = arg[1:].split(arg[0]) if len(params) == 3: pattern, replace, options = params elif len(params) == 2: pattern, replace = params options = "" count = 1 icase = Preference("Plugins/vi/ignorecase").get() or (options.find("i") < 0) if loc == maxloc: maxloc = loc.end_of_line() # On whole line by default else: count = 10000000 if options.find("g") >= 0: count = 100000000 # as many times as needed while count > 0: result = loc.search(pattern, regexp=True, dialog_on_failure=False, case_sensitive=icase) if not result: return else: start, last = result if start > maxloc: return # Add support for \1,.. in the replacement string found = buffer.get_chars(start, last - 1) if icase: r = re.compile(pattern) else: r = re.compile(pattern, re.IGNORECASE) repl = r.sub(replace, found) buffer.delete(start, last - 1) buffer.insert(start, repl) loc = start + len(repl) buffer.current_view().goto(loc) count = count - 1
def remove_overlays(self): """Remove all isearch overlays in the current editor""" highlight_next_matches = Preference( 'Plugins/isearch/highlightnext').get() self.cancel_idle_overlays() if highlight_next_matches: loc = self.editor.beginning_of_buffer() is_on = loc.has_overlay(self.overlay) end = self.editor.end_of_buffer() while loc < end: loc2 = loc.forward_overlay(self.overlay) if is_on: self.editor.remove_overlay(self.overlay, loc, loc2) is_on = not is_on loc = loc2
def EntityIterator(where): """Return all entities from WHERE""" if not where: ignore_projects = [ s.strip().lower() for s in Preference( "Plugins/unused_entities/ignoreprj").get().split(",") ] for p in Project.root().dependencies(recursive=True): if p.name().lower() not in ignore_projects: Console().write("Searching unused entities in project " + p.name() + "\n") for s in p.sources(): for e in s.entities(local=True): yield e elif isinstance(where, Project): for s in where.sources(): for e in s.entities(local=True): yield e elif isinstance(where, File): for e in where.entities(local=True): yield e
Automatically saves the contents of the Messages window when a compilation has finished. The output is saved in a file called "messages.txt" (or some other name set in the preferences) in the root project's object directory. If there is no object directory for the root project, then the file is saved in the directory of the project file itself. """ from GPS import Preference, Project, Console from os.path import dirname, join from gs_utils import hook file_name_pref = Preference("Plugins/save_on_compile/file_name").create( "File Name", "string", "Name of the file you want to save the messages into", "messages.txt") @hook('compilation_finished') def on_compilation_finished(*args): obj_dirs = Project.root().object_dirs(False) path = obj_dirs[0] if obj_dirs else dirname(Project.root().file().path) base = file_name_pref.get() if not base: Console().write( "plugin save_on_compile.py: no file name is specified in the" " preferences\n") else: try:
EditorBuffer, MDI from gps_utils import interactive xmlada_projects = [ "xmlada_sax", "xmlada_dom", "xmlada_schema", "xmlada_unicode", "xmlada_input", "xmlada_shared", "xmlada" ] aws_projects = [ "aws_config", "aws_libz", "aws_shared", "aws_ssl_support", "aws_components", "aws_xmlada", "aws" ] Preference("Plugins/unused_entities/ignoreprj").create( "Ignored projects", "string", """Comma-separated list of projects for which we never want to look for unused entities. # This should in general include those projects from third-party libraries. You can still search for unusued entities if you select that project specifically.""", ",".join(xmlada_projects + aws_projects)) def EntityIterator(where): """Return all entities from WHERE""" if not where: ignore_projects = [ s.strip().lower() for s in Preference( "Plugins/unused_entities/ignoreprj").get().split(",") ] for p in Project.root().dependencies(recursive=True): if p.name().lower() not in ignore_projects:
If the variable highlight_next_matches is set to True, then whenever you modify the current pattern, GPS will also highlight the next matches of this pattern in the buffer. Such higlights will stay even when you cancel the current search. To hide them, start a new search, and cancel it immediately. The highlighting of the next matches is done in the background if pygtk was installed along with GPS. Otherwise, it is done every time the pattern is modified, and will slow things down a little """ from GPS import CommandWindow, EditorBuffer, Hook, Preference, \ execute_action, lookup_actions_from_key from gps_utils import interactive Preference('Plugins/isearch/highlightnext').create( 'Highlight next matches', 'boolean', "Highlight the next matches in the editor." + " This highlighting will be visible until the next isearch command." + " To cancel, start an isearch and press Esc immediately", True) bg_next_match_pref = Preference('Search-Src-Highlight-Color') bg_color_pref = Preference('Command-Windows-Background-Color') bg_error_pref = Preference('High-Importance-Messages-Highlight') isearch_action_name = 'isearch' isearch_backward_action_name = 'isearch backward' # Changing the name of menus should be reflected in emacs.xml try: # If we have PyGTK installed, we'll do the highlighting of the next # matches in the background, which makes the interface more responsive from gi.repository import GLib
- "ls" => If you have no current selection, this will simply insert the contents of the current directory in the file - "date" => Insert the current date in the file """ ############################################################################ # No user customization below this line ############################################################################ from GPS import Preference, EditorBuffer, Process, CommandWindow from gps_utils import interactive Preference("External Commands:Pipe/bgcolor").create( "Background color", "color", "Background color for the command window" " where you enter the command to execute", "yellow") def sel_pipe(command, buffer=None): """Process the current selection in BUFFER through COMMAND, and replace that selection with the output of the command""" if not buffer: buffer = EditorBuffer.get() start = buffer.selection_start() end = buffer.selection_end() # Ignore white spaces and newlines at end, to preserve the rest # of the text if start != end: while end.get_char() == ' ' or end.get_char() == '\n':
A convenience menu is added to open the console: /Navigate/Open Addr2line Console It asks you for the location of the executable """ ############################################################################# # No user customization below this line ############################################################################# from GPS import Console, EditorBuffer, File, MDI, Preference, Process from gps_utils import interactive import re import os.path Preference("Plugins/addr2line/args").create( "Arguments", "string", """Additional arguments to pass to addr2line""", "--functions --demangle=gnat") file_line_re = "(([-_\w./\\\\]+):(\d+)(:(\d+))?)" class Addr2line(Console): def __init__(self, executable): self.executable = executable self.name = "addr2line -e " + os.path.basename(self.executable) Console.__init__(self, self.name, on_input=Addr2line.on_input) self.create_link(file_line_re, self.onclick) self.clear() self.write("Backtrace ?") self.enable_input(True) MDI.get(self.name).raise_window()
you use the <up> and <down> keys, previous commands can be executed again, or modified and then executed. In addition, pression <control-.> will execute the previous command without displaying the command window. This is by analogy with vi's <.> command, although the scope is less ambitious here. """ ############################################################################# # No user customization below this line ############################################################################# from GPS import Preference, CommandWindow, EditorBuffer, Hook, parse_xml import re Preference("Plugins/vi/bgcolor").create( "Background color", "color", """Color to use for the command line window""", "red") Preference("Plugins/vi/ignorecase").create( "Ignore case", "boolean", """If enabled, searching will ignore casing by default""", False) def on_gps_started(hook_name): parse_xml(""" <action name='vi_command_line' category="Editor" output="none"> <description /> <filter id="Source editor" /> <shell lang="python">vi.CmdLine()</shell> </action> <action name='vi_repeat_cmd' category="Editor" output="none">
def __init__(self): CommandWindow.__init__(self, global_window=True, prompt="Shell command:", on_activate=self.on_activate) self.set_background(Preference("External Commands:Pipe/bgcolor").get())
GPS Messages window (which you can then save to a text file, or through a graphical tree widget, which you can dynamically manipulate. """ # # No user customization below this line # from GPS import Console, EditorBuffer, File, Preference, Project, XMLViewer from gps_utils import interactive import traceback import re import os Preference("Plugins/dependencies/show_source").create( "Show source", "boolean", "If enabled, show the file dependencies that explain project dependencies" ". If disabled, you only see the dependencies between the projects", False) Preference("Plugins/dependencies/show_diff").create( "Show diff", "boolean", "If enabled, show only the differences with the current project setup." "This mode helps you clean up the with statements in your projects", True) Preference("Plugins/dependencies/no_src_prj").create( "Projects with no sources", "string", "comma-separated list of project names that contain no sources, but are " "used to share common settings. Since this script looks at source files " "to find out dependencies, the dependencies on such projects would not " "be shown otherwise.", "shared") show_single_file = True
""" ########################################################################### # No user customization below this line ########################################################################### from GPS import Console, Debugger, EditorBuffer, \ Entity, Hook, Preference, Project, current_context from gps_utils import interactive, with_save_current_window import text_utils import re import os.path Preference("Plugins/debugger/save_autocont_br").create( "Preserve auto-cont breakpoints", "boolean", "If set, the source locations where the debugger should not stop on an" + " exception are preserved across GPS sessions. If unset, you'll have to" + " reset them the next time you start the debugger, but on the other" + " hand this might work better when the source code has changed", True) def in_debugger(context): try: return Debugger.get() is not None except: return False def in_debugger_and_file(context): try: return Debugger.get() is not None and context.file() is not None except:
def on_gps_started(hook): # Set the preferences. You can adjust them at your convenience. Preference("Ada-Format-Operators").set(True) Preference("Ada-Ident-Casing").set("Smart_Mixed") Preference("Warnings-Src-Highlight-Color").set("#FFFF6D6D6D6D")
########################################################################### # No user customization below this line ############################################################################ from GPS import Console, Contextual, EditorBuffer, File, Hook, Logger, \ Preference, Process, Vdiff, XMLViewer import os import shutil import datetime import traceback import time import re Preference("Plugins/local_history/rcsdir").create( "Local RCS dir", "string", """Name of the local directory created to store history locally. One such directory will be created in each object directory of the project and its subprojects""", ".gpsrcs") Preference("Plugins/local_history/maxdays").create( "Max age", "integer", """Keep revisions for that many days at most""", 2, 0, 1000) Preference("Plugins/local_history/maxrevisions").create( "Max revisions", "integer", """Maximal number of revisions to keep""", 200, 0, 10000) Preference("Plugins/local_history/diff_switches").create( "Diff switches", "string",