Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion source/globalCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2006-2020 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui Batista, Joseph Lee,
# Leonard de Ruijter, Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Łukasz Golonka
# Leonard de Ruijter, Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Łukasz Golonka, Accessolutions,
# Julien Cochuyt

import time
import itertools
Expand Down Expand Up @@ -1714,6 +1715,42 @@ def script_navigatorObject_devInfo(self,gesture):
script_navigatorObject_devInfo.__doc__ = _("Logs information about the current navigator object which is useful to developers and activates the log viewer so the information can be examined.")
script_navigatorObject_devInfo.category=SCRCAT_TOOLS

@script(
description=_(
# Translators: Input help mode message for a command to delimit then
# copy a fragment of the log to clipboard
"Mark the current end of the log as the start of the fragment to be"
" copied to clipboard by pressing again."
),
category=SCRCAT_TOOLS,
gesture="kb:NVDA+control+shift+f1"
)
def script_log_markStartThenCopy(self, gesture):
if globalVars.appArgs.secure:
return
if log.fragmentStart is None:
if log.markFragmentStart():
# Translators: Message when marking the start of a fragment of the log file for later copy
# to clipboard
ui.message(_("Log fragment start position marked, press again to copy to clipboard"))
else:
# Translators: Message when failed to mark the start of a
# fragment of the log file for later copy to clipboard
ui.message(_("Unable to mark log position"))
return
text = log.getFragment()
if not text:
# Translators: Message when attempting to copy an empty fragment of the log file
ui.message(_("No new log entry to copy"))
return
if api.copyToClip(text):
# Translators: Message when a fragment of the log file has been
# copied to clipboard
ui.message(_("Log fragment copied to clipboard"))
else:
# Translators: Presented when unable to copy to the clipboard because of an error.
ui.message(_("Unable to copy"))

@script(
# Translators: Input help mode message for Open user configuration directory command.
description=_("Opens NVDA configuration directory for the current user."),
Expand Down
50 changes: 49 additions & 1 deletion source/logHandler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2007-2020 NV Access Limited, Rui Batista, Joseph Lee, Leonard de Ruijter, Babbage B.V.
# Copyright (C) 2007-2020 NV Access Limited, Rui Batista, Joseph Lee, Leonard de Ruijter, Babbage B.V.,
# Accessolutions, Julien Cochuyt
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

Expand Down Expand Up @@ -113,6 +114,11 @@ class Logger(logging.Logger):
DEBUGWARNING = 15
OFF = 100

#: The start position of a fragment of the log file as marked with
#: L{markFragmentStart} for later retrieval using L{getFragment}.
#: @type: C{long}
fragmentStart = None

def _log(self, level, msg, args, exc_info=None, extra=None, codepath=None, activateLogViewer=False, stack_info=None):
if not extra:
extra={}
Expand Down Expand Up @@ -189,6 +195,48 @@ def exception(self, msg="", exc_info=True, **kwargs):
return
self._log(level, msg, (), exc_info=exc_info, **kwargs)

def markFragmentStart(self):
"""Mark the current end of the log file as the start position of a
fragment to be later retrieved by L{getFragment}.
@returns: Whether a log file is in use and a position could be marked
@rtype: bool
"""
if (
not globalVars.appArgs
or globalVars.appArgs.secure
or not globalVars.appArgs.logFileName
or not isinstance(logHandler, FileHandler)
):
return False
with open(globalVars.appArgs.logFileName, "r", encoding="UTF-8") as f:
# _io.TextIOWrapper.seek: whence=2 -- end of stream
f.seek(0, 2)
self.fragmentStart = f.tell()
return True

def getFragment(self):
"""Retrieve a fragment of the log starting from the position marked using
L{markFragmentStart}.
If L{fragmentStart} does not point to the current end of the log file, it
is reset to C{None} after reading the fragment.
@returns: The text of the fragment, or C{None} if L{fragmentStart} is None.
@rtype: str
"""
if (
self.fragmentStart is None
or not globalVars.appArgs
or globalVars.appArgs.secure
or not globalVars.appArgs.logFileName
or not isinstance(logHandler, FileHandler)
):
return None
with open(globalVars.appArgs.logFileName, "r", encoding="UTF-8") as f:
f.seek(self.fragmentStart)
fragment = f.read()
if fragment:
self.fragmentStart = None
return fragment

class RemoteHandler(logging.Handler):

def __init__(self):
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ What's New in NVDA
- The GUI Helper's BoxSizerHelper.addDialogDismissButtons supports a new "separated" keyword argument, for adding a standard horizontal separator to dialogs (other than messages and single input dialogs). (#6468)
- Additional properties were added to app modules, including path for the executable (appPath), is a Windows Store app (isWindowsStoreApp), and machine architecture for the app (appArchitecture). (#7894)
- It is now possible to create app modules for apps hosted inside wwahost.exe on Windows 8 and later. (#4569)
- A fragment of the log can now be delimited and then copied to clipboard using NVDA+control+shift+F1. (#9280)


= 2020.2 =
Expand Down