Skip to content

Commit

Permalink
Check unimacro feb24 (#49)
Browse files Browse the repository at this point in the history
* checking getTopOrChild function...
* fixing, at lasts, switch on a unimacro grammar, doing a reload (by the loader), with the force option.
* _general.py fixed several dgndictation things (also in nsformat.py of natlinkcore)
* brought win32clipboard under try finally
* tidy up _general
* work in progress _folders, getting natlinktimer again at work...
* working on the _folders grammar option and checking automatic tracking of recent folders and files and subfolders
* effort to diminish the errors when an ini file is invalid...
* working on getActiveFolder

Co-authored-by: Doug Ransom <doug.ransom@gmail.com>
  • Loading branch information
quintijn and dougransom authored Mar 13, 2024
1 parent c98b32c commit c38d3c9
Show file tree
Hide file tree
Showing 23 changed files with 1,064 additions and 1,496 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ __pycache__/
/src/unimacro/grammar.bin
README.html
/src/unimacro/UnimacroGrammars/rememberdialog.py
/tests/rememberdialog.py
9 changes: 7 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "flit_core.buildapi"
name = "unimacro"
authors = [{name = "Quintijn Hoogenboom (maintainer)", email = "q.hoogenboom@antenna.nl"}]
dynamic = ["version", "description"]
requires-python = ">=3.9"
requires-python = ">=3.10"
readme = "README.md"


Expand Down Expand Up @@ -35,11 +35,16 @@ test = [
"pytest >=7.1.2","flake8"
]
dev = [
"pyenvutils","entry-point-inspector"
"pyenvutils","entry-point-inspector","build"
]
[project.entry-points."natlink.grammars"]
unimacro_builtins = "unimacro.UnimacroGrammars:locateme"

[project.entry-points."dt.loggers"]
unimacro ="unimacro:logname"
control="unimacro:control_logger_name"
folders="unimacro:folders_logger_name"

[tool.pytest.ini_options]
minversion = "7.1.2"
addopts = "--capture=tee-sys "
Expand Down
4 changes: 2 additions & 2 deletions src/unimacro/OtherUnimacroGrammars/_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ def unload():
# here code to interactive run this module
natlink.natConnect()
try:
thisGrammar = ThisGrammar()
thisGrammar.startInifile(modName = '_latex')
thisGrammar = ThisGrammar(inifile_stem='_latex')
thisGrammar.startInifile()
thisGrammar.initialize()
Words = ['add', 'option', 'draft']
FR = {}
Expand Down
19 changes: 11 additions & 8 deletions src/unimacro/UnimacroGrammars/_brackets.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ def rule_brackets(self, words):
newpleft = pList[0]
newpright = pList[1]
else:
lenph = int(len(p)/2)
lenph = len(p)//2
newpleft, newpright = p[:lenph], p[lenph:]
# make more brackets together, from outer to inner:
self.pleft = self.pleft + newpleft
self.pright = newpright + self.pright
#print 'pleft: "%s", pright: "%s"'% (repr(self.pleft), repr(self.pright))
# print(f'result rule_brackets: |{self.pleft}|, pright: |{self.pright}|')

def subrule_before(self, words):
"(here|between|empty)+"
Expand All @@ -113,8 +113,11 @@ def gotResults(self, words, fullResults):
text = ""

if self.here:
print('do a left buttonClick')
unimacroutils.buttonClick('left', 1)
print('do a "visibleWait')
unimacroutils.visibleWait()
print('after a visibleWait')

leftText = rightText = leftTextDict = rightTextDict = ""
if text:
Expand All @@ -134,13 +137,13 @@ def gotResults(self, words, fullResults):
if lSpacing:
keystroke(lSpacing)

action(self.pleft)
keystroke(self.pleft)
unimacroutils.visibleWait()
if text:
#print 'text: |%s|'% repr(text)
keystroke(text)
unimacroutils.visibleWait()
action(self.pright)
keystroke(self.pright)
unimacroutils.visibleWait()

if rSpacing:
Expand Down Expand Up @@ -199,9 +202,9 @@ def stripFromBothSides(text):
text = text.rstrip()
return text, leftText, rightText

# standard stuff Joel (adapted for possible empty gramSpec, QH, unimacro)
# standard stuff Joel (adapted in course of time, QH)
def unload():
#pylint:disable=W0603
#pylint:disable=W0603, E0601
global bracketsGrammar
if bracketsGrammar:
bracketsGrammar.unload()
Expand All @@ -211,8 +214,8 @@ def unload():
if __name__ == "__main__":
natlink.natConnect()
try:
bracketsGrammar = BracketsGrammar()
bracketsGrammar.startInifile(modName = '_brackets')
bracketsGrammar = BracketsGrammar(inifile_stem='_brackets')
bracketsGrammar.startInifile()
bracketsGrammar.initialize()
finally:
natlink.natDisconnect()
Expand Down
39 changes: 27 additions & 12 deletions src/unimacro/UnimacroGrammars/_clickbyvoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@
#
# the lists {pagecommands} and {tabcommands} in the inifile (edit chrome hah)
#
#pylint:disable=C0209

"""
This commands grammar allows clicking by voice
It is a global grammar, that is activated as soon as one of the chromium browsers is
in the foreground
"""
#pylint:disable=

import natlink
from unimacro import natlinkutilsbj as natbj
from dtactions.unimacro import unimacroutils
from dtactions.unimacro.unimacroactions import doAction as action
Expand All @@ -53,7 +54,7 @@ class ThisGrammar(ancestor):

gramSpec = """
<shownumbers> exported = ((show) (numbers) [{additionalonoroff}]+) | ((numbers) {additionalonoroff}+) ;
<hidenumbers> exported = (hide) (numbers) [after {n1-20}];
<hidenumbers> exported = (hide) (numbers);
<picknumber> exported = (pick) <integer> [{navigateoptions}];
# is already in _tasks grammar:
Expand All @@ -67,6 +68,7 @@ class ThisGrammar(ancestor):
(page (back|forward) [{n1-20}]) |
page {pagecommands} |
(next|previous) page {pagecommands};
#and the numbers grammar (0,...,999 or chain of digits):
"""+numberGram

Expand Down Expand Up @@ -155,17 +157,15 @@ def gotResults_shownumbers(self, words, fullResults):
self.showNumbers = showNumbers
self.getInputcontrol()
self.doOption(showNumbers)
print('clickbyvoice, before finishInputControl')
self.finishInputControl()

print('clickbyvoice, after finishInputControl')


def gotResults_hidenumbers(self, words, fullResults):
"""hide the numbers
"""
wordFound, _position = self.hasCommon(words, "after", withIndex=True)
if wordFound:
print("setting timer later")

self.getInputcontrol()
self.doOption(self.hideNumbers)
self.finishInputControl()
Expand Down Expand Up @@ -330,11 +330,26 @@ def fillInstanceVariables(self):


# standard stuff Joel (adapted for possible empty gramSpec, QH, unimacro)
thisGrammar = ThisGrammar()
if thisGrammar.gramSpec:
if __name__ == "__main__":
## interactive use, for debugging:
with natlink.natConnect():
try:
thisGrammar = ThisGrammar(inifile_stem="_clickbyvoice")
# thisGrammar.startInifile()
thisGrammar.initialize()
print('clickbyvoice, before finishInputControl')
thisGrammar.finishInputControl()
print('clickbyvoice, after finishInputControl')



finally:
thisGrammar.unload()
elif __name__.find('.') == -1:
# standard startup when Dragon starts:
thisGrammar = ThisGrammar()
thisGrammar.initialize()
else:
thisGrammar = None


def unload():
#pylint:disable=W0603
Expand Down
151 changes: 151 additions & 0 deletions src/unimacro/UnimacroGrammars/_folders fillinstancevariables.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
fillinstancevariables old:
def fillInstanceVariables(self):
"""fills the necessary instance variables
take the lists of folders, virtualdrives (optional) and remotedrives (optional).

"""
#pylint:disable=R0914
self.useOtherExplorer = self.ini.get('general', 'use other explorer')
if self.useOtherExplorer:
if os.path.isfile(self.useOtherExplorer):
print('_folders, use as default explorer: "%s"'% self.useOtherExplorer)
else:
print('_folders, variable "use other explorer" set to: "%s" (use data from "actions.ini")'% self.useOtherExplorer)

## callback time in seconds:
interval = self.ini.getFloat('general', 'track folders interval')
if interval:
self.trackFoldersInterval = int(interval*1000) # give in seconds
else:
self.trackFoldersInterval = 4000 # default 4 seconds

self.recentfoldersDict = {}
inipath = self.ini.getFilename()
if inipath.endswith('.ini'):
_changingDataIniPath = inipath.replace(".ini", "changingdata.pickle")
self.pickleChangingData = inipath.replace(".ini", "changingdata.pickle")
else:
self.pickleChangingData = ""

## automatic tracking of recent folders :
self.trackFoldersHistory = self.ini.getInt('general', 'track folders history')
if self.trackFoldersHistory:
if self.pickleChangingData:
self.recentfoldersDict = self.loadRecentFoldersDict()
if self.recentfoldersDict:
print("recentfolders, set %s keys from _folderschangingdata.pickle"% len(self.recentfoldersDict))
else:
print("recentfolder, no previous recentfolders cached in _folderschangingdata.pickle")

self.doTrackFoldersHistory = True # can be started or stopped with command
# recent [folders] START or recent [folders] STOP
intervalSeconds = self.trackFoldersInterval/1000
print('maintain a list of %s recent folders (Explorer or File Dialog) at every utterance and every %s seconds'% (self.trackFoldersHistory, intervalSeconds))
natlinktimer.setTimerCallback(self.catchTimerRecentFolders, self.trackFoldersInterval) # every 5 seconds
else:
self.doTrackFoldersHistory = False
if self.doTrackFoldersHistory:
rfList = self.ini.get('recentfolders')
for key in rfList:
value = self.ini.get('recentfolders', key)
self.recentfoldersDict[key] = value
# extract special variables from ini file:
self.virtualDriveDict = {}
wantedVirtualDriveList = self.ini.get('virtualdrives')
if wantedVirtualDriveList:
self.resolveVirtualDrives(wantedVirtualDriveList)
self.virtualDriveList = list(self.virtualDriveDict.keys())
# print '_folders, virtual drives from dict: %s'% repr(self.virtualDriveDict)
# print '_folders, virtual drives from list: %s'% ', '.join(self.virtualDriveList)

# checking the passes of all folders:
foldersList = self.ini.get('folders')
self.foldersDict = {}
for f in foldersList:
raw_folder = self.ini.get('folders', f)
folder = self.substituteFolder(raw_folder)
if not os.path.isdir(folder):
print(f'warning _folders, folder "{f}" does not exist: "{folder}"')
# self.ini.delete('folders', f)
# self.ini.set('obsolete folders', f, folder)
continue
self.foldersDict[f] = folder

# track virtual drives if in ini file:
self.trackFolders = self.ini.getList('general', 'track folders virtualdrives')
self.trackFiles = self.ini.getList('general', 'track files virtualdrives')
# below this threshold, the getting of subfolders and files in a directory is not printed in the messages window
self.notifyThresholdMilliseconds = self.ini.getInt("general", "notify threshold milliseconds", 50)
# print("_folders, notify threshold milliseconds: %s"% self.notifyThresholdMilliseconds)
# in order to accept .py but it should be (for fnmatch) *.py etc.:
self.acceptFileExtensions = self.ini.getList('general', 'track file extensions')
self.ignoreFilePatterns = self.ini.getList('general', 'ignore file patterns')

# these are for automatic tracking the current folder:
self.trackAutoFolders = self.ini.getBool('general', 'automatic track folders')
self.trackAutoFiles = self.ini.getBool('general', 'automatic track files')

self.foldersSections = ['folders']
# track folders:
for trf in self.trackFolders:
if not trf:
continue
trf2 = self.substituteFolder(trf)
#print 'input: %s, output: %s'% (trf, trf2)
if not os.path.isdir(trf2):
print('warning, no valid folder associated with: %s (%s) (skip for track virtualdrives)'% (trf, trf2))
continue
#else:
# print 'valid folder for tracking: %s (%s)'% (trf, trf2)
subf = [f for f in os.listdir(trf2) if os.path.isdir(os.path.join(trf2, f))]
self.trackFoldersSection = 'folders %s'% trf
self.ini.delete(self.trackFoldersSection) # not in inifile
self.foldersSections.append(self.trackFoldersSection)
self.acceptVirtualDrivesFolder(trf, trf2) # without f, take virtualdrive itself...
for f in subf:
## if no strange signs in folder name:
self.acceptVirtualDrivesFolder(trf, trf2, f)
#self.cleanupIniFoldersSection(self.trackFoldersSection, trf)
#self.removeObsoleteIniSections(prefix="folders ", validPostfixes=self.trackFolders)
self.removeObsoleteIniSections(prefix="folders ", validPostfixes=[]) # do not keep in ini file

# do the files:
self.filesDict = {}
self.trackFiles = self.ini.getList('general', 'track files virtualdrives')
# in order to accept .py but it should be (for fnmatch) *.py etc.:
self.acceptFileExtensions = self.ini.getList('general', 'track file extensions')
self.ignoreFilePatterns = self.ini.getList('general', 'ignore file patterns')
self.filesSections = ['files']
# from section files (manual):
filesList = self.ini.get('files')
if filesList:
for f in filesList[:]:
filename = self.substituteFilename(self.ini.get('files', f))
if not os.path.isfile(filename):
print(f'warning _folders, file "{f}" does not exist: "{filename}"')
# self.ini.delete('files', f)
# self.ini.set('obsolete files', f, filename)
continue
self.filesDict[f] = filename

for trf in self.trackFiles:
if not trf:
continue
trf2 = self.substituteFolder(trf)
if not os.path.isdir(trf2):
print('warning, no valid folder associated with: %s (%s) (skip for track files)'% (trf, trf2))
continue
filesList = [f for f in os.listdir(trf2) if os.path.isfile(os.path.join(trf2, f))]
self.trackFilesSection = 'files %s'% trf
self.ini.delete(self.trackFoldersSection) # not in inifile
self.filesSections.append(self.trackFilesSection)
for f in filesList:
self.acceptFileInFilesDict(trf, trf2, f)
#self.cleanupIniFilesSection(self.trackFilesSection, trf)
self.removeObsoleteIniSections(prefix="files ", validPostfixes=[])
#self.removeObsoleteIniSections(prefix="files ", validPostfixes=self.trackFiles) # not in inifile any more

# self.childBehavesLikeTop = self.ini.getDict('general', 'child behaves like top')
# self.topBehavesLikeChild = self.ini.getDict('general', 'top behaves like child')
# save changes if there were any:
self.ini.writeIfChanged()
Loading

0 comments on commit c38d3c9

Please sign in to comment.