2017-10-26 2 views
2

Ich versuche ein Plugin zu erstellen, das eine .log-Datei öffnet, die mit einer Datei verknüpft ist, die ich bearbeite. Ich konnte die Datei öffnen, konnte aber den Cursor nicht zum Ende der Datei bewegen, es sei denn, ich führe den Code erneut aus, wenn die Datei bereits geöffnet ist.Plugin zum Öffnen der Datei bei eof

import sublime 
import sublime_plugin 

class OpenlogCommand(sublime_plugin.TextCommand): 
    def run(self, edit): 
     if os.path.isfile(self.view.file_name()[:-3]+"log"): 
      a=sublime.active_window().open_file(self.view.file_name()[:-3]+"log") 
     a.run_command("move_to", {"to": "eof"}) 

Weiß jemand, wie man es macht?

Antwort

1

Der Grund, dass dies nicht funktioniert, wenn die Datei bereits geöffnet ist, weil das Laden einer Datei asynchron ist; Der Befehl zum Öffnen der Datei wird sofort zurückgegeben und die Datei wird im Hintergrund geladen, wenn sie nicht bereits geöffnet ist.

Wenn Sie also das erste Mal den Befehl ausführen, wird der Befehl move_to nicht ausgeführt, da er bereits am Ende eines leeren Puffers steht. Wenn die Datei jedoch bereits geladen wurde, wird der erwartete Vorgang ausgeführt.

Um dies zu umgehen, müssen Sie feststellen, ob die Datei noch geladen ist, und den Aufruf verzögern, um bis zum Ende der Datei zu springen, bis sie beendet ist. Ein Beispiel dafür ist die folgende:

import sublime 
import sublime_plugin 
import os 

class OpenLogCommand(sublime_plugin.TextCommand): 
    def run(self, edit): 
     log_name = self.view.file_name()[:-3] + "log" 
     log_view = self.view.window().open_file(log_name) 

     if log_view.is_loading(): 
      log_view.settings().set("_goto_eol", True) 
     else: 
      log_view.run_command("move_to", {"to": "eof"}) 

    def is_enabled(self): 
     fname = self.view.file_name() 
     if fname is not None and not fname.endswith(".log"): 
      return os.path.isfile(fname[:-3] + "log") 

     return False 

class OpenLogListener(sublime_plugin.EventListener): 
    def on_load(self, view): 
     if view.settings().get("_goto_eol", False): 
      view.settings().erase("_goto_eol") 
      view.run_command("move_to", {"to": "eof"}) 

Ein Problem mit Ihrer vorhandenen Version davon ist, dass die file_name() Methode gibt None, wenn die Datei noch nicht auf Platte gespeichert wurde. Wenn Sie diesen Befehl für eine nicht gespeicherte Datei ausführen, wird ein Fehler in der Konsole generiert. Dies ist harmlos, aber ein wenig unrein, da es ein Fehler sein könnte, wenn Sie andere Probleme haben und diese Fehler in der Konsole sehen.

Hier wird der Befehl nur aktiviert, wenn die Datei gespeichert wurde, um diese Art von Problem zu stoppen. Es wird auch nur aktiviert, wenn es sich nicht bereits um eine Protokolldatei handelt (da dies redundant wäre) und wenn eine zugehörige Protokolldatei tatsächlich vorhanden ist.

Wenn ein Befehl deaktiviert ist, können Sie ihn nicht ausführen. Das bedeutet, dass es auch nicht in der Befehlspalette angezeigt wird und in Menüs ausgegraut erscheint (vorausgesetzt, Sie haben es zu einem der beiden hinzugefügt).

Wenn Sie den Befehl ausführen, ruft er zuerst open_file auf, um die zugehörige Protokolldatei zu öffnen, und fragt dann die Ansicht "Laden Sie noch?". Wenn die Ansicht NEIN sagt, bedeutet dies, dass die Datei bereits geöffnet ist und wir sofort zum Ende der Datei springen können.

Wenn die Ansicht JA zu dieser Frage sagt, setzen wir eine temporäre Einstellung in der Ansicht, so dass wir wissen, dass wenn der Inhalt dieser Ansicht fertig geladen ist, wir zum Ende des Puffers springen wollen.

Der Ereignis-Listener fragt jede Ansicht nach dem Laden ab, ob diese Einstellung festgelegt wurde. Wenn dies der Fall ist, wird die Einstellung entfernt und dann zum Ende der Datei gesprungen.


[Bearbeiten]

Wie unten in den Kommentaren erwähnt, ist der move_to Befehl verhält sich etwas anders für eine Datei, die im Vergleich zu einer Datei bereits geöffnet ist, das Laden gerade beendet hat.

Ich bin nicht ganz sicher, warum das der Fall ist, aber ich vermute, dass es eine subtile Wechselwirkung zwischen der on_load Benachrichtigung geliefert wird, wenn der Dateiinhalt geladen wurde, aber noch nicht angezeigt oder etwas in diesen Zeilen, obwohl dies ist nur eine Vermutung.

In jedem Fall ist die zweckmäßigste fix wäre eine leichte Modifikation des Ereignis-Listener zu machen, indem der Teil des Codes oben mit diesem statt ersetzen:

class OpenLogListener(sublime_plugin.EventListener): 
    def on_load(self, view): 
     if view.settings().get("_goto_eol", False): 
      view.settings().erase("_goto_eol") 
      sublime.set_timeout(lambda: view.run_command("move_to", {"to": "eof"}), 1) 

Dies ändert die Dinge so ein wenig nach oben, dass Der Aufruf des Befehls move_to erfolgt effektiv, nachdem die gesamte Ereignisbehandlung abgeschlossen wurde. Das scheint das Problem zumindest auf meiner Testmaschine zu lösen.

+0

Danke für die tolle Erklärung! Ich habe ein kleines Problem mit dem Befehl eof. Wenn ich Strg + Ende in einem beliebigen Puffer drücke, wird der Cursor in die letzte Zeile gesetzt und die letzte Zeile bleibt am unteren Rand der Seite, wodurch die Textmenge auf dem Bildschirm maximiert wird. Mit diesem Code funktioniert es so, wenn die .log-Datei bereits geöffnet ist. Wenn es noch nicht geöffnet ist, legt es die letzte Textzeile in die erste Zeile des Bildschirms, zeigt überhaupt keinen Text und ich muss nach oben scrollen, um den Text zu sehen. Ich habe bisher viel auf Google gesucht, ohne Erfolg. Weißt du, wie man das löst? – Emerson

+0

Hmm interessant. Ich bin mir nicht sicher, warum das passiert, obwohl es verdächtig scheint. Ich habe die Antwort bearbeitet, um eine mögliche Problemumgehung bereitzustellen. Lassen Sie mich wissen, ob das für Sie funktioniert oder nicht. – OdatNurd

+0

Perfekt! Vielen Dank! – Emerson