Skip to content

Commit 8312ab7

Browse files
Merge 25b87fd into 9967903
2 parents 9967903 + 25b87fd commit 8312ab7

2 files changed

Lines changed: 96 additions & 6 deletions

File tree

source/globalCommands.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- coding: UTF-8 -*-
2-
#globalCommands.py
3-
#A part of NonVisual Desktop Access (NVDA)
4-
#This file is covered by the GNU General Public License.
5-
#See the file COPYING for more details.
6-
#Copyright (C) 2006-2018 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
2+
# globalCommands.py
3+
# A part of NonVisual Desktop Access (NVDA)
4+
# This file is covered by the GNU General Public License.
5+
# See the file COPYING for more details.
6+
# Copyright (C) 2006-2020 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui Batista, Joseph Lee,
7+
# Leonard de Ruijter, Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Łukasz Golonka, Accessolutions,
8+
# Julien Cochuyt
79

810
import time
911
import itertools
@@ -1623,6 +1625,42 @@ def script_navigatorObject_devInfo(self,gesture):
16231625
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.")
16241626
script_navigatorObject_devInfo.category=SCRCAT_TOOLS
16251627

1628+
@script(
1629+
# Translators: Input help mode message for a command to delimit then
1630+
# copy a fragment of the log to clipboard
1631+
description=_(
1632+
"Mark the current end of the log as the start of the fragment to be"
1633+
" copied to clipboard by pressing again."
1634+
),
1635+
category=SCRCAT_TOOLS,
1636+
gesture="kb:NVDA+control+shift+f1"
1637+
)
1638+
def script_log_markStartThenCopy(self, gesture):
1639+
if globalVars.appArgs.secure:
1640+
return
1641+
if log.fragmentStart is None:
1642+
if log.markFragmentStart():
1643+
# Translators: Message when marking the start of a fragment of the log file for later copy
1644+
# to clipboard
1645+
ui.message(_("Log fragment start position marked, press again to copy to clipboard"))
1646+
else:
1647+
# Translators: Message when failed to mark the start of a
1648+
# fragment of the log file for later copy to clipboard
1649+
ui.message(_("Unable to mark log position"))
1650+
return
1651+
text = log.getFragment()
1652+
if not text:
1653+
# Translators: Message when attempting to copy an empty fragment of the log file
1654+
ui.message(_("No new log entry to copy"))
1655+
return
1656+
if api.copyToClip(text):
1657+
# Translators: Message when a fragment of the log file has been
1658+
# copied to clipboard
1659+
ui.message(_("Log fragment copied to clipboard"))
1660+
else:
1661+
# Translators: Presented when unable to copy to the clipboard because of an error.
1662+
ui.message(_("Unable to copy"))
1663+
16261664
@script(
16271665
# Translators: Input help mode message for Open user configuration directory command.
16281666
description=_("Opens NVDA configuration directory for the current user."),

source/logHandler.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# A part of NonVisual Desktop Access (NVDA)
2-
# Copyright (C) 2007-2020 NV Access Limited, Rui Batista, Joseph Lee, Leonard de Ruijter, Babbage B.V.
2+
# Copyright (C) 2007-2020 NV Access Limited, Rui Batista, Joseph Lee, Leonard de Ruijter, Babbage B.V.,
3+
# Accessolutions, Julien Cochuyt
34
# This file is covered by the GNU General Public License.
45
# See the file COPYING for more details.
56

@@ -113,6 +114,11 @@ class Logger(logging.Logger):
113114
DEBUGWARNING = 15
114115
OFF = 100
115116

117+
#: The start position of a fragment of the log file as marked with
118+
#: L{markFragmentStart} for later retrieval using L{getFragment}.
119+
#: @type: C{long}
120+
fragmentStart = None
121+
116122
def _log(self, level, msg, args, exc_info=None, extra=None, codepath=None, activateLogViewer=False, stack_info=None):
117123
if not extra:
118124
extra={}
@@ -189,6 +195,52 @@ def exception(self, msg="", exc_info=True, **kwargs):
189195
return
190196
self._log(level, msg, (), exc_info=exc_info, **kwargs)
191197

198+
def markFragmentStart(self):
199+
"""Mark the current end of the log file as the start position of a
200+
fragment to be later retrieved by L{getFragment}.
201+
@returns: Whether a log file is in use and a position could be marked
202+
@rtype: bool
203+
"""
204+
if (
205+
not globalVars.appArgs
206+
or globalVars.appArgs.secure
207+
or not globalVars.appArgs.logFileName
208+
or not self.handlers
209+
or not isinstance(self.handlers[0], FileHandler)
210+
):
211+
return False
212+
import codecs
213+
with codecs.open(globalVars.appArgs.logFileName, "r", encoding="UTF-8") as f:
214+
# io.IOBase.seek: whence=2 -- end of stream
215+
f.seek(0, whence=2)
216+
self.fragmentStart = f.tell()
217+
return True
218+
219+
def getFragment(self):
220+
"""Retrieve a fragment of the log starting from the position marked using
221+
L{markFragmentStart}.
222+
If L{fragmentStart} does not point to the current end of the log file, it
223+
is reset to C{None} after reading the fragment.
224+
@returns: The text of the fragment, or C{None} if L{fragmentStart} is None.
225+
@rtype: str
226+
"""
227+
if (
228+
self.fragmentStart is None
229+
or not globalVars.appArgs
230+
or globalVars.appArgs.secure
231+
or not globalVars.appArgs.logFileName
232+
or not self.handlers
233+
or not isinstance(self.handlers[0], FileHandler)
234+
):
235+
return None
236+
import codecs
237+
with codecs.open(globalVars.appArgs.logFileName, "r", encoding="UTF-8") as f:
238+
f.seek(self.fragmentStart)
239+
fragment = f.read()
240+
if fragment:
241+
self.fragmentStart = None
242+
return fragment
243+
192244
class RemoteHandler(logging.Handler):
193245

194246
def __init__(self):

0 commit comments

Comments
 (0)