/----------------------------------------------------------\ | XyPy: Python Extensions for XyWrite | | C.L. Distefano -- v0.99 rev. 2014-10-08 | | For XyWrite 4 (DOS) + XyWWWeb Jumbo U2 + Python 3.x | | Download: <http://users.datarealm.com/xywwweb/XYPY.ZIP> | \----------------------------------------------------------/ Overview ======== XyPy proposes a framework for using Python as a second scripting language for XyWrite, in conjunction with XyWrite's built-in Programming Language, XPL. Python is a general-purpose programming language used in a wide variety of applications. It can be downloaded for free at <www.python.org>. Python scripts are text files, and can be created and edited in XyWrite. Visually, Python and XPL are a study in contrast. Python looks more or less like plain English; its syntax and programming conventions place high value on the readability of code. XPL, as most XyWriters know, is dense and often inscrutable. Yet both are high-level, interpreted languages, rich in possibilities. XyPy's premise is that these idioms can be combined to extend XyWrite in interesting and useful ways. For example, you can: * Use XyWrite as a Python shell, to launch free-standing Python scripts from the XyWrite command line (CMline); * Embed a Python script within an XPL program (XPyL), using Python to extend XPL's baseline capabilities; * Write XyWrite macros/programs in Python, as an alternative to XPL; or * Any combination of the above. A suite of XPL routines and a Python module (xy.py) supply the "glue" that makes it possible. XyPy also includes tools to enhance XyWrite's usefulness as a Python editor. Files included in XYPY.ZIP ========================== XYPY.NOW ... quick-start instructions XYPY.TXT ... this documentation file XYPY.FRM ... U2 frames to be added to your U2 file (details below) XYPY.TPL ... template file for xy.py, used by U2 frame MAKEXYPY to construct the actual xy.py module (details below) General Information =================== XyPy uses Python Version 3. An introductory Python 3 tutorial can be found at <http://docs.python.org/3/tutorial/introduction.html>. Full documentation is available at <http://docs.python.org/3/>. XyPy presumes familiarity with XyWrite 4 for DOS, XPL, and the XyWWWeb Jumbo U2 customization file. Visit <http://users.datarealm.com/xywwweb/> for information and downloads. To gain familiarity with the XyWrite Programming Language (XPL), peruse the XyWrite Programming Language User's Guide: <http://users.datarealm.com/xywwweb/XPL.PDF>. If you're new to XyWrite and want to learn more about this classic DOS word-processor, subscribe to the XyWrite Mailing List <http://www.freelists.org/list/xywrite>. You can also browse the list archives at <http://www.freelists.org/archive/xywrite/>. For software history buffs, the archives of predecessor XyWrite discussion lists, going back to 1991, are available at XySearch <http://www.holmgren.org/Xy/Search>. XyPy Setup ========== Step 0 ------ Install Python 3 (as of this writing the latest standard release is v3.4.2, dated 8 October 2014). Download at: <http://www.python.org/download/>. During installation, at the Customize Python 3.x screen, be sure to choose the option to "Add python.exe to search path". If you run XyWrite in a virtual machine, make sure that python.exe is located on a drive that is accessible to XyWrite. Step 1 ------ Unzip XYPY.ZIP into the directory that contains EDITOR.EXE. Step 2 ------ MErge XYPY.FRM into your U2 file (near top of file). Be sure to delete any earlier versions of these frames. Issue LOADHELP<Helpkey> to reLOAD U2. Step 3 (Critical -- Do NOT Skip!) ----------------------------------------------------- Issue MAKEXYPY<Helpkey> to install the xy.py module. When you run MAKEXYPY, it uses XYPY.TPL to create a module named "xy.py", customized to reflect the location of EDITOR.EXE on your system. Xy.py is saved to a Python subdirectory named ".\Lib\site-packages\xypy". (If subdirectory "xypy" does not exist in site-packages, MAKEXYPY creates it.) Any existing copy of xy.py in that subdirectory is overwritten without warning. New as of 8/11/13: MAKEXYPY automatically configures variable Python_EXE in XYWWWEB.REG. This should work if python.exe is in the Path (see Step 0 above). If you get an error message, add python.exe to the Path and try again, or configure the variable manually. Do so by adding the following stanza to XYWWWEB.REG, editing the path to python.exe as necessary: ; [Python] Python_EXE=d:\Python34\python.exe ; New as of 11/30/13: Existing users of XyPy v0.81 or later can update XyPy to subsequent versions simply by UNZIPping the latest version of XYPY.ZIP into Editor's directory (be sure to OVERWRITE all existing files!) and then issuing: UPDATEXYPY<Helpkey> You're ready to roll. XyPy Core Routines (U2 Frames) ============================== These routines have been tested in XyWrite 4 (DOS) running under Windows XP. They may or may not work (probably not) in Nota Bene for Windows (the actively-developed successor to XyWrite) or in the now rare XyWrite for Windows. Frame PY, PYI, PYW, PY/ ----------------------- Execute Python code in the current XyWrite window -- a must-have for writing and testing Python code in XyWrite! Works on a DeFined (selected) block of code or, if nothing is DeFined, the entire file. The file need not have the ".py" extension. Arguments can be passed to the Python routine by adding them on the CMline; (the Python routine must, of course, be coded to accept arguments). -- Usage (with DeFined Python code or script file in current window): PY [arg(s)]<Helpkey> Frame PY "shells" to the Python interpreter and executes the subject code (file or DeFined block). The session remains open after execution, so that output or error messages can be viewed. -- PYI [args]<Helpkey> is same as PY except runs script with python.exe -i option, leaving the Python interpreter active after the script executes -- PYW<Helpkey> takes output from *DeFined* Python code and displays this output in a new Untitled XyWrite window. The input code must adhere to the usage requirements for XPyL embedded code (see frame XPyL, below). To see how it works, DeFine the following block of Python code and issue PYW<Helpkey>: # start import xy xy.outok() xy.xywrite(b'Hello, world!') # Note bytes, not text string! xy.outok(1) # end # same as above, with text string instead of bytes # note text usage for func xy.xywrite() import xy xy.outok() xy.xywrite('Hello, world!', xy.OUTFN, 'wt') # text string usage xy.outok(1) # end -- PY/<Helpkey> (note forward slash in framename) takes you directly to the Python interpreter command prompt Note on Using XyWrite to Edit Python Scripts ............................................ The Ascii-26 end_of_file character that XyWrite appends to saved files is sometimes interpreted by Python as an illegal instruction, causing some otherwise error-free scripts to fail. Annoying, yes, but there's an easy workaround: just add a short #comment at the bottom of the script; do NOT end the comment with a CrLf a/k/a newline! For example: # approaching end of script... print('Goodbye!') # <== final instruction # end<== script ends at the end of the word "end"; do not add a newline! Frame PY|PYI|PY/ appends the closing comment automatically when operating on a DeFined block. You must, however, insert the closing comment manually at the end of any .PY script file launched with frame PY. - - - Frame IDLE ---------- Open IDLE GUI Usage 1 (open Python shell in IDLE): IDLE<Helpkey> Usage 2 (edit file in IDLE): IDLE [d:\path\filename_to_edit]<Helpkey> Usage 3 (edit file in current XyWrite window in IDLE): IDLE/<Helpkey> <== Note trailing forward slash (/) in framename! Frame PYTHON ------------ Launch an external Python script from within an XPL program. -- Usage (in XPL code): <SV50,[d:\path\scriptname.py] [args]>JM 2.python[/K][/X][/I]Q2 ;*; -- Optional framename switches /K and /X are XyWrite's DOS command switches. By default, the DOS switches used to launch the script are DOS/NV/Z /C ... Specifying /K in the framename overrides the default /C (keeps the DOS window open after the script finishes, instead of closing it). Specifying /X adds that switch to the DOS command to freeze the XyWrite display while the Python script executes. Optional framename switch /I runs script in Python's interactive mode (python.exe -i), leaving the interpreter open after the script executes Frames PYENC and PYDEC ---------------------- Encode|Decode file or DeFined block to|from Python hexadecimal byte code -- Usage (with input file or DeFined block in current window): PYENC<Helpkey> <== Encode to bytes Encodes, e.g., sa to b'\xff\x82\xabsa\xff\x82\x7f' -- PYDEC<Helpkey> <== Decode from bytes (b'...') Decodes, e.g., b'\xff\x82\xabsa\xff\x82\x7f' to sa Frame TIMEDF ------------ Time a DeFined block of Python code -- Usage (with code_to_time DeFined): TIMEDF [setup[, number[, repeat]]]<Helpkey> -- Omit quotes around setup (supplied by frame TIMEDF) Defaults: setup='', number=1000, repeat=10 TIMEDF uses timeit.repeat and reports *minimum* value returned For further information, see Python 3 documentation for the timeit module: http://docs.python.org/3/library/timeit.html?highlight=timeit Frame XPyL ---------- Run Python code embedded in an XPL program; (Python code is executed inline at runtime) -- Usage (XPL): <SV50,[text of Python script]>;*; JM 2.XyPL[/K][/X][//][/50][/CM|/DG|/PR|/ME|/W]Q2 ;*; -- Framename switches: /K and /X are DOS command switches (default = DOS/NV/Z /C ...). /K keeps the DOS session open after the Python script ends (useful for debugging). /X freezes the XyWrite display while the Python script runs. /50, /CM, /PR, /ME, /W determine how output from the Python script is handled in XyWrite: /50 directs output to Save/Get 50 /CM puts output on the CMline /DG displays output in DialoG box (good for single-screen output) /PR displays output as a PRompt (via S/G 50; i.e., "/PR" implies "/50") /ME merges output into the current file at the cursor location /W displays output in a new XyWrite Untitled window Use switch "//" when no output is expected from embedded Python code. It can be merged with /X or /K, thus: 2.XPyL//X - Exit codes (S/G 61 out): -1: Python not installed or missing Reg var Python_EXE 0: Python routine not launched 1: No output 2: Output received XPyL: Python Coding Conventions ------------------------------- Embed your Python code in Save/Get 50, immediately before the call to JM 2.XPyL[/switches]Q2 (see frame XPyL usage above). Use single-quotes ('') for Python quoted strings, to avoid confusion with XPL's required double-quotes. If your Python script returns output to XyWrite, or if it uses any of XyPy's custom functions (details below), the first line of your embedded code (in S/G 50) should import the XyPy module (xy.py): import xy If the script is expected to return output to XyWrite, the next line of the embedded script should be: xy.outok(0) # or simply xy.outok() This sets a flag file ("xpyldata.ok", located in the directory that contains EDITOR.EXE) to inform Editor that output is pending. Output may be written to a file using XyPy's custom variable xy.OUTFN, which points to a file called "xpyldata.out" located in Editor's directory. If the output to be imported into XyWrite is a formatted document or XPL code, don't attempt text decoding in Python; instead, use binary data (Python byte strings), and let XyWrite do the decoding for you. (Frame PYENC, described above, is handy for converting text and XPL into Python byte strings.) After the line in your Python script that writes output to a file, add the following line to remove the output flag file (usually at or near the end of the embedded script): xy.outok(1) Thus, a basic template for writing binary output is as follows: import xy xy.outok() spam = b'Better than ham!' # Note byte string, not string! with open(xy.OUTFN, 'wb') as f: f.write(spam) xy.outok(1) Or, more compactly, using xy.py's xywrite function to write the output file: import xy xy.outok() spam = b'Better than ham!' xy.xywrite(spam) xy.outok(1) As an alternative to importing the entire xy.py module, you can import only the xy.py objects required by your embedded code. The imported object names become part of the namespace of your routine -- meaning, in practical terms, that you must (1) omit the "xy." prefix from variable and function names, and (2) guard against name clashes with variables and other object names used in your routine. Using individual object imports, we can rewrite the previous example thus: from xy import outok, xywrite outok() spam = b'Better than ham!' xywrite(spam) outok(1) Be aware of XyWrite's programming memory limitations when stuffing Python code into Save/Get 50. For longer scripts, use pithy variable names and minimal indentation (e.g., one blank space per indent) to conserve Save/Get memory. XyPy includes several U2 routines as working examples of "XPyL". See "Demo Frames", below. Using Python to Manufacture XPL ------------------------------- Sometimes the data produced by your embedded Python script will be XPL code, to be run when control is handed back to XyWrite, or perhaps a formatted document, to be saved to disk and CAlled in XyWrite. To manufacture XPL or XyWrite formatted text in Python, you will need to use Python byte strings. The XyPy module, xy.py, includes functions that produce byte strings corresponding to XyWrite embedded commands, functions, SEarch wildcards, printable 3-byte characters, and XyWrite's extended character set (Speedo characters). Some of these functions can be seen in action in the two numbered demos below; read them in XyWrite's eXPanded view. Demo 1 uses a "for" loop and xyfunc() to assign byte codes for functions BC (Blank the Command line) and GT (Go to Text, i.e., move cursor to text area) to Python variables of the same name. It then manufactures a snippet of XPL code that (for demo purposes) opens an Untitled window in eXPanded view, writes some dummy text, waits 5 seconds, then ABorts the window. In Demo 1, the constructed code is *displayed* in an Untitled XyWrite window, using frame XPyL/W (cf. Demo 2, below); manually ABort the window when you're done viewing the code. To run this demo, DeFine the entire block of code and command RUNCODE<Helpkey>, or simply command DEMO1<Helpkey>: ;*; Demo 1 (Python-made XPL code, displayed) SV50, from xy import OUTFN, outok, xywrite, xyfunc, xycm, fBX outok() for varname in 'BC', 'GT': exec(varname + ' = xyfunc(varname)') xywrite(fBX('es 1') + xycm(b'SX01,\xaeVA$NW\xaf') + fBX('d nw=3', 'ne/100') + BC + b'This Untitled window will ABort in 5 seconds...' + GT + b'[Nothing here in the text window]' + xycm('PRWaiting...') + fBX('p 5', 'ab') + fBX(b'd nw=\xaePV01\xaf') + BC + GT + xycm('PRDone', 'EX')) outok(1) 2.XPyL/X/WPRABort window after viewingEX ;*; end Demo 1 It works! Demo 2 manufactures the same code, but this time instead of displaying it, it *executes* the XPL upon returning to XyWrite. This is accomplished by saving the manufactured code to Save/Get 50 (using frame XPyL's /50 switch), and then executing it with <PV50>. To run this demo, DeFine the entire block of code and command RUNCODE<Helpkey>, or command DEMO2<Helpkey>: ;*; Demo 2 (Python-made XPL code, executed) SV50, from xy import OUTFN, outok, xywrite, xyfunc, xycm, fBX outok() for varname in 'BC', 'GT': exec(varname + ' = xyfunc(varname)') xywrite(fBX('es 1') + xycm(b'SX01,\xaeVA$NW\xaf') + fBX('d nw=3', 'ne/100') + BC + b'This Untitled window will ABort in 5 seconds...' + GT + b'[Nothing here in the text window]' + xycm('PRWaiting...') + fBX('p 5', 'ab') + fBX(b'd nw=\xaePV01\xaf') + BC + GT + xycm('PRDone', 'EX')) outok(1) 2.XPyL/X/50PV50PRDone!EX ;*; end Demo 2 And the manufactured snippet of XPL works, too. QED. Note that by using PYENC to byte-encode the output from Demo 1, you can rewrite the XPL code as raw bytes, as follows: ;*; Demo 1a (Python-made XPL code, displayed) SV50, from xy import outok, xywrite outok() xywrite(b'\xff\x82\xabes 1\xff\x82\x7f\xaeSX01,\xaeVA$NW\xaf\xaf\xff\x82\xabd nw=3\xff\x82\x7f\xff\x82\xabne/100\xff\x82\x7f\xff\x81\x1fThis Untitled window will ABort in 5 seconds...\xff\x80}[Nothing here in the text window]\xaePRWaiting...\xaf\xff\x82\xabp 5\xff\x82\x7f\xff\x82\xabab\xff\x82\x7f\xff\x82\xabdnw=\xaePV01\xaf\xff\x82\x7f\xff\x81\x1f\xff\x80}\xaePRDone\xaf\xaeEX\xaf') outok(1) 2.XPyL/X/WPRABort window after viewingEX ;*; end Demo 1a This works the same as the original Demo 1, and will run slightly faster. (DeFine the demo code block and command RUNCODE<Helpkey> to run it; or command DEMO1A<Helpkey>.) The trade-off is that the raw byte code is less identifiably XPL-like. Demo Frames =========== XyPy includes U2 frames that show XPyL in action. Some of these routines serve mainly as proof-of-concept; others are actually useful. Feel free to suggest or write real-world applications of your own. The included frames are: BCONV number, base_in, base_out<Helpkey> Base-to-base conversion for base 2 - 36 Output on PRompt line and in S/G 50 WCPY [d:\path\filename]<Helpkey> Performs word count on current file, specified file, or DeFined block LISTWORDS [d:\path\filename]<Helpkey> Compiles a sorted list of all unique words in current or specified file; also reports average word length LISTCP 'string'<Helpkey> [single quotes required!] List all (case-sensitive) occurrences of 'string' in current file (CharPos and snippet of text containing 'string'). LSTCP 'string'<Helpkey> [single quotes required!] List bare CharPos of all (case-sensitive) occurrences of 'string' in current file (faster than LISTCP) JMPCP 'string'<Helpkey> [single quotes required!] JuMP to CharPos of each (case-sensitive) occurrence of 'string' in current file (simulates native SEA command). There is a 500-hit maximum to avoid out-of-memory anomalies in XyWrite FUNCSPY<Helpkey> Use Python to construct and list all XyWrite 3-byte functions in an Untitled window WILDPY<Helpkey> Use Python to construct and list a full set of 3-byte reverse-video Ascii chars (a subset of which constitutes XyWrite's SEarch wildcards) in an Untitled window 3BYTERSPY<Helpkey> Use Python to construct and list a full set of XyWrite's printable 3-byte character set (including characters that cannot be displayed or printed in XyWrite in 1-byte form) SPEEDOSPY<Helpkey> Use Python to construct and list a full set of XyWrite's Speedo character set GOOPY [search terms]<Helpkey> Google search GETM<Helpkey> Read your e-mail messages in a XyWrite Untitled window Note 1: You will be prompted for your POP server name and e-mail address. Alternatively, this information can be supplied by setting user variables in XYWWWEB.REG, like this: ; Email_Address=myname@myISP.com POP_Server=pop.myISP.com ; Note 2: You will be prompted for a password. Exercise caution when entering it as the password will be displayed! PY3 [search terms]<Helpkey> Search Python 3 documentation via Google - - - UH-HUH: Unlimited Hint These companion routines extend Robert Holmgren's command Stack utility by enabling unlimited command archiving and retrieval. Stack's command history can hold about 200 commands in memory. That sounds like a lot, but in an active editing session useful commands are quickly pushed down and out of the stack. Although Stack has a facility for saving the command history to a file for later retrieval, the number of commands in any such file is still subject to the (approximately) 200-command limit. UH-HUH overcomes this limitation, enabling *all* commands to be archived permanently to disk, to be retrieved at any time by Stack's trademark method of providing a "hint", or substring, of the desired command. (UH stands for Unlimited Hint, HUH for Have Unlimited Hint.) The catch is that you *must* establish frame HUH in an XPL routine that you run *every time you quit XyWrite*. (The Jumbo U2 includes such a routine: FINITO). Do this by adding the following line to FINITO or your own routine: 2.huh;*; New (7/28/13): XyPy now includes frame FINITO so modified. (If Python or Stack is not detected, HUH backs off quietly.) Alternatively, you can assign HUH to a key, along with the QUIT command, in the KBD file: nn=NOJM2,.,h,u,h,Q2BXq,u,i,t,/,n,v,Q2 HUH can also be assigned to another key to allow easy updating of STACKALL.SAV during editing sessions. Alternatively, you can manually issue HUH<Helpkey> after Stacking a key command to ensure that it is permanently archived. Every time you run HUH, the command stack is merged into STACKALL.SAV, located in Editor's directory. STACKALL.SAV is a sorted listing of archived commands (duplicate commands are purged). To retrieve commands from STACKALL.SAV, use frame UH to issue a (case-INsensitive) hint, or fragment of the desired command; for example: UH .txt<Helpkey> [list all commands containing string '.txt'] A sorted list of commands containing the hint is opened in a new XyWrite window. To pop any command to the CMline, place the cursor on the desired command and hit <Helpkey>. Once popped and reSTACKed, archived commands re-enter the active command Stack and become accessible by scrolling through the Stack (Up|Down arrow keys or frame STACKBOX) or normal Stack hinting. New (7/29/13): UH now works on non-Python setups; STACKALL.SAV must be present in Editor's directory. Python is still required to run HUH, which creates and updates STACKALL.SAV, but you can now enjoy UH on Python-less systems simply by copying your STACKALL.SAV to Editor's directory. New (10/16/13): HUH now also works on non-Python setups, via a new frame HUHXPL, which is called by HUH if a Python installation is not detected. As a result, a STACKALL.SAV created on a Python-enabled Xy setup can be copied to a non-Python XyWrite directory and used interchangeably on the two setups. See also frame ADDSTACKALL (immediately below), which enables STACKALL.SAV archives created on different XyWrite setups to be merged into a single STACKALL.SAV, useable on all setups. New (10/27/13): Frame ADDSTACKALL enables merging a separate STACKALL.SAV-type file into STACKALL.SAV. Command-line usage is: ADDSTACKALL [d:\path\filename]<Helpkey> where "d:\path\filename" is the file to be merged into STACKALL.SAV. The file-to-be-merged must be formatted either one command to a line (like STACKALL.SAV) or Ascii-190[command]Ascii-190[command]Ascii-190 ..., like the native command stack created by STACK.PM (located in Save/Get 623). Use ADDSTACKALL to merge STACKALL.SAV files from multiple XyWrite setups into a single STACKALL.SAV. I use ADDSTACKALL to keep my home and work copies of STACKALL.SAV in sync. New (10/30/13): STACKALL.SAV now lists each command on a separate line (ending with CrLf) instead of using STACK.PM's native Ascii-190 command separator. The new format makes it easier to browse and manually add commands to, or delete commands from, STACKALL.SAV. Also new: UH<Helpkey>, with no hint/argument, CAlls STACKALL.SAV for viewing or editing. New (11/01/13, 11/11/13): New frame ADDCM allows the current CMline or a DeFined block to be added to the STACKALL.SAV command archive whether or not STACK.PM is not installed. ADDCM must be assigned to a key of your choosing in the KBD file, with: nn=NOJM(,2,.,a,d,d,C,M,) Hit your dedicated ADDCM key to add the current CMline to STACKALL.SAV. (Stack users can use ADDCM as well.) ADDCM opens up the possibilities of UH-HUH unlimited hinting to all Xy4 users, whether or not STACK.PM is installed -- and whether or not Python is installed as well. New (11/21/13): The pure-XPL version of UH-HUH now uses Christian Maas's CMSORT.EXE utility (freeware) for Windows to sort the command archive -- if and only if CMSORT.EXE is present in Editor's directory (otherwise XyWrite's native SORT command is still used). CMSORT.EXE overcomes out- of-memory anomalies that sometimes appear when the native SORT command is used against longer files. If you are running the pure-XPL (non- Python) version of UH-HUH on your Win32 system, it is recommended that you download the CMSORT ZIP archive and unzip all files into the directory that contains EDITOR.EXE (only CMSORT.EXE is required, but the ZIP includes a helpful manual [PDF] and README file). For further information see: http://www.chmaas.handshake.de/delphi/freeware/cmsort/cmsort.htm (download link is at bottom of page) New (11/21/13): Added frame AHUH (Aleatory HUH), which runs frame HUH probabilistically (1 in 10|50|100 times; default = 1/100). Assign AHUH to one or more keys, or embed a call to AHUH in XPL routines, to ensure that the STACKALL.SAV command archive is regularly, yet unobtrusively, updated. For example, to assign AHUH to your SAve key: nn=NOJM(,2,.,a,h,u,h,),BX(,s,a,) UH-HUH really does provide unlimited hinting. The STACKALL.SAV archive can grow indefinitely, and may come to contain many hundreds or even thousands of commands. In my tests with a manufactured STACKALL.SAV archive with 130,000+ commands, UH instantaneously processed a hint that returned over 2,000 matching commands; a hint that returned more than 70,000 matching commands took just a couple of seconds to complete. HUH had no trouble removing duplicates from this 2 Meg archive, immediately reducing it to a 20KB file of about 1300 commands. UH-HUH, it works! UHDEL [string]<Helpkey> Delete all commands containing string from STACKALL.SAV command history archive file. Two (2) available windows required. UHDEL also works on non-Python Xy setups; STACKALL.SAV must be present in Editor's directory. - - - WEB [url]<Helpkey> - Open URL in the default browser. - URL can be specified on the CMline or DeFined in text. If nothing is DeFined and the cursor is in text, frame WEB tries to "lift" the URL (if any) under the cursor. If the URL does not specify a protocol, 'http://' is prepended. Frame WEB uses Python's webbrowser module to create a Xy CMline-Web interface in two (2) lines of XPyL code! -- WEB [alias]<Helpkey> [Alias] is a single-word abbreviation for a full URL. Set your aliases by adding lines to XYWWWEB.REG, thus: URL1=monty=http://pythonline.com/ URL2=cye=http://en.wikipedia.org/wiki/List_of_Curb_Your_Enthusiasm_episo des#Series_overview URL3=xyw=users.datarealm.com/xywwweb/ [etc.] Then, for example: WEB monty<Helpkey> opens <http://pythonline.com/> -- Automatic alias: Single-word URLs not in dictionary are rendered as www.URL.com. E.g.: WEB ebay<Helpkey> opens <http://www.ebay.com>. LOOKUP [YA][suffix] search_term(s)<Helpkey> Web lookup via U2 frame MDSOLBLinkSV50,YA2.HelpYA*MDNM YA__ framenames must be correctly configured in the XyWWWeb REGistry (XYWWWEB.U2). Command HELP YA<Helpkey> for further information. VERITAS [keyword(s)]<Helpkey> Wine|Liquor search via wine-searcher.com MONTYPY [number_of_doors [iterations]]<Helpkey> Demonstrates the Monty Hall Paradox, a famous probability brain-teaser. The classic statement of the problem is: `Suppose you're on a game show, and you're given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what's behind the doors, opens another door, say No. 3, which has a goat. He then says to you, "Do you want to pick door No. 2?" Is it to your advantage to switch your choice?' (See <http://en.wikipedia.org/wiki/Monty_Hall_problem>.) Frame MONTYPY helps you find (and understand) the answer by simulating 10,000 random repetitions of the game situation and reporting the number of times the car is behind the first door chosen versus the alternative door. MONTYPY further illustrates the problem more generally by allowing you to run the simulation with more than 3 doors and more (or fewer) than 10,000 repetitions. ZAPPY [d:\path\filename]<Helpkey> Zap Ascii-26 End-of-File character Works on current file, file specified on CMline, or filename under cursor in DIRectory listing (XPyL equivalent of U2 frame ZAP26) GSFPY[/50|/CM|/ME|/PR|/W] [Long_Filename]<Helpkey> GSFPY[/50|/CM|/ME|/PR|/W]<Helpkey> with [Long_Filename] DeFined SV50,Long_Filename2.gsfpy/50;*; S/G 50 in and out Returns Windows Short Filename; framename switch determines output mode /50 = S/G 50 out; /CM = put on CMline; /ME = MErge in text at cursor position; /W = put in new text Window; /PR = display on PRompt line (default) The XyPy Module =============== The XyPy module (xy.py) enables the following Python variables, which can be used in any XPyL routine or freestanding Python script: EDDIR = Directory containing EDITOR.EXE (without trailing slash) Note: EDDIR is set automatically by frame MAKEXYPY CMFN = EDDIR + '/cml.sav' # File containing CMline at runtime INFN = EDDIR + '/xpyldata.in' # File for input from XyWrite OUTFN = EDDIR + '/xpyldata.out' # File for output from Python script OKFN = EDDIR + '/xpyldata.ok' # Output ready flag file bLG = b'\xAE' # Byte code for 1-byte left guillemet bRG = b'\xAF' # Byte code for 1-byte right guillemet To gain access to these variables, you must import the module into your Python routine (see discussion of XPyL coding, above). Recall that Python module, function, and variable names are case- sensitive. In accordance with Python coding convention, some xy.py variable names are uppercase because their values are intended to be constants -- and should be treated as such by the user. If your script calls for these values to be changed, manipulate a *copy* of the variable's contents or assign a copy to a new variable; for example: NewOutFn = xy.OUTFN[:] # provided variable type supports indexing! Then manipulate the new variable. Note: Since xy.py imports the os module, scripts that import xy can access methods in os with xy.os.method_name(). E.g., xy.os.system('cls'). XyPy Custom Functions ===================== The xy.py module includes functions that provide a Python syntax for constructing XyWrite commands, control characters, and XPL code in Python. (Some of these functions are illustrated in the two XPyL demo examples above.) After importing xy.py, you can invoke any function with "xy.funcname(arg)" --- or simply "funcname(arg)" if the function has been imported with the "from xy import funcname" usage. The functions in xy.py are: xyread() -------- Read XyWrite input file (minus EOF) Usage: var = xyread(filename_in, mode) Default filename is 'xpyldata.in', in directory that contains EDITOR.EXE. Default mode is read binary ('rb'). Returns input file contents if read succeeds, else returns None. xywrite() --------- Write file for output to XyWrite var = xywrite(bytes_out, 'd:/path/filename_out', mode) Default filename is 'xpyldata.out', in directory that contains EDITOR.EXE. Default mode is write binary ('wb'). Returns 1 if write succeeds, else returns None. GetCMline() ----------- Fetch byte code representing the contents of the XyWrite command line (CMline) at runtime. The XPL portion of the routine must first save the CMline to file CML.SAV, located in Editor's directory. (xy.py global variable CMFN points to this filename.) The XyWWWeb U2 convention for U2 frames is to pass the CMline via Save/Get 50; hence the required code would look like this: ;*; SX01,IS50;*; Hand CMline to S/G 01 SX50,VA$ED2.GetPath;*; Save Editor's dir to S/G 50 sa %01,PV50\CML.SAV;*; Save 01 to CML.SAV in that dir ;*; Then, in the Python portion of your routine, you can save the CMline to a variable, thus: cmline = xy.GetCMline() # var cmline has the current command line xycm(*cm_in) ------------ Returns bytes for XyWrite embedded command(s) Note: cm_in must be all Ascii 32-127 text or else hex byte code Examples: >>> LMargin = xy.xycm('LM5DI') # same as: # LMargin = b'\xAELM5DI\xAF' >>> Margins = xy.xycm('LM5DI', 'RM75DI') # same as: # Margins = b'\xAELM5DI\xAF\xAELM75DI\xAF' fBX(*cm_in) ----------- Return bytes for "command [args]" for one or more commands Each command must be all Ascii 32-126 text or else hex byte code Examples: >>> xy.fBX('lm 5di') # Returns byte code for "lm 5di", i.e.: # b'\xFF\x82\xABlm 5di\xFF\x82\x7F' # >>> xy.fBX('lm 5di', 'rm 75di') # Returns byte code for "lm 5dirm 75di", i.e.: # b'\xFF\x82\xABlm 5di\xFF\x82\x7F\xFF\x82\xABrm 75di\xFF\x82\x7F' # # If command is not plain Ascii text (32-126), input bytes instead # E.g., instead of xy.fBX('se /th/'), use: # xy.fBX(b'se /\xFF\xC0\xB3\xFF\xC0\xCEth/') # Use frame PYENC to convert to hex byte code! xyfunc(*func_mnemonic) ---------------------- Return bytes for 3-byte function corresponding to one or more XyWrite 2-character function mnemonics Examples: Assign byte code for func 'BC' to Python variable BC: >>> BC = xy.xyfunc('BC') # same as: # BC = b'\xFF\x81\x01' Assign byte code for }?;: >>> myfuncs = xy.xyfunc('BC', 'GT', 'DO', 'FF') # same as: # myfuncs = b'\xFF\x81\x1F\xFF\x80\x7D\xFF\x81\x3F\xFF\x81\x3B' xywild(*n) ---------- Returns bytes for reverse-video wildcard character(s), specified by (case-sensitive) 1-byte Ascii counterpart(s) or by Ascii-number (0 - 255) Examples: >>> wildX = xy.xywild('X') # same as wildX = b'\xFF\xC0\xD8' >>> wildX = xy.xywild(88) # same as above >>> wild3X = xy.xywild('3', 'X') # same as wild3X = b'\xFF\xC0\xB3\xFF\xC0\xD8' >>> wild3X = xy.xywild(51, 88) # same as above xy3bchar(*char_in) ------------------ Returns bytes for one or more XyWrite 3-byte printable chars (0 - 255); arg = 1-byte Ascii char(s) or integer(s) in range 0 - 255 Examples: >>> my3byter = xy.xy3bchar('A') # same as my3byter = b'\xFF\x34\x31' >>> my3byter = xy.xy3bchar(255) # same as my3byter = b'\xFFFF' >>> my3byters = xy.xy3bchar('A', 'u') # same as: my3byter = b'\xFF41\xFF75' >>> my3byters = xy.xy3bchar(254, 255) # same as: my3byter = b'\xFFFE\xFFFF' xychar(*char_num) ---------------- Returns bytes for XyWrite 3-byte Speedo char(s) (256-1023), specified by number Examples: >>> mySpeedo335 = xy.xychar(335) # same as: # mySpeedo335 = b'\xFEO\x00' # bytes for 'O ' >>> mySpeedos = xy.xychar(256, 257, 258) # same as: # mySpeedos = b'\xFE\x00\x00\xFE\x01\x00\xFE\x02\x00' # bytes for ' ' GetStackall() ------------- Get byte contents of command history archive file STACKALL.SAV (Used by frame UH) PutStackall() ------------- Write byte contents of command history archive file STACKALL.SAV (Used by frame HUH) bconv(num, base_in, base_out) --------------------------------------- Base-to-base number conversion (base 2 - 36) Input number may be int if all numerals, else must be str Default base_in = 16, default base_out = 10 Examples: bconv(101, 2, 8) bconv('1g2f', 17, 16) Revision History ================ 08/22/14 (v0.98): Undid tweak to frame GETM (Getmail) 08/22/14 (v0.97): Tweak to frame GETM (Getmail) 06/22/14 (v0.96): Bug in frame WCPY caused stray text to be written to screen -- fixed 05/27/14 (v0.95): Updated XYPY.TXT to refer to latest standard release of Python 3 (v3.4.1) Default Python stanza name in XYWWWEB.REG changed from "[Python: Python3]" to "[Python]" (either one works; stanza name can be omitted: XYWWWEB.REG stanza names are non-functional and entirely optional) Revised frame XyPyREG to recognize existing stem variable Python_EXE.1, Python_EXE.2, etc. 02/10/14 (v0.94): Added frame FORMATD* (format digits), used in frame UH to display formatted number of archived commands when no arg specified (UH<Helpkey>) 02/01/14 (v0.93): Frame POPCM translates 5-byte chars into 3-byte chars (via new frame STR5TO3) before popping string to CMline 01/26/14 (v0.92): Frame UH handles Speedo chars (Ascii-254 + byte2 + byte3) in hints, and transforms 5-byte versions of Speedo chars to the corresponding 3-byte char when listing hint results (applies only to XPyL version of UH, not to pure-XPL frame UHLIST) 01/06/14 (v0.91): Code economies/tweaks to function bconv in xypy.tpl 01/06/14 (v0.90): Frame XPyL has option /DG to display output in DialoG box (via frame ShowSG01) Added frame MONTYPY (fun with the Monty Hall Paradox) 12/29/13 (v0.89): Added frame GSFPY* (get Windows Short FileName) 12/29/13 (v0.88): Updated XYPY.TXT to refer to latest standard release of Python 3 (v3.3.3) 12/26/13 (v0.87): Tweaks to frame XPyL; substantial rewrite of frame UPDATEXYPY 12/15/13 (v0.86): Frame MAKEXYPY ChDirs to Editor's directory before running XYPY.BAT (work around problems when a drive letter is SUBSTituted for Editor's dir) 12/12/13 (v0.85): Tweak to frame POPCM 12/12/13 (v0.84): Frame XYPYVER saves XyPy version number to S/G 50; new framename XYPYVER/[NV] suppresses PRompt on EXit Frame UPDATEXYPY calls frame XYPYVER/NV to report updated XyPy version number; other small tweaks to frame UPDATEXYPY Frame HUH (now HUH,HUH/*) enables new framename HUH/[NV] to suppress PRompt on EXit Frame HUHXPL (now HUHXPL*) enables new framename HUHXPL/[NV] to suppress PRompt on EXit Frame AHUH now calls HUH/NV (or HUHXPL/NV if Python not installed) 12/07/13 (v0.83): New frame XYPYVER reports version number of the installed XyPy 12/01/13 (v0.82): Tweaks to frames AHUH (runs HUH 1 in 500 times), HUHXPL (tests for Win32 OS before using CMSORT.EXE) 11/30/13 (v0.81): New frame UPDATEXYPY updates existing XyPy installation with a single command (after UNZIPing latest XYPY.ZIP into Editor's directory); will allow easy updating to future releases of XyPy or via the forthcoming XYWWWEB.U2 v120 or later versions of U2. UPDATEXYPY calls new frame MEXYPY, which MErges XYPY.FRM into U2, (replacing existing frames) and reloads U2 Revisions to frames UH, UHLIST 11/24/13 (v0.80): Revised frame UHLIST (pure-XPL variant of UH) to support listings of arbitrarily long lines. Concomitantly, revised frame ADDCM to eliminate 79-byte limit on DeFined blocks (now, a DF block of any length can be added to STACKALL.SAV with ADDCM) 11/22/13 (v0.79): Small revision to frame UH 11/21/13 (v0.78): Revised frame STACKBOX is bundled with XyPy (included in XYPY.FRM); also included frame R?:* (RC|RK with workaround for UnDo), for compatibility with STACKBOX Pure-XPL version of frame HUH (frame HUHXPL) now uses Christian Maas's freeware CMSORT.EXE for Win32 to sort the command archive, if and only if CMSORT.EXE is present in Editor's directory (otherwise XyWrite's SORT command is still used). CMSORT.EXE overcomes a bug (failure to remove duplicate items despite default SK=4) that sometimes occurs when the native SORT command is used with larger files Added frame AHUH (Aleatory HUH), which runs frame HUH probabilistically (1 in 10|50|100 times). Assign to key(s) or embed in XPL routines to ensure that the STACKALL.SAV command archive is regularly, yet unobtrusively, updated 11/17/13 (v0.77): Further revisions to frame HUH 11/15/13 (v0.76): Bug fix for frame UH if Stack.PM not installed; revision to frame HUH 11/12/13 (v0.75): Added frame VERITAS (Wine|Liquor search via wine-searcher.com) 11/11/13 (v0.74): Frame ADDCM now adds DeFined block (max. length 79 bytes) to STACKALL.SAV (DF block takes precedence over CMline if length of DF block is < 80) 11/09/13 (v0.73): Added frame LOOKUP (Web lookup via frame YA* framename + search_term) 11/09/13 (v0.72): Revised xy.py function xy3bchar to use '{}'.format()' string formatting of hexadecimal values 11/09/13 (v0.71): Revisions to frames HUH and HUHXPL to ensure that STACKALL.SAV is sorted even if STACK.PM not active 11/05/13 (v0.70): Frame POPCM (copy line of text under cursor to CMline) now calls frame PUTDF-CM to ensure proper handling of all 3-byte chars 11/04/13 (v0.69): "Hint" (argument) not passed from frame UH to frame UHLIST when Python not detected -- fixed 11/02/13 (v0.68): Improved error-checking in frame ADDCM; small revision to frame ADDSTACKALL 11/01/13 (v0.67): Added frames ADDCM (add current CMline to STACKALL.SAV) and POPCM (pop line under cursor to CMLine): When assigned to a key, ADDCM enables archiving of individual commands in STACKALL.SAV even if STACK.PM is not installed. POPCM moves command under cursor in STACKALL.SAV up to the CMline 10/30/13 (v0.66): Revised frames UH, HUH and related frames to support formatting of STACKALL.SAV with one command to a line (ending with CrLf). UH<Helpkey> (no hint) now CAlls STACKALL.SAV for viewing or editing 10/28/13 (v0.65): Revised frame HUHXPL to capture SORT error 10/27/13 (v0.64): Added frame ADDSTACKALL (Merge external STACKALL.SAV-type command archive and/or current Stack (S/G 623) into STACKALL.SAV); revised frame HUHXPL to use file-based SORTing (much faster!) 10/24/13 (v0.63): Fixed error in frame HUHXPL 10/16/13 (v0.62): Added frame HUHXPL, a pure-XPL version of frame HUH (Have Unlimited Hint) to XYPY.FRM; HUHXPL is called by HUH if (and only if) Python is not installed 10/13/13 (v0.61): Revisions to funcs xycm and fBX (xypy.tpl); revised Demos 1, 2 and 1a in XYPY.TXT (and frames DEMO# and DEMO1A in XYPY.FRM) 10/13/13 (v0.60): Revised frames UH and HUH to use bytearray methods to manipulate bytes directly; deleted functions Bytes2Str and Str2Bytes from xypy.tpl as unnecessary. 10/12/13 (v0.59): Further revisions to funcs Bytes2Str and Str2Bytes 10/12/13 (v0.58): Revised funcs Bytes2Str and Str2Bytes to fix error in handling internal single quotes (') 09/14/13 (v0.57): Revised frame PYDEC to correct decoding of encoded Python byte strings enclosed in double quotes; tweaks to frame WEB 09/02/13 (v0.56): Frame WEB revised to handle local files (e.g., from DIR listing) 09/01/13 (v0.55): Added frame GETM (read e-mail in XyWrite Untitled window) 08/31/13 (v0.54): Tweaked examples for xy.py functions Bytes2Str and Str2Bytes 08/30/13 (v0.53): Revisions to frame HUH and xy.py func PutStackall (trap 0-byte stackall error) 08/26/13 (v0.52): Minor revisions to XYPY.TXT 08/25/13 (v0.51): Revised functions xycm and xyfunc in xy.py (use list concatenations instead of .append to create the returned bytearrays); other light revisions to xy.py Added frames DEMO# and DEMO1A, which run Demos 1, 2 and 1a in XYPY.TXT. Revisions to XYPY.TXT 08/25/13 (v0.50): Frame UH: reinstated support for hints with 3-byte chars (requires 3- to 5-byte transformation) xy.py functions GetCMline and GetStackall zap Ascii-26 EOF character before return 08/24/13 (v0.49): Added functions Bytes2Str and Str2Bytes to xy.py; these functions are now used in frames UH and HUH, making the embedded Python scripts more readable 08/24/13 (v0.47, 0.48): Frames UH and HUH now use split/join procedure for stripping byte string to bare string (fast!) 08/24/13 (v0.46): Revised frames PYENC and PYDEC Frames UH and HUH now check for presence of Ascii-26 EOF in STACKALL.SAV rather than assuming it is there 08/23/13 (v0.45): Eliminated unnecessary import from frame HUH (XPyL) 08/21/13 (v0.44): Revised XYPY.TXT to reflect further testing of UH-HUH unlimited command Stack save-and-retrieve utilities 08/21/13 (v0.43): Revised XYPY.TXT 08/19/13 (v0.42): Added PYW usage to frame PY: displays output from Python code in new Untitled XyWrite window 08/18/13 (v0.41): Frame ZAPPY (Zap Ascii-26 EoF character) now avoids reading entire file into memory if no Ascii-26 EoF is present 08/18/13 (v0.40): Added frame SPEEDOSPY (write full set of Speedo chars 256-1023); cf. frames 3BYTERSPY, WILDPY, FUNCSPY 08/16/13 (v0.39): Light revisions to XYPY.TXT 08/14/13 (v0.38): Added usage note for frame PY re need to add a closing #comment to Python scripts after editing & SAving in XyWrite, to neutralize effect of Ascii-26 EOF added by XyWrite 08/13/13 (v0.37): Revise MAKEXYPY to trap error if Python not installed or RegVar Python_EXE not configured 08/12/13 (v0.36): Frame XyPyREG tests for existence (not content) of RegVar Python_EXE, to avoid overwriting a complex assignment that evaluates to a (possibly empty) S/G 99; XYPY.BAT, created by frame MAKEXYPY, now creates emptly xy.py before writing the module file, to avoid XCOPY's File or Directory prompt 08/11/13 (v0.33, v0.34, v.035): Substituted new frame SWAPSLASH for SWAP$ to substitute forward slash for backslash in filenames; further revisions to XYPY.TXT; frame ZAPPY now accepts point-and-shoot filename from DIRectory listing; revised function xyfunc() in xy.py 08/11/13 (v0.31, v0.32): Revised setup instructions; light revisions to xy.py; revisions to XYPY.TXT 08/11/13 (v0.30): Added frame XyPyREG, enabling hands-off configuration of variable Python_EXE in XYWWWEB.REG (XyPyREG is called by MAKEXYPY) 08/10/13 (v0.29): Revised frame TIMEDF to support multi-level indents in DeFined code (up to 6 levels assuming 2 spaces per indent) 08/10/13 (v0.28): Revised frame TIMEDF 08/09/13 (v0.27): Added frame TIMEDF (simple Python code timer); revisions to XYPY.TXT 08/08/13 (v0.26): Revisions to XYPY.TXT 08/07/13 (v0.25): Alternate Python code added to frame WILDPY; light revisions to XYPY.TXT 08/06/13 (v0.24): Added alternate coding methods to frames FUNCSPY, WILDPY, and 3BYTERSPY Revisions to XYPY.TXT; plain-text version of XYPY text posted to XyWWWeb as XYPYDOC.TXT (http://users/datarealm.com/xywwweb/xypydoc.txt) 08/05/13 (v0.22, 0.23): Minor tweaks to xy.py (calls to built-in function value() replaced with calls to isinstance()); revisions to XYPY.TXT. 08/04/13 (v0.21): Added U2 frame IDLE (start IDLE GUI from CMline) 08/04/13 (v0.20): Added frame PY3 (Google the Python 3 Standard Library documentation) 08/04/13 (v0.19): Added function bconv to xy.py and frame BCONV to XYPY.FRM (base-to-base conversions for base 2-36) 08/02/13 (v0.18): Revised frame HUH; light revisions to XYPY.TXT 08/01/13 (v0.17): Added functions xyread() and xywrite() to xy.py; various U2 frames revised to make use of these functions 07/31/13 (v0.16): Minor revisions to various U2 frames Deleted unnecessary global variable statements at top of xy.py 07/29/13 (v0.15): Streamlined URL dictionary code in frame WEB Frames UH (Stack Unlimited Hinting) UHDEL (Stacked-command delete facility) now work whether or not Python is installed (STACKALL.SAV must be in Editor's directory). Python is still required to run frame HUH, which updates STACKALL.SAV Tweaks/corrections to frame UH 07/29/13 (v0.14): Added frame PYDEC, companion to PYENC 07/28/13 (v0.13): Added frame UHDEL (delete commands from STACKALL.SAV command history archive) 07/27/13 (v0.12): Deleted frame CHECKFORXYPY (unfinished, unused). Minor edits to XYPY.TXT. 07/27/13 (v0.11): Functions GetCMline(), GetStackAll(), PutStackall() added to xy.py module. New U2 frames UH and HUH (Unlimited Hinting from command archive file STACKALL.SAV; also included: frame FINITO, revised to call HUH (to archive the Stack) before QUITting 07/26/13 (v0.10): Removed frames PYENCODE and PYDECODE (PY??CODE), and renamed frame PYENCPY to PYENC. PYENC is now the preferred (and only) XyPy tool for encoding from XyWrite into Python byte strings. 07/26/13 (v0.09): Added frame PYENCPY (XPyL version of PYENCODE); later renamed to PYENC Revised XYPY.TXT 07/25/13 (v0.08): Added frame GOOPY (Google search from Xy CMline) Frame WEB now accepts URL aliases set in XYWWWEB.REG Added frame GOOPY (Google keyword search) 07/24/13 (v0.07): Revised frame ZAPPY Adopted parens/brackets instead of '\' for Python code line continuations 07/23/13 (v0.06): Added frame ZAPPY (XPyL equivalent of frame ZAP26) 07/21/13 (v0.05): Revised XYPY.TXT to document that xy.py imports os module. Frame WEB: Added dictionary lookup for popular URLs; single-word URL not in dictionary is rendered as 'www.url.com' Frame XPyL: Added framename switch "//" to signal no output expected from embedded Python code Modified frames PYTHON and PY to add option to run script in with python -i switch, leaving interpreter open after script executes Added frame WEB (open URL in new browser tab via Python's webbrowser module) Minor tweaks to frame XPyL 07/21/13 (v0.04): Frame MAKEXYPY deletes any existing copy of xy.py in \Lib Removed unused variable LG and RG from XYPY.TPL (xy.py) Frame MAKEXYPY revised to conform to Python's conventions regarding the location of third-party add-on modules. The XyPy module, xy.py, is now installed in a subdirectory of .\Lib\site-packages call "xypy" (.Lib\site-packages\xypy\xy.py) The "xypy" subdirectory is added to the Python module search path by means of a .pth file named "xypy.pth", located in .\Lib\site-packages. 07/20/13 (v0.03): Light revisions to XYPY.TPL and XYPY.TXT 07/20/13 (v0.02): Fixed XPyL coding errors in frame JMPCP; revised XYPY.TXT; added author contact e-mail address 07/20/13 (v0.01): Initial release on XyWWWeb: <http://users.datarealm.com/xywwweb/#xypy> Enjoy! -- C.L. Distefano palacreide-xylist (at) yahoo.com [End of file XYPY.TXT] Addendum 1: XyPy Python Module xy.py (XYPY.TPL) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= (Rev. 1/11/14; current version may differ) #! python3 ''' xy.py: Module for XyPy|XPyL (Python embedded in XPL) C.L.Distefano rev. 2014-01-11 ---------------------------------------------------------- Requires XyWrite 4 (DOS) + XyWWWeb.U2 + Python 3.x. See XYPY.TXT (in http://users.datarealm.com/xywwweb/XYPY.ZIP) for setup instructions and usage. ''' import os # Global variables # ---------------- EDDIR = '' # Editor's directory (set by U2 frame MAKEXYPY) CMFN = EDDIR + '/cml.sav' INFN = EDDIR + '/xpyldata.in' # Input from XyWrite OUTFN = EDDIR + '/xpyldata.out' # Output from Python script OKFN = EDDIR + '/xpyldata.ok' # Output ready flag file bLG = b'\xAE' # byte code for left guillemet bRG = b'\xAF' # byte code for right guillemet # 3-byte Function mnemonics FUNCNAMES = [ '@0', '@1', '@2', '@3', '@4', '@5', '@6', '@7', '@8', '@9', '@A', '@B', '@C', '@D', '@E', '@F', '@G', '@H', '@I', '@J', '@K', '@L', '@M', '@N', '@O', '@P', '@Q', '@R', '@S', '@T', '@U', '@V', '@W', '@X', '@Y', '@Z', 'AD', 'AS', 'BF', 'BK', 'BS', 'CC', 'CD', 'CH', 'CI', 'CL', 'CM', 'CN', 'CP', 'CR', 'CS', 'CU', 'DC', 'DF', 'GH', 'DL', 'DP', 'DS', 'DW', 'EL', 'ER', 'EX', 'GT', 'HM', 'M0', 'M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'MD', 'MU', 'MV', 'NC', 'NL', 'NK', 'NP', 'NR', 'NS', 'NT', 'NW', 'PC', 'PD', 'PL', 'PP', 'PR', 'PS', 'PT', 'PU', 'PW', 'R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9', 'RC', 'RD', 'RE', 'RL', 'RP', 'RS', 'RV', 'RW', 'SD', 'SH', 'SI', 'SK', 'SM', 'SN', 'SS', 'SU', 'SV', 'TF', 'TI', 'TN', 'TS', 'UD', 'WA', 'WC', 'WC', 'WN', 'WS', 'WX', 'WW', 'XC', 'XD', 'DT', 'S1', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'SP', 'BC', 'LB', 'LE', 'NF', 'PF', 'TP', 'BD', 'MS', 'NM', 'LD', 'LL', 'LR', 'LU', 'UP', 'FF', 'YD', 'DO', 'DX', 'MK', 'SO', 'OP', 'WZ', 'NX', 'SW', 'FD', 'FM', 'TL', 'TR', 'TE', 'ED', 'EE', 'HC', 'EC', 'MC', '#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8', '#9', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', 'DR', 'EN', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'EF', 'IB', 'NO', 'NI', 'CO', '$0', 'LS', 'XP', 'WG', 'XM', '&0', '&1', '&2', '&3', '&4', '&5', '&6', '&7', '&8', '&9', '&A', '&B', '&C', '&D', '&E', '&F', '&G', '&H', '&I', '&J', '&K', '&L', '&M', '&N', '&O', '&P', '&Q', '&R', '&S', '&T', '&U', '&V', '&W', '&X', '&Y', '&Z', 'HL', '$A', '$A', '$C', '$D', '$E', '$F', '$G', '$H', '$I', '$J', '$K', '$L', '$M', '$N', '$O', '$P', '$Q', '$R', '$S', '$T', '$U', '$V', '$W', '$X', '$Y', '$Z', 'XX', 'H@', 'VH', 'MW', 'QH', 'DK', 'SR', 'SC', 'TG', 'H1', 'JH', 'DZ', 'DD', 'DM', 'LT', 'RK', 'NN', 'MT', 'ET', 'ZT', 'T1', 'TT', '<<', '>>', 'IT', 'SL', 'SF', 'FL', 'FR', 'FC', 'SY', 'ME', 'AC', 'FS', 'TW', 'MI', 'RO', 'NB', 'Q1', 'Q2', 'Q3', 'Q4', 'Q5', 'Q6', 'Q7', 'Q8', 'TO', 'IR', 'AR', 'AX', 'DB', 'DE', 'HF', 'SA', 'OV', 'TC', 'TB', 'JM', 'SG', 'XH', 'FT', 'BX', 'MN', 'CB', 'M9', 'MZ', 'ZZ', 'RX', 'ST', 'KF', 'JC', 'AK', 'TM', 'NU', 'B4', 'QP', 'HG', 'US', 'XE', 'ES', 'RB', 'S-', 'S+', '**', 'BN', 'RU', 'CF', 'UI', 'XS', 'EA', 'BT', 'KD', 'DN', 'HI', 'WH', 'XN', 'FX', 'UN', 'MX', 'AZ', 'BR', 'HK', '#X', '#X', 'BM', 'JR', 'XO', 'XW', 'TX', 'LF', 'LO', 'BL', 'XT', 'WT', 'IC', 'CT', 'VB', '-D', 'WD', 'RM', 'LM', 'aL', 'aR', 'aB', 'aE', 'MP', 'mN', 'QL', 'QR', 'MF'] # Function definitions # -------------------- def outok(flag = False, okfile = OKFN): ''' Output ready flag file (0=write|1=delete, flag_filename) ''' if not flag: with open(okfile, 'wt') as okfo: okfo.write('') else: try: os.remove(okfile) except FileNotFoundError: pass def xyread(file_in = INFN, mode = 'rb'): ''' Read XyWrite input file (minus EOF) ''' try: with open(file_in, mode) as f: fb = f.read() if fb[-1] == 26: fb = fb[:-1] # fails with 0-byte file return fb except: return None def xywrite(bytes_in, file_out = OUTFN, mode = 'wb'): ''' Write file for output to XyWrite ''' try: with open(file_out, mode) as f: f.write(bytes_in) return 1 except: return None def GetCMline(): ''' Fetch CMline file in binary mode ''' with open(CMFN, 'rb') as f: cmline = f.read() if cmline[-1] == 26: # fails with 0-byte file cmline = cmline[:-1] return cmline def xycm(*cm_in): ''' Returns bytes for XyWrite embedded command(s) ''' ba = bytearray() for cm in cm_in: if isinstance(cm, str): cm = cm.encode() try: ba.extend(b'\xae' + cm + b'\xaf') except ValueError: print('Bad:', cm, '- must be Ascii text string or bytes') return None except Exception as e: print(e) return None return ba def fBX(*cm_in): ''' Returns bytes for BX [command]Q2 ''' ba = bytearray() for cm in cm_in: if isinstance(cm, str): cm = cm.encode() try: ba.extend(b'\xff\x82\xab' + cm + b'\xff\x82\x7f') except ValueError: print('Bad:', cm, '- must be Ascii text string or bytes') return None except Exception as e: print(e) return None return ba def xyfunc(*func_mnemonic): ''' Return bytes for XyWrite 3-byte function mnemonic(s) ''' ba = bytearray() for mn in func_mnemonic: try: if mn not in FUNCNAMES: mn = mn.upper() n = FUNCNAMES.index(mn) # byte1 byte2 byte3 for b in 255, 128 + n // 128, (1 + n * 2) % 256: ba.append(b) except Exception: print(mn, 'is not a valid 3-byte func mnemonic') return None return ba def xywild(*char_in): ''' Returns bytes for standard reverse-video wildcard character(s) by normal Ascii char or Ascii-number (0 - 255) ''' ba = bytearray() for n in char_in: if isinstance(n, str): if len(n) == 1: n = ord(n) if isinstance(n, int): if 0 <= n < 256: n = (n + 128) % 256 b2 = 192 if n < 128: b2 = 193 for v in 255, b2, n: ba.append(v) else: raise ValueError('1-byte Ascii char or int 0-255 only') return None return ba def xy3bchar(*char_in): ''' Returns bytes for XyWrite 3-byte printable char(s) (0 -255) args = 1-byte Ascii char or integer 0 - 255 ''' ba = bytearray() for n in char_in: if isinstance(n, str): if len(n) == 1: n = ord(n) if isinstance(n, int): # next line converts, e.g., 0xa to '0A' h = '{0:0>2s}'.format(hex(n).split('x')[1].upper()) # byte1 byte2 byte3 for bt in 255, ord(h[0]), ord(h[1]): ba.append(bt) else: raise ValueError('1-byte Ascii 0 - 255 char(s) only') return None return ba def xychar(*char_num): ''' Return bytes for XyWrite 3-byte Speedo char(s) 256 - 1023 ''' ba = bytearray() errmsg = 'arg must be integer(s) in range 256-1023' for n in char_num: if isinstance(n, int): if 256 <= n < 1024: # byte1 byte2 byte3 for b in 254, (n - 256) % 256, (n - 256) // 256: ba.append(b) return ba else: raise ValueError(errmsg) return None else: raise ValueError(errmsg) return None def GetStackall(): ''' Read command archive file STACKALL.SAV ''' stackall = None with open(EDDIR + '/stackall.sav', 'rb') as f: stackall = f.read() try: if stackall[-1] == 26: stackall = stackall[:-1] except: pass return stackall def PutStackall(bytes_in): ''' Write command archive file STACKALL.SAV ''' if bytes_in: with open(EDDIR + '/stackall.sav', 'wb') as f: try: f.write(bytes_in) return 1 except: pass else: pass def bconv(num, base_in = 16, base_out = 10): ''' Base-to-base number conversion ''' prefix = '' try: num = int(str(num), base_in) if base_out == 10: return num if str(num).startswith('-'): num = str(num)[1:] prefix = '-' L = '0123456789abcdefghijklmnopqrstuvwxyz' num = int(num) digits_out = '' # convert base10 to base_out value while num >= base_out: i = divmod(num, base_out) digits_out += L[:base_out][i[1]] num = i[0] digits_out += L[:base_out][num] return prefix + digits_out[::-1] except Exception as e: print(e) return None if __name__ == '__main__': print(__doc__) # end xy.py Addendum 2: XyPy U2 Frames (XPL/XPyL) in Pseudo-Code =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [as revised 2/10/14; current real-code version may differ] /-- Start XyPy routines {{5xypyver*}} Report XyPy version number (S/G 50 out; XYPYVER/[NV] suppresses PRompt) [CLD] {2}<SV50,0.98><IF"/"{238}<VA$FR>{less_than}0><PRXyP y v@50><EI>{2} {{5py,pyi,pyw,py/}} PyShell: Run Python code from XyWrite [CLD rev.8/19/13] {2};*; PY [arg(s)]<Helpkey> runs current file ;*; or DF block as Python script ;*; PYI<Helpkey> runs file|DF block in python -i interactive mode ;*; PYW<Helpkey> displays output from DeFined Python (XPyL) script ;*; PY/<Helpkey> shells directly to Python interpreter <IF<VA$WS>==1&"/"{238}<VA$FR>{less_than}0><SX01,@up r(<VA$FR>)>DZ ;*; <IF<IS01>{240}"W"><IF<VA$DE>{greater_than}0>< SV50>JM 2.XPyL/X/WQ2 <EI><EX><EI>;*; <SV02,><IF<VA|50>{greater_than}0><SX02,<IS50> ><EI><SX50,<VA$ED>> JM 2.GetPathQ2 <SX03,<IS50>+"\xytmp.py"><SV04, # EoF comment workaround>BX sa %04,<PV03>Q2 BX waitQ2 DZ BX apt <PV03>Q2 BX waitQ2 ;*; <LBa><SX50,<IS03>> <IF<VA|02>{greater_than}0><SX50,<IS50>+" "+<IS02>><EI>;*; JM 2.python/k<IF<IS01>{240}"I">/i<EI>Q2 DO FF <EX><EI><SV03,><SV02,><GLa>{2} {{5python*}} Launch Python interpreter/script [CLD rev.7/21/13] {2};*; ;*; Fully-qualified path to python.exe must be in Reg var Python_EXE ;*; Usage: << SV50,[scriptname.py] [args]>> JM 2.python[/k][/x]Q2 ;*; ;*; /K and /X are DOS command switches (default = DOS/NV/Z /C ...) ;*; /I launches the script with the python -i option, which returns ;*; you to the Python interpreter prompt >>> after the script ;*; executes ;*; <SX62,@upr(<VA$FR>)><SV99,Python_EXE>JM 2.RegData/RQ2 <IF"PYTHON.EXE"{238}@upr(<IS99>){less_than}0><PRPython 3 and XyWWWeb RegVar Python_EXE required!><EX1><EI><SX63,<IS99>>;*; <SV64,><IF<VA|50>{greater_than}0><SX64,<IS50> ><EI><SX50,<VA$ED>> JM 2.GetPathQ2 <SX65,<IS50>+"\xpyldata.out">BX ernv <PV65>Q2 BX waitQ2 ;*; <SX65,<IS50>+"\xpyldata.ok">BX ernv <PV65>Q2 BX waitQ2 ;*; BX dos/nv<IF<IS62>{240}"/X">/x<EI>/z <IF<IS62>{240}"/K">/k<GLa><EI>/c<LBa> <PV63><IF<IS62>{240}"/I"> -i <EI><IF<VA|64>{greater_than}0> <PV64><EI>Q2 BX waitQ2 {2} {{5XPyL*}} Run Python script embedded in S/G 50 ("XPyL") [CLD rev.1/6/14] {2}BX es 1Q2 <SX61,-1> <IF<VA|50>{greater_than}0><SX62,<IS50>><SX62, <IS62>+" # end"><SX63,@upr(<VA$FR>)><SX50,<VA$ED>>JM 2.GetPathQ2 ;*; <SV99,Python_EXE>JM 2.RegData/RQ2 <IF"PYTHON.EXE"{238}@upr(<IS99>){less_than}0> <PRPython 3 and XyWWWeb RegVar Python_EXE required!><EX1><EI> <SX64,<IS99>>;*; <SX61,0><SX65,<IS50>+"\xpyltmp.py">BX sa %62,<PV65>Q2 BX waitQ2 <SV62,>;*; <SX66,<IS50>+"\xpyldata.out">BX ernv <PV66>Q2 BX waitQ2 ;*; <SX67,<IS50>+"\xpyldata.ok">BX ernv <PV67>Q2 BX waitQ2 ;*; BX dos/nv<IF<IS63>{240}"/X">/x<EI>/z <IF<IS63>{240}"/K">/k<GLa><EI>/c<LBa> cmd.exe /c <PV64> <PV65><IF<VA|68>{greater_than}0> <PV68><EI>Q2 BX waitQ2 DO FF <IF<IS63>{240}"//"><EX><EI>;*; ;*; ;*; Output modes <SX61,1><PRWaiting for output...><SX62,3>;*; <CUb,62>BX exist <PV67>Q2 <IF<ER>><GLc><EI> BX pQ2 <LBb><PRNo output><EX>;*; <LBc><SX61,2>BX ernv <PV67>Q2 BX waitQ2 ;*; <SV67,><IF<VA$MG>{less_than}{greater_than}""><SX67, <VA$MG>><EI> <PR@67><SV67,>;*; ;*; Store output in S/G 50; optionally display on CMline (/CM), ;*; in DialoG box (/DG), or on PRompt line (/PR) <IF<IS63>{240}"/50"!<IS63>{240}"/CM"!<IS63>{240}"/D G"! <IS63>{240}"/PR">;*; <SX50,<IS66>>JM 2.SV50Q2 ;*; <IF<IS63>{240}"/DG"><SX01,<IS50>><SV50,>JM 2.ShowSG01Q2 <EX><EI>;*; <IF<IS63>{240}"/CM">BC <GT50><EI><IF<IS63>{240}"/PR"><PR@50><E I> <LBd>;*; ;*;BX ernv <PV66>Q2 BX waitQ2 ;*; <EX><EI>;*; ;*; MErge at cursor position (/ME) or into Untitled file in new window (/W) <IF<IS63>{240}"/ME"!<IS63>{240}"/W">;*; <IF<IS63>{240}"/W"><SX62,<VA$WA>><IF<PV62& gt;{less_than}1><PRNo window> BX pQ2 <GLe><EI>;*; BX func #<PV62>Q2 BX ne/100Q2 <EI> <SX50,<CP>>BX me <PV66>Q2 BX waitQ2 JM 2.ReJuMPQ2 <PRDone><GLd><EI>;*; ;*; Else do nothing (output retained in XPYLDATA.OUT) <LBe>;*; ;*;BC ca <PV66><SX62,"Output in "+<IS66>><PR@62> <EX><EI><PRXPL usage: <SV50,[Python_code]>JM 2.XPyL[/K][/X][//|/50|/CM|/DG|/PR|/ME|/W]Q2>{2} {{5idle*}} Start Python IDLE GUI [CLD rev.8/4/13] {2}<SV01,><IF<VA$FR>{240}"/"><SX01,<VA$FP>> ;<EI><IF<VA|50>{greater_than}0 > <SX01,<IS50>><EI>;*; <SV99,Python_EXE>JM 2.RegData/RQ2 <IF<VA|99>{greater_than}0>;*; <SX50,<IS99>>JM 2.GetPathQ2 ;*; <SX02,"@echo off call "+<IS50>+"\Lib\IDLELIB\IDLE.BAT "+<IS01>+" exit"><SX50,<VA$ED>>JM 2.GetPathQ2 ;*; BX sa %02,<PV50>\idlexy.batQ2 ;*; BX dos/nv/x/z /c cmd.exe /c start <PV50>\idlexy.bat <PV01>Q2 ;*; BX p 5Q2 BX ernv <PV50>\idlexy.batQ2 <EX><EI><PRPython not installed!>{2} {{5pyenc}} Encode file|DF block to Python hex byte code (XPyL) [CLD rev.8/24/13] {2}<SV01,><IF<VA|50>{less_than}1><IF<VA$WS>== 1> <LBa><IF<VA$WA>{greater_than}0><SX50,<VA$ED>& gt;JM 2.GetPathQ2 <SX02,<IS50>+"\xpyldata.in"><IF<VA|01>{greater_than }0> BX copy/nv <PV01> <PV02>Q2 BX waitQ2 <EI>DZ BX sa<IF<VA$DE>{greater_than}0>d<EI>/nv <PV02>Q2 BX waitQ2 <LBa><SX50," from xy import outok, xyread, xywrite, OUTFN outok() xywrite(str(xyread()), OUTFN, 'wt') outok(1)">JM 2.XPyL/X/WQ2 <PROriginal is in Alternate Screen><EX> <EI><PRNo window><EX> <EI><PRNo file><EX> <EI><SX01,<VA$FP>>YD <GLa>{2} {{5pydec}} Decode Python hex byte code (file|DF block) (XPyL) [CLD rev.9/14/13] {2}<SV01,><IF<VA|50>{less_than}1><IF<VA$WS>== 1> <LBa><IF<VA$WA>{greater_than}0><SX50,<VA$ED>& gt;JM 2.GetPathQ2 <SX02,<IS50>+"\xpyldata.in"><IF<VA|01>{greater_than }0> BX copy/nv <PV01> <PV02>Q2 BX waitQ2 <EI> DZ BX sa<IF<VA$DE>{greater_than}0>d<EI>/nv <PV02>Q2 BX waitQ2 <LBa><SX50," from xy import outok, xyread, xywrite, INFN outok() fb = xyread(INFN, 'r') # zap EOF: if fb[-1] == chr(26): fb = fb[:-1] # adjust if double-quotes ("") if 'b""' in fb: if fb.index('b""') == 0 and '\'' in fb: fb = fb.replace('\'', '\\\'') fb = fb.replace('""', '\'') exec('fb = ' + fb) if not xywrite(fb): xywrite(b'Decoding failed. Input must be b\'hex_bytes\'') outok(1)">JM 2.XPyL/X/WQ2 XP TF <PROriginal is in Alternate Screen><EX> <EI><PRNo window><EX> <EI><PRNo file><EX> <EI><SX01,<VA$FP>>YD <GLa>{2} {{5timedf}} Time a DeFined block of Python code (XPyL) [CLD rev.8/10/13] {2};*; TIMEDF [setup[, number[, repeat]]]<Helpkey> ;*; Defaults: setup='', number=1000, repeat=10 ;*; Renumber: Left$ "0+", Freeze 50 BX es 1Q2 DX DZ <IF<VA$DE>{greater_than}0><IF<VA|50>{less_than}0> ;<SV50,><EI>;*; <SV01,0+02>;*; <SV02,code><SV03,setup><SV04,number><SV05,repeat> ; <SX06,<IS50>>;*; <SV06,args> ;*; Fix code (temporarily using 03, 04, 05): <SV02><SX02,"\n"+<IS02>><SU05,<LBa><IF< IS02>{240}<IS07>><SV03,><XS02,07, 04,,03><SX02,<IS04>+<IS08>+<IS03>><GLa> <EI>><SV07,> <SV08,\n><GT05><SV07,{tab}><SV08,\t><GT05> ;*; ;*; Convert space indents to tabs (to 6 levels assuming 2 spaces per tab) <SX09,12><SV10,\n><CUb,09><SX07,<IS10>+" "><SX08,<IS10>+"\t"><GT05><SX10,<IS10>+"\t "><LBb>;*; ;*; Default setup, number, repeat: <SV03,><SV04,1000><SV05,10>;*; ;*; Parse args, if any, into <SV03,><SV04,><SV05> <IF<VA|06>{greater_than}0><SV08,,><SV09,>;*; <SU10,<SX01,<PV01>+1><SX01,<IS01>><IF<V A|01>{less_than}2> <SX01,"0"+<IS01>><EI> <IF<VA|11>{greater_than}0><SX12,"<SV"+<IS01>+"," +<IS11>+">"><PV12> <EI>><LBc><IF<IS06>{240}","><XS06,08,11,12 ,09><GT10><SX06,<IS09>><GLc> <EI><SX11,<IS06>><GT10><EI>;*; ;*; Python script: <SX50,"import xy, timeit xy.outok() # print('Timing (could take a while)...') out = min(timeit.repeat('"+<IS02>+"', setup='"+<IS03>+"', number="+<IS04>+", repeat="+<IS05>+"))*1000 out = 'Min %.2f msec (number="+<IS04>+" repeat="+<IS05>+")' % out xy.xywrite(out, xy.OUTFN, 'wt') xy.outok(1)"><PRTiming (could take a while)...>JM 2.XPyL/X/50Q2 DO FF <PR@50><EX><EI><PRNothing DeFined>{2} {{5bconv}} Base-to-Base number conversion (XPyL; S/G50 out) [CLD rev.8/4/13] {2}<IF<VA|50>{greater_than}0><SX01,<IS50>><IF "'"{238}<IS01>{less_than}0> <IF","{238}<IS01>{less_than}0><SX01,"'"+<IS01>+"'"& gt;<EI> <IF<IS01>{240}","><SV02,,><SV03,><XS01,02,04, ,03> <SX01,"'"+<IS04>+"',"+<IS03>><EI><EI><S X50," from xy import outok, xywrite, bconv outok() res = bconv("+<IS01>+") if not res: res = 'Conversion failed' xywrite(str(res), mode = 'wt') outok(1)">JM 2.XPyL/X/PRQ2 <EX> <EI><PRBCONV num_in, base_in, base_out<Helpkey>>{2} {{5wcpy}} Word count of DeFined block, or current or specified file (XPyL) [CLD rev. 6/22/14] {2}BX es 1Q2 DX <PRWorking>;*; <SV01,><IF<VA|50>{greater_than}0><SX01,<IS50> ><EI><SX50,<VA$ED>>JM 2.GetPathQ2 <SX98,<IS50>><IF<VA|01>{less_than}1&<VA$WS>== 1><SX01,<VA$FP>>DZ <IF<VA$DE>{greater_than}0><SX01,<IS98>+"\xpyldata.i n"><EI>BX sad/nv <PV01>Q2 BX waitQ2 <EI><IF<VA|01>{greater_than}0>BX exist <PV01>Q2 <IF@not(<ER>)><SX50,<IS01>>JM 2.swapslashQ2 <SX02,<IS50>><SX50,<IS98>+"\xpyldata.out"><SV 98,>JM 2.swapslashQ2 <SX03,<IS50>><SX50,"import xy, re xy.outok() "><IF@upr(<IS02>){240}"XPYLDATA.IN"><SX50,<IS50> +"infn = xy.INFN "><GLa><EI><SX50,<IS50>+"infn = '"+<IS02>+"' "><LBa> <SX50,<IS50>+"with open(infn, 'rb') as f1, open(xy.OUTFN, 'wt') as f2: words = re.findall('\w+', f1.read().decode(encoding='latin-1')) f2.write('{0:,d}'.format(len(words)) + ' words in ' + infn.replace('/','\\')) xy.outok(1)">JM 2.XPyL/X/PRQ2 <EX><EI><PRNon-existent file: @01><EX><EI><PRNo file specified>{2} {{5listwords}} List all words in specified or current file (XPyL) [CLD rev.7/21/13] {2}BX es 1Q2 <IF<VA|50>{less_than}1&<VA$WS>==1><SX50,<VA$FP&g t;><EI> <IF<VA|50>{greater_than}0>JM 2.swapslashQ2 <SX01,<IS50>> <SX50,<VA$ED>>JM 2.GetPathQ2<SX02,<IS50>+"\xpyldata.out"> <SX50,<IS02>>JM 2.swapslashQ2 <SX03,<IS50>> <SX50,"import xy, re xy.outok() fn1, fn2 = '"+<IS01>+"', '"+<IS03>+"' print('Compiling case-sensitive list of words in', fn1) with open(fn1, 'rb') as f1, open(fn2, 'wt') as f2: wds = [] txt = f1.read().decode(encoding='latin-1') # wds = re.findall('\w+', txt) # wds += re.findall('\w+(?:[-/]\w+)+', txt) # wds = re.split('\w+', txt) wds = re.findall('[A-Z,a-z]+', txt) wds += re.findall(""[A-Z,a-z]+(?:[-/'][A-Z,a-z]+)+"", txt) if wds: txt = wds wds = set(wds) wdlist, wdlistlen = [], 0 wdlgth = 0 for wd in wds: if ',' in wd: wd = wd.replace(',', '') # wc = txt.count(wd) # if len(wd) & wc: wdlist.append(wd+' ('+str(wc)+')') if len(wd): wdlist.append(wd) wdlgth += len(wd) if wdlist: wdlist = sorted(set(wdlist)) wdlistlen = len(wdlist) wdlgth = wdlgth/wdlistlen wdlist = '\n'.join(wdlist) f2.write(wdlist) xy.os.system('cls') print('Done\n\t', '{0:,d}'.format(wdlistlen), 'unique words found in', fn1) print('\t Average word length = {0:.1f} chars'.format(wdlgth)) input('\nHit Enter to view word list in XyWrite{greater_than}') else: print('No words found!') input('\nHit Enter to return to XyWrite{greater_than}') xy.outok(1)">JM 2.XPyL/WQ2 <IF<VA$FI>=="[UNTITLED]">BX ch [wC] [wC]Q2 <SX01,<VA$WC>+1><SX01,<IS01>+" words">DO F.2D <PR@01><EI><EX> <EI><PRLISTWORDS [d:\\path\\filename] (default = current file)>{2} {{5listcp}} List CharPos of all case-sensitive occurrences of '$tring' in current file, plus text snippet containing '$tring' (XPyL) [CLD rev.6/15/13] {2}BX es 1Q2 <IF<VA|50>{greater_than}0><SX01,<IS50>><SX50, <VA$FP>> JM 2.swapslashQ2 <SX02,<IS50>><SX50,<VA$ED>>JM 2.GetPathQ2 <SX50,<IS50>+"\xpyldata.out">JM 2.swapslashQ2<SX03,<IS50>> <SX50,"# -*- coding: latin-1 -*- import xy, re xy.outok() fn1, fn2 = '"+<IS02>+"', '"+<IS03>+"' def snip(cp, text): return text[cp-45:cp+65] with open(fn1, 'rb') as f1, open(fn2, 'wt') as f2: mch = "+<IS01>+" ixo = '' txt = f1.read().decode(encoding='latin-1') ixs = ['\n--\n'+str(i.start())+':\n... '+ snip(i.start(), txt)+' ...\n' for i in re.finditer(mch, txt)] ixo = ('""'+mch+'"" in '+fn1+' ('+str(len(ixs))+ ' occurences):\n--\n[CP]:\n[snippet]\n\n' + ''.join(ixs)) try: f2.write(ixo) except Exception as e: f2.write('Python error message:\n'+str(e)) xy.outok(1)">JM 2.XPyL/x/wQ2 ;*; ;*;<IF<PV61>{greater_than}1>BX ch ",",[wC][wC]"Q2 BX waitQ2 <EI>;*; <EX><EI><PRLISTCP 'string'<Helpkey>>{2} {{5lstcp}} List CharPos of all case-sensitive occurrences of '$tring' in current file (XPyL) [CLD rev.6/15/13] {2}BX es 1Q2 <IF<VA|50>{greater_than}0><SX01,<IS50>><SX50, <VA$FP>> JM 2.swapslashQ2 <SX02,<IS50>> <SX50,<VA$ED>>JM 2.GetPathQ2 <SX50,<IS50>+"\xpyldata.out"> JM 2.swapslashQ2 <SX03,<IS50>> <SX50,"# -*- coding: latin-1 -*- import xy, re xy.outok() fn1, fn2 = '"+<IS02>+"', '"+<IS03>+"' with open(fn1, 'rb') as f1, open(fn2, 'wt') as f2: mch = "+<IS01>+" txt = f1.read().decode(encoding='latin-1') # mch = str(re.findall("+<IS01>+", txt)) ixs = [str(i.start()) for i in re.finditer(mch, txt)] ixo = '\n'.join(ixs) ixo = mch+' in '+fn1+' ('+str(len(ixs))+' occurences):\n' + ixo try: f2.write(ixo) except Exception as e: f2.write('Python error message:\n'+str(e)) xy.outok(1)">JM 2.XPyL/x/wQ2 <EX><EI><PRLSTCP 'string'<Helpkey>>{2} {{5jmpcp}} JuMP to all (case-sensitive) occurrences of '$tring' in current file (simulates native SEA command) (XPyL) [CLD rev.7/20/13] {2}BX es 1Q2 <IF<VA|50>{greater_than}0><SX01,<IS50>><SX50, <VA$FP>> JM 2.swapslashQ2 <SX02,<IS50>> <SX50,"# -*- coding: latin-1 -*- import re from xy import OUTFN, outok, bLG, bRG, FUNCNAMES, xyfunc, xycm, f BX outok() infn = '"+<IS02>+"' for v in 'BX', Q2 ', 'BC', 'GT': exec(v + ' = xyfunc(v)') with open(infn, 'rb') as f1, open(OUTFN, 'wb') as f2: mch = "+<IS01>+" txt = f1.read().decode(encoding='latin-1') ixs = [str(i.start()) for i in re.finditer(mch, txt)] if len(ixs) {greater_than} 500: ixs = ixs[:500] ixo = '""'+mch+'"" in '+infn+' ('+str(len(ixs))+' hits [500 max])' ixs = '|'.join(ixs) + '|' ixs = ( fBX('es 1') + BC + b'Press any key to locate hits, Esc to quit' + xycm('PR'+ixo, 'SV01,'+ixs, 'SV02,|', 'LBa', (b'SX03,'+bLG+b'RK'+bRG), (b'IF'+bLG+b'VA$KC'+bRG+b'{greater_than}1'), (b'IF'+bLG+b'IS01'+bRG+b'\xF0""|""'), 'SV04,', 'XS01,02,03,04,04', (b'SX01,'+bLG+b'IS04'+bRG)) + fBX(bJM p '+bLG+b'PV03'+bRG) + xycm('GLa', 'EI', 'EI') + BC + GT + xycm('PRDone')) f2.write(ixs) outok(1)">JM 2.XPyL/x/50Q2 <PV50><EX><EI><PRLSTCP 'target_string'<Helpkey>>{2} {{5funcspy}} Write full set of 3-byte functions [CLD rev. 8/6/13] {2}<IF<VA$WA>{greater_than}0><SV50,from xy import outok, xywrite outok() b = bytearray() for x in ([(255, i, j) for i in range(128, 131) for j in range(1, 256, 2)]): for y in x: b.append(y) # for x in range(128, 131): # for y in range(1, 256, 2): # for z in 255, x, y: # b.append(z) if not xywrite(b): xywrite(b'File write error') outok(1)>JM 2.XPyL/X/WQ2 <EX><EI><PRNo window>{2} {{5wildpy}} Write full set of 3-byte reverse-video (wildcard) chars [CLD rev.8/11/13] {2}<IF<VA$WA>{greater_than}0><SV50,from xy import outok, xywrite outok() b = bytearray() # fastest: for x in range(128, 256): for y in 255, 192, x: b.append(y) for x in range(128): for y in 255, 193, x: b.append(y) # a little slower: # for x in ([(255, 192, i) for i in range(128, 256)] + # [(255, 193, i) for i in range(128)]): # for y in x: # b.append(y) # slowest: # z = (x for y in # ([(255, 192, i) for i in range(128, 256)] + # [(255, 193, i) for i in range(128)]) # for x in y) # for v in z: # b.append(v) if not xywrite(b): xywrite(b'File write error') outok(1)>JM 2.XPyL/X/WQ2 <EX><EI><PRNo window>{2} {{53byterspy}} Write full set of 3-byte printable chars [CLD rev.8/6/13] {2}<IF<VA$WA>{greater_than}0><SV50,from xy import outok, xy3bchar, xywrite outok() b = bytearray() for x in map(xy3bchar, range(256)): for y in x: b.append(y) # for x in range(256): # for y in xy3bchar(x): # b.append(y) if not xywrite(b): xywrite(b'File write error') outok(1)>JM 2.XPyL/X/WQ2 <EX><EI><PRNo window>{2} {{5speedospy}} Write full set of Speedo chars [CLD rev.8/18/13] {2}<IF<VA$WA>{greater_than}0><SV50,from xy import outok, xychar, xywrite outok() b = bytearray() for x in map(xychar, range(256, 1024)): for y in x + b' ': b.append(y) if not xywrite(b): xywrite(b'File write error') outok(1)>JM 2.XPyL/X/WQ2 <EX><EI><PRNo window>{2} {{5goopy}} Google search (XPyL) [CLD rev.7/25/13] {2}<IF<VA|50>{greater_than}0><SX50,"import webbrowser webbrowser.open('http://www.google.com/search?num=50&q="+<IS50>+"' ) ">JM 2.XPyL//XQ2 <EX><EI><PRGOOPY [search terms]>{2} {{5py3}} Search the Python 3 Standard Library via Google [CLD] {2}<IF<VA|50>{greater_than}0><SX50,<IS50>+" site:docs.python.org/3/library/">JM 2.goopyQ2 <EX><EI> <PRPY3 [keywords]<Helpkey> [Python 3 documentation search]>{2} {{5getm}} Simple GetMail (XPyL) [CLD rev.9/1/13] {2};*; Review all messages in Untitled file. ;*; Messages are NOT deleted! <SV99,POP_Server>JM 2.RegDataQ2 <SX01,<IS99>>;*; <SV99,Email_Address>JM 2.RegDataQ2 <SX02,<IS99>>;*; <SX50," import poplib from xy import outok, xywrite outok() try: p = '"+<IS01>+"' u = '"+<IS02>+"' if not p: p = input('Enter POP3 server name: ') if not u: u = input('E-mail address: ') print('Caution: Password will be displayed...') s = input('Password: ') M = poplib.POP3(p, port=110, timeout=15) M.user(u) M.pass_(s) numMessages = len(M.list()[1]) if numMessages: print(numMessages, 'messages') msgs = bytearray() for i in range(numMessages): print('Downloading message #', i+1) msgs += ( ('-='*10).encode() + b' [Message # ' + str(i+1).encode() + b' of ' + str(numMessages).encode() + b'] ' + ('-='*10).encode() + b'\r\n' ) for j in M.retr(i+1)[1]: # for j in M.retr(i+1): msgs += j + b'\r\n' msgs += b'\r\n\r\n' else: msgs = b'No mail' M.quit() except: msgs = b'Error retrieving mail' xywrite(msgs) outok(1)">JM 2.XPyL/WQ2 {2} {{5uh}} Unlimited Hint: List commands matching "hint" (any substring of command) from omnibus command archive STACKALL.SAV [CLD rev.1/26/14] {2}<IF<VA$WA>{greater_than}0>BX es 1Q2 DX <SV99,Python_EXE> JM 2.RegDataQ2 ;*; <IF<VA|50>{less_than}0><SV50,><EI><SX01,<I S50>><SX50,<VA$ED>> JM 2.GetPathQ2 ;*; <IF<VA|01>{greater_than}0><IF<VA|99>{greater_than}0 > BX sa %01,<PV50>\cml.savQ2 <SX01,<IS50>>;*; <SX50," from xy import outok, GetCMline, GetStackall, xywrite outok() hint = GetCMline() hint = hint.replace(b'\xff', b'\xffFF').replace(b'\xfe', b'\xffFE') ft = GetStackall() ftlist = ft.split(b'\r\n') # list commands hits = bytearray() if hint: for h in ftlist: if hint.upper() in h.upper(): hits.extend(h.replace( b'\xffFF', b'\xff').replace( b'\xfe', b'\xffFE') + b'\r\n') if hits: if not xywrite(hits): xywrite(b'File write error') outok(1) ">JM 2.XPyL/X/WQ2 BX exist <PV01>\xpyldata.outQ2 <IF<ER>&<VA|99>{greater_than}0>BX ab/nvQ2 DO F.2D <PRNot found><EX><EI> DO FF BC popCMGT <PR{less_than}Helpkey{greater_than} copies command under cursor to CMline><EX><EI><SX50,<IS01>>JM 2.uhlistQ2 <EX><EI>;*; <SX01,<VA$WA>>BX func #<PV01>Q2 <SX50,<IS50>+"\STACKALL.SAV"> JM 2.CallorGo/100Q2 TF BX ch/t [wC] [wC]Q2 BX waitQ2 BC popCMGT <SX50,<VA$WC>>JM 2.formatd/nvQ2 <SX01,<IS51>+" archived commands"> <PR@01><EX><EI><PRNo window>{2} {{5uhdel,uhlist}} Delete|List commands containing substring from STACKALL.SAV command history archive file [CLD rev.11/27/13] {2}<IF<VA$WA>{greater_than}0><IF<VA|50>{greater_tha n}0>BX es 1Q2 DX <SX01,<IS50>><SX02,@upr(<VA$FR>)><SX50,<VA $ED>>JM 2.GetPathQ2 <SX50,<IS50>+"\STACKALL.SAV">BX exist <PV50>Q2 <IF@not(<ER>)> <SU03,BX ab/nvQ2 <IF<VA$WS>{less_than}1>BX rsQ2 <EI>> <LBa>BX gofile <PV50>Q2 <IF@not(<ER>)><GT03><GLa><EI><SX04,< VA$WA>> BX func #<PV04>Q2 BX ca/100 <PV50>Q2 BX waitQ2 <SX04,<VA$WA>> BX func #<PV04>Q2 BX ne/100Q2 AS <SV04,DP AS CP YD AS ><SX05,0> <LBc>BX se [999]<PV01>[999]Q2 <IF@not(<ER>)><SX05,<PV05>+1>YD <PV04><GLc><EI><IF<PV05>{less_than}1><S X01,""""+<IS01>+""" not found in "+<IS50>><LBd><GT03><GT03>DO F.2D <PR@01><EX><EI> <IF"DN "{238}<IS04>{less_than}0>AS TF DO FF <IF<IS02>{240}"DE"><LBe><SX05,"Delete ALL of these commands? (y|N)"><PR@05><SX05,<RK>><SV06,><SX05,< VA$KC>><SX05,"|"+<IS05>+"|"> <SV07,|71|92|=TF |14|72|100|=LU |73|93|=PU |75|101|=CL |77|103|=CR |79|96|=BF |80|102|=LD |81|97|=PD |> <IF<IS07>{240}<IS05>><XS07,05,,08,09><SV07,=& gt;<XS09,07,,07,08> <SV07,|><XS08,07,06,,07><EI><IF<VA|06>{greate r_than}0><PV06><GLe><EI> <IF<VA$KC>{less_than}{greater_than}21><SV01,No operation><GLd><EI> DX <GT03><SV04,DP DN ><SX05,0>TF <GLc><EI><EI><IF<IS02>{240}"LI"> AS <GT03>BC popCMGT <PR{less_than}Helpkey{greater_than} copies command under cursor to CMline><EX><EI><SV01,Done><IF<IS02>{240}"D E"> <SX01,<IS01>+": SAve STACKALL.SAV to make deletions permanent; otherwise, ABort file"><EI>TF <PR@01><EX><EI><SX01,<IS50>+" does not exist"><PR@01><EX><EI><PRUHDEL|UHLIST [substring_in_command(s)_to_ delete|list]{less_than}Helpkey{greater_than}><EX><EI> <PRTwo (2) available windows required>{2} {{5ahuh}} Aleatory HUH [CLD rev.12/12/13] {2}<IF<VA$ET>{240}"3.33"!<VA$ET>{240}"7.77">;*; 1 in 500 chance ;*;<IF<VA$ET>{240}"3.33"!<VA$ET>{240}"5.55"!<VA$ET> {240}"7.77">;*; 1 in 333 ;*;<IF<VA$ET>{240}".77">;*; 1 in 100 ;*;<IF<VA$ET>{240}".17"!<VA$ET>{240}".71">;*; 1 in 50 ;*;<IF<VA$ET>{240}".7">;*; 1 in 10 JM 2.HIDE:01-03,50,99Q2 JM 2.huh/nvQ2 BX pQ2 JM 2.UNHIDEQ2 ;*; <EI>;*;<EI><EI><EI><EI>{2} {{5huh,huh/*}} Have Unlimited Hint: Add the current command Stack to omnibus command archive STACKALL.SAV [CLD rev.12/12/13] {2}<SX01,<VA$FR>><SV99,Python_EXE>JM 2.RegDataQ2 <IF<VA|99>{greater_than}0>;*; DX BX es 1Q2 <SX50,<VA$ED>>JM 2.GetPathQ2 <SX02,<IS50>>;*; BX ernv <PV02>\623.SAVQ2 BX waitQ2 ;*; <IF<VA@623>{240}"{190}">BX sa %623,<PV02>\623.savQ2 BX waitQ2 <EI>;*; BX exist <PV02>\stackall.savQ2 ;*; <IF<ER>><SV03,>BX sa %03,<PV02>\stackall.savQ2 BX waitQ2 <EI>;*; <SX50,"from xy import outok, EDDIR, xyread, xywrite, GetStackall, PutStackall # outok() # (current) Stack: newstack = b'' try: newstack = xyread(EDDIR+'/623.sav').replace(b'\xbe', b'\r\n') except: pass oldstack = GetStackall() # (archived) Stack # Grandfather STACKALL.SAV using Ascii-190 separator: oldstack = oldstack.replace(b'\xbe', b'\r\n') if newstack: oldstack += newstack s = sorted(set(oldstack.split(b'\r\n'))) cbs = bytearray(b'') for i in s: if i: cbs.extend(i + b'\r\n') if cbs: PutStackall(cbs) # xywrite(b'Stack merged into STACKALL.SAV') # else: xywrite(b'Oops (unexpected): STACKALL.SAV not modified') # outok(1) # end">;*; ;*;JM 2.XPyL/X/50Q2 ;*; JM 2.XPyL//XQ2 ;*; BX ernv <PV02>\623.SAVQ2 BX waitQ2 <IF"/"{238}<IS01>{less_than}0> <PRStack merged into STACKALL.SAV><EI><EX> <EI>JM 2.huhxpl<IF<IS01>{240}"/">/nv<EI>Q2 <EX>;*; Run pure-XPL HUH if Python not installed{2} {{5huhxpl*}} HUH (Have Unlimited Hint-pure XPL version) [CLD rev.12/12/13 (uses CMSORT.EXE for Win32 OSes)] {2}<IF<VA$WA>{greater_than}0>BX es 1Q2 DX <SX01,<VA$FR>><SX50,<VA$ED>>JM 2.GetPathQ2 ;*; <SV02,><IF"{190}"{238}<VA@623>==0><SX02,<IS50> ;+"\623.SAV"> BX sa %623,<PV02>Q2 BX waitQ2 <EI>;*; <SX03,<IS50>+"\STACKALL.">BX exist <PV03>SAVQ2 ;*; <IF<ER>><SV04,>BX sa %04,<PV03>SAVQ2 BX waitQ2 <EI>;*; <SU05,<SX04,<VA$WA>>BX func #<PV04>Q2 ><GT05>;*; BX gofile <PV03>SAVQ2 <IF<ER>>BX ca/100 <PV03>SAVQ2 <EI>XP BX waitQ2 ;*; <IF<VA|02>{greater_than}0>BX me <PV02>Q2 BX waitQ2 <EI>;*; TF BX ch/1 {190}Q2 BX waitQ2 BX ch {190} [wC]Q2 BX waitQ2 ;*; <SX04,<VA$SK>><SX04,"BX d sk="+<IS04>+"Q2 ">BX d sk=4,80Q2 ;*; BX st/nv <PV03>TM0Q2 ;*; BX exist <PV50>\cmsort.exeQ2 <IF@not(<ER>)>JM 2.GetXyOSQ2 ;*; <IF"W"{238}<VA@652=2>==0&"W9"{238}<VA@652=2>{less_than}{g reater_than}0>; *; BX dos/nv/x/z /c <PV50>\cmsort.exe /B /D /Q <PV03>TM0 <PV03>TM1Q2 <GLa><EI>;*; <EI>BX sort/nv <PV03>TM0,<PV03>TM1Q2 <LBa><IF@not(<ER>)>BX waitQ2 <PV04>;*; BX copy/nv <PV03>TM1 <PV03>SAVQ2 BX waitQ2 ;*; BX ernv <PV03>TM0Q2 BX waitQ2 BX ernv <PV03>TM1Q2 BX waitQ2 ;*; <GT05>BX ca/100 <PV03>SAVQ2 ;*; <LBb>BX ch [wC][wC] [wC]Q2 <IF@not(<ER>)>BX waitQ2 <GLb><EI>;*; BX st/nv <PV03>SAVQ2 <IF<VA$WS>{less_than}1>BX rsQ2 <EI>;*; <IF<IS01>{240}"/"><SX01,<VA$MG>><PR@01>< ;EX><EI> <PRStack merged into STACKALL.SAV><EX><EI>;*; <PRSort error: STACKALL.SAV not modified>BX pQ2 <EX><EI><PRNo window>{2} {{5addstackall}} Merge external STACKALL.SAV-type command archive and/or current Stack (S/G 623) into STACKALL.SAV [CLD rev.11/2/13] {2};*; Usage: ADDSTACKALL [d:\path\stackall_filename]{less_than}Helpkey{greater_than} BX es 1Q2 <IF<VA|50>{greater_than}0><SX01,<IS50>><EI> ; <SX50,<VA$ED>>JM 2.GetPathQ2 ;*; <SX51,<IS50>+"\">JM 2.tmpfileQ2 ;*; <SV50,tempfile><SV51,Editor's directory\> <IF<VA|01>{greater_than}0>BX exist <PV01>Q2 <IF@not(<ER>)>;*; <SX02,<IS51>+"STACKALL.SAV">BX exist <PV02>Q2 <IF@not(<ER>)>;*; BX dos/nv/x/z /c copy <PV01>/a+<PV02> <PV50>/b{greater_than}NULQ2 ;*; <IF<VA$RR>==0>BX copy/nv <PV50> <PV02>Q2 <IF<ER>>;*; <SX01,<VA$ER>><SX01,"<VA\"+<IS01>+">">< SX01,<PV01>><PR@01>BX pQ2 <EI>;*; BX waitQ2 BX ernv <PV50>Q2 BX waitQ2 <EI>;*; <IF<VA$RR>{less_than}{greater_than}0><SX02,<VA$RR>& gt; <SX01,"DOS error code "+<IS02>+" while copying "+<IS01>><PR@01> BX pQ2 <EI><EI><EI><EI>JM 2.huhQ2 {2} {{5popCM}} Copy line of text under cursor to CMline [CLD rev.12/13/13] {2}<IF<VA$WS>==1>BX es 1Q2 GT YD DP DM CL DZ <SV50>YD JM 2.str5to3Q2 <IF<VA|50>{less_than}=<VA$SW>-@siz(<VA$P.>)>BC <GT50>YD DO FF <EX> <EI><PRToo long for CMline><EX><EI><PRNo file>{2} {{5str5to3}} Change 5-byters to 3-byters in $tring (S/G50 in|out) [CLD rev.2/1/14] {2}<IF<IS50>{240}"[255+70+70]"!<IS50>{240}"[255+70+69]"&g t;;*; ;*; <SV51,3-byte 255|254> <SV52,1-byte 255|254 [SUb]>;*; ;*; <SV53,1-byte 255> <SV54,1-byte 254> <SV55,special 3- byter|SUb> <SV55,[255+252+254]>NO <SV51,{252}><XS55,51,53,54,54><SV56,{27}X>;*; <SU55,<SX57,<IS50>><SV50,>;*; <LBa><IF<IS57>{240}<IS51>><SV58,><XS57, 51,59,58,58>;*; <SX50,<IS50>+<IS59>>;*; <IF<VA|58>{greater_than}1><SV60,><XS58,56,59,59,60& gt; <SV61,><XS60,56,62,62,61>;*; <IF<VA|59>==1&<VA|62>==1>;*; <SX50,<IS50>+<IS52>+<IS59>+<IS62>><SX57 ,<IS61>><GLa><EI><EI>;*; <SX50,<IS50>+<IS51>><SX57,<IS58>><GLa&g t;<EI><SX50,<IS50>+<IS57>>>;*; <SV51,[255+70+70]><SX52,<IS53>><GT55> <SV51,[255+70+69]><SX52,<IS54>><GT55> <EI>{2} {{5addCM}} Add CMline|DF_block to STACKALL.SAV [CLD rev.11/24/13] {2};*; Must be assigned to key with nn=NOJM(,2,.,a,d,d,C,M,) BX es 1Q2 <PRWorking><SU45,DZ <IF<VA$DE>{less_than}1><SX46,<IS00>+" "><EX><EI><SV46><SV47, ><LBa><IF<IS46>{240}" "&<VA|48>{greater_than}0><SV48,><XS46,47,49,,48>;*; <IF<VA|48>{greater_than}0><SX46,<IS49>+"[wC]"+<I S48>><GLa><EI><EI> <IF" [255+192+143][255+192+142]"{238} (<IS46>+"[255+192+143][255+192+142]"){less_than}0><SX46,< IS46>+" "><EI>>;*; <GT45><IF<VA|46>{greater_than}2>;*; <SV46,CMline> <SX50,<VA$ED>>JM 2.GetPathQ2 <SX51,<IS50>+"\">JM 2.tmpfileQ2 ;*; <SX47,<IS50>>;*; <SV47,tempfile><SV51,Editor's directory\> <SX45,<IS51>+"STACKALL.SAV">BX exist <PV45>Q2 <IF@not(<ER>)>;*; BX sa %46,<PV47>Q2 <IF@not(<ER>)>;*; BX waitQ2 BX apt <PV47>,<PV45>Q2 <IF@not(<ER>)>;*; BX waitQ2 JM 2.huhQ2 <SX45,"CMline|DeFine added to "+<IS45>>;*; <LBb>BX ernv <PV47>Q2 <PR@45><EX><EI><EI>;*; <SX45,<VA$ER>><SX46,"<VA\"+<IS45>+">">< SX46,<PV46>><GLb><EI>;*; BX sa %46,<PV45>Q2 BX waitQ2 <GLb><EI><PREmpty CMline!>{2} {{5formatd*}} Format digits (S/G 50 in, S/G 51 out) [CLD rev.2/10/14] {2}<IF<VA|50>{less_than}1&<VA$DF>{less_than}1><LBa& gt;<PRFORMATD[/NV] number|DeFined_number{less_than}Helpkey{greater_than} (S/G 51 out)><EX><EI> <SV51,><IF<VA|50>{less_than}1>DZ <SV50><SV52,!><EI> <SX51,<IS50>><SV53,><SV54,><IF<IS51>{24 0}<VAEU1>> <SX55,<VAEU1>><XS51,55,56,,53><SX51,<IS56>> ;<EI> <IF<VA{21}51>{less_than}1><GLa><EI> <SX55,<IS51>><SV51,><SV56,{27}N{27}N{27}N{14}> <LBb><IF<VA|55>{greater_than}3><SX55,<IS55>+" {14}"><XS55,56,54,57,58> <SX55,<IS54>><SX51,<VAEU2>+<VA@57{14}1>+<I S51>><GLb><EI> <IF<VA|53>{greater_than}0><SX51,<IS51>+<VAEU1> ;+<IS53>><EI> <SX51,<IS54>+<IS51>><IF<VA|52>{greater_than}0 >DN <GT51><EI><IF"/"{238}<VA$FR>{less_than}0><PR@ 51><EI>{2} {{5Stackbox}} Stack list|hint utility v2 [CLD Rev.10/14/08; rev.8/11/13 to call frame UH if hint not found {2};*; As "Hint" key: nn=NOXHJM(,2,.,s,t,a,c,k,b,o,x,) ;*; or: STACKBOX [hint]{less_than}Helpkey{greater_than} XH BX es 1Q2 <IF<VA|623>{less_than}2!"{190}"{238}<VA@623>{less_than}0& gt; <SV01,Empty Stack or STACK.PM not installed><PR@01><EX><EI> JM 2.CMlineQ2 <IF<VA|50>{greater_than}- 1><SX616,<IS50>><EI> ;*; JM 2.ahuhQ2 ;*; <IF@upr(<IS616>){238}@upr(<IS623>){less_than}0> <SX50,<IS616>>JM 2.uhQ2 <SV616,>;*; ;*;<PRNo Stack Match>;*; <EX><EI><SV02,><IF<IS616>{240}"{190}">< SV616,><EI><LBa><SV03,{190}> <SV04,><SX05,0><SX06,<IS623>><LBb><IF&l t;VA|06>{greater_than}1><SV07,> <XS06,03,08,,07><SX06,<IS07>><SV07,> <IF<VA|08>{greater_than}0&(<VA|616>{less_than}1! @upr(<IS08>){240}@upr(<IS616>))><SX04,<IS04>+< ;IS08>+" "><SX05,<PV05>+1><EI><GLb><EI><IF< ;PV05>{less_than}2><SV616,><SV01, ><XS04,01,01,,03>BC <GT01><EX><EI><IF<VA|02>{greater_than}0>&l t;GT04>TF ;*; <SX07,0><GLd><EI><SX06,<PV05>><SX07,< ;VA$SW>-5-<VALM{less_than}DI>> <IF<PV06>{greater_than}<VA$SL>- 5><SX06,<VA$SL>-5><EI> DX BX window/nv n, <IF<VA$VE>{greater_than}"V4.099">17,3,63,20<GLc><EI > 3,1,<PV07>,<PV06><LBc>Q2 ;*; <IF@not(<ER>)><SX09,<VAIP>><SX09,"BX d ip="+<IS09>+"Q2 FF "> BX d ip=0di,2di,0diQ2 BX ne/1<IF<IS04>{240}"<"!<IS04>{240}">">00<EI> ;Q2 <GT04><SX07,0><LBd><SV08,>BX jmp <PV07>Q2 DO FF <SV04,><SX05,<IS05>><SV03,items><IF<VA|616 >{greater_than}0> <SV03,matches><EI>;*; <SX96,<IS05>+" Stack "+<IS03>+": {less_than}C{greater_than}Mline| {less_than}cr{greater_than}|{less_than}H{greater_than}key {less_than}P| -{greater_than}urge {less_than}S{greater_than}ort| {less_than}R{greater_than}evSort|{less_than}U{greater_than}nsort Esc"> BX jmp <PV07>Q2 <SV10,><LBe>DO FF JM 2.RK:01Q2 YD <SX11,<VA$KC>><SX11,"|"+<IS11>+"|"><SV03,|71| 92|=TF |14|72|100| =LU |73|93|=PU |75|101|=CL |77|103|=CR |79|96|=BF |80|102|=LD |81|97| =PD |><IF<IS03>{240}<IS11>><XS03,11,,12,13><SV 03,=><XS13,03,,03,12> <SV03,|><XS12,03,01,,03><EI><SX11,<VA@11|2>&g t;<SX11,<VA@11|1>> <IF<PV11>{less_than}2><SX04,<IS616>><LBf>& lt;SV01,><SV02,><SV03,> <SV05,><SV06,><SV07,><SV10,><SV11,><SV1 2,><SV13,><SV96,><SV616,> JM 2.ab/nvQ2 <SV48,><SV49,><IF<VA|04>{greater_than}0> BC <GT04><EI><PV09><SV09,><IF<VA|08>{great er_than}0> BX esQ2 DO FF <SX627,<IS04>>JM 2.$SQ2 <SV04,> <IF<IS08>{240}"U"><SV08,>JM 2.PrsCMlineQ2 <EX><EI><PV08><EX><EI>;*; <SV01,><IF<VA$MG>{less_than}{greater_than}""><SX01, <VA$MG>><EI><PR@01> <EX><EI><IF"SR"{240}<IS01>><SX04,<VA$SK> ;><SX06,<VA$SW>><SX07,1> <IF"R"==<IS01>><SX07,2><EI>BX d sk=<PV07>,<PV06>Q2 DX BF YD DF TF DF BX sort/nvQ2 BX waitQ2 <SV1816,>;*; BX d sk=<PV04>Q2 TF DO F.2D <SV02,!><GLe><EI><IF"U"==<IS01>>DX BF YD DF TF DF DN <SV02,!><GLa><EI>;*; <IF"|12|25|28|35|45|46|67|74|104|"{240}("|"+<IS11>+"|")& @upr(<IS01>)==<IS01>!"XC $2 Q8 $X "{240}<IS01>>YD DX BX seb [wC]Q2 <IF<ER>>TF <GLg><EI>CR <LBg><SX07,<CP>>D F BX se/f [wC]Q2 DF <SV04><IF"XXC "{240}<IS01>!"|28|67|104|"{240}("|"+<IS11>+"|")><SV08, XC ><EI> <IF"H$2 Q8 $X "{240}<IS01>><SV08,U><EI> <IF("|"+<IS11>+"|"){238}"|12|25|74|"{less_than}0><GLf> <EI>;*; DM CR DZ DN <SX627,"{190}M{190}P"+<IS04>>JM 2.$SQ2 <SX05,<PV05>-1><IF<PV05>{less_than}2>TF YD DF BX se/f [wC]Q2 DF <SV04>YD <EI><GLd><EI><IF<VA|01>==1>LU <SU04,<SX50,<CP>>BX se [999][wC]<PV10>[999]Q2 <IF@not(<ER>)>CL <EI>><SX10,<IS10>+<IS01>><GT04><IF&l t;CP>{greater_than}<PV50>><GLe><EI> <IF<VA|10>{greater_than}1><SX10,<IS01>>LD <GT04><IF<CP>{greater_than}<PV50>><GLe>< ;EI>DX TF BX se [999]<PV10>[999]Q2 <IF<CP>==1>CL <SX10,<IS01>>JM 2.ReJuMPQ2 <GT04><IF<ER>>TF <EI><GLe><EI><EI> TF <SX10,<IS01>><GT04><GLe><EI><IF<VA|0 1>{greater_than}2& "CU CD LU LD MU MD CR CL LR LL LB LE EL ER PU PD TF BF HM BS "{240}<IS01>><PV01><EI><GLe><EI><PRN o window>{2} {{5finito}} Optionally Save the Stack, then Quit Unconditionally RJH LastRev.8/7/08 CLD rev.7/27/13 (HUH) {2}<IF<VA$WO>{greater_than}1><LBA><IF<VA$ED>{ 240}".DLL"&<VA$WO>{less_tha n}3&(<VA$FI>{240}"["!<VA$WS>{less_than}{greater_than}1)>& lt;IF<VA$WO>{great er_than}1>AS <IF<VA$WN>{less_than}{greater_than}66>AS <LBB><PRWindows open><EX><EI>AS <EI><LBC><IF<VA|620>{greater_than}0>BC <SV01,><IF<VA|50>{greater_than}0><SX01,<IS50> ><EI> <IF<VA|01>{less_than}1> ;*; ;*; Fully qualified d:\path\filename in which to save Stack <SV99,Stored_Stack>JM 2.RegData/RQ2 <SX01,<IS99>><EI><SX50,"S"+<IS01>> JM 2.stackauxQ2 BX waitQ2 <EI>BX ab/nvQ2 <SX50,<VA$ED>>JM 2.GetPathQ2 <SX49,<IS50>+"\KillNB.exe">BX exist <PV49>Q2 <IF@NOT(<ER>)><IF<VA$VE>{less_than}"V4.1">BX exist <PV50>\UNDOPIDQ2 <IF@NOT(<ER>)><SX51,"<VA="+<IS50>+"\UNDOPID,PID= >"><SX51,<PV51>> BX do/nv/x/z <PV49> <PV51>Q2 <EI><EI>JM 2.MyPIDQ2 <IF<VA|50>{greater_than}0>BX del/nv <PV51>DATQ2 BX do/nv/x/z <PV49> <PV50>Q2 <EX1><EI><EI>JM 2.huhQ2 BX quit/nvQ2 <EX1><EI><GLB><EI><IF<VA$WS>==1>< IF<VA$ED>{240}".DLL"><GLA><EI><GLB><EI> <GLC>{2} {{5web}} Open URL in new browser tab (XPyL) [CLD rev.9/14/13] {2}DX BX es 1Q2 <SV01,><IF<VA|50>{greater_than}0><SX01,<IS50> ><EI>;*; <IF<VA|01>{less_than}1> <SV02,><IF<VA$TX>{less_than}1><SV02,GH ><EI>DZ ;*; <IF<VA$DE>{greater_than}0><SV01><EI><PV02> <EI>;*; <IF<VA|01>{less_than}1> <IF<VA$WS>{greater_than}1><SX01,<VA$DR>><EI&g t;<EI>;*; <IF<VA|01>{less_than}1> <IF<VA$WS>==1&<VA$TX>{greater_than}0><SX50,<CP&g t;>BX seb [wC]Q2 <IF<ER>>LB <EI>JM 2.FindNextURLQ2 <SV01>YD JM 2.ReJuMPQ2 <EI>;*; <IF<VA|01>{greater_than}0>;*; ;*; Import URL alias list from XYWWWEB.REG <LBa><SX02,0><SV03,><LBb><SX02,<PV02>+1 >;*; <SX99,"URL"+<IS02>>JM 2.RegDataQ2 <IF<VA|99>{greater_than}0>;*; <IF<VA|03>{greater_than}0><SX03,<IS03>+"\n">< EI><SX03,<IS03>+<IS99>> <GLb><EI>;*; <SX50,"import webbrowser url = '"+<IS01>+"' if '\\' in url: url = 'file:///' + url.replace('\\', '/') urls = '"+<IS03>+"' if url + '=' in urls: # urls = 'alias1=url1\nalias2=url2\n ...' url = {x.split('=')[0]: x.split('=')[1] for x in urls.split('\n')}[url] if '.' not in url: url = 'www.' + url + '.com' if '://' not in url: url = 'http://' + url webbrowser.open(url, new=2) ">JM 2.XPyL//XQ2 <EX><EI><PRNo URL><EX><EI><GLa>{2} {{5lookup}} Web lookup via frame YA* framename + search_term [CLD rev.11/9/13] {2}<IF<VA|50>{greater_than}0><LBa><SV01, ><XS50,01,99,01,01>;*; <IF"YA"{238}@upr(<IS99>){less_than}{greater_than}0> <SX99,"YA"+<IS99>><EI>;*; JM 2.RegDataQ2 <IF<VA|99>{greater_than}0>;*; <SX50,"import webbrowser url = '"+<IS99>+"' if '://' not in url: url = 'http://' + url term = '"+<IS01>+"' newterm = term for char in term: if ( ord(char) in range(45) or ord(char) in (47, 58, 59, 61, 63, 64, 91, 93) or ord(char) in range(127, 256) ): newterm = newterm.replace( char, '%'+'{0:0{greater_than}2s}'.format(hex(ord(char)).split('x')[1]) ) url += newterm webbrowser.open(url, new=2)">JM 2.XPyL//XQ2 <EX><EI><EI>;*; DZ <IF<VA$DE>{greater_than}0><SV50><GLa><EI>; *; <PRLOOKUP [YA][suffix] seach_term(s){less_than}Helpkey{greater_than}>{2} {{5veritas}} Wine|Liquor search via wine-searcher.com (XPyL) [CLD rev.11/12/13] {2}<IF<VA|50>{greater_than}0><SX01,<IS50>>;*; <SV02,'><LBa><IF<IS01>{240}"'">;*; replace single quotes with hex equivalent <SV03,><XS01,02,04,,03><SX01,<IS04>+"%27"+<IS03& gt;><GLa><EI>;*; <SX50,"from webbrowser import open keywords = '"+<IS01>+"' if ' ' in keywords: keywords = keywords.replace(' ','+') open('http://www.wine-searcher.com/find/' + keywords, new=2)">JM 2.XPyL//XQ2 <EX><EI><PRVERITAS [keyword(s)]{less_than}Helpkey{greater_than}{2} {{5montypy}} Monty Hall Paradox (XPyL) [CLD rev.1/6/14] {2};*; For information, issue: ;*; WEB en.wikipedia.org/wiki/Monty_Hall_problem<Helpkey> BX es 1Q2 <PRWorking...><IF<VA|50>{less_than}0><SV50,>< EI>;*; <SX01,<IS50>><SV02,> <IF<IS01>{240}" "><SX02,<VA@01 2>><SX01,<VA@01 1>><EI>;*; <SV50,# setup from xy import outok, xywrite outok() import random, sys doors_number = 3 # 'Let's Make A Deal' default times = 10000 # default iterations ><IF<VA|01>{greater_than}0><SX50,<IS50>+" try: doors_number = max("+<IS01>+", 3) "><EI>;*; <IF<VA|02>{greater_than}0><SX50,<IS50>+" times = max("+<IS02>+", 100) "><EI>;*; <IF<IS50>{240}"try:"><SX50,<IS50>+"except: pass "><EI>;*; <SX50,<IS50>+"random.seed() # main [the problem] doors = list(range(1, doors_number + 1)) contestant_wins, new_door_wins = 0, 0 for n in range(times): car = random.choice(doors) contestant_door = random.choice(doors) goats = [g for g in doors if g is not car and g is not contestant_door] zonk = random.choice(goats) other_doors = [d for d in doors if d is not zonk and d is not contestant_door] new_door = random.choice(other_doors) if contestant_door == car: contestant_wins += 1 if new_door == car: new_door_wins += 1 # end main output = ('\r\n'+str(doors_number)+' doors, '+str(times)+' times\r\n'+ '-'*len(str(doors_number)+' doors, '+str(times)+' times')+'\r\n'+ 'Contestant\'s door had car '+str(contestant_wins)+' times\r\n'+ 'New door had car '+str(new_door_wins)+' times\r\n\r\n') diff = abs(new_door_wins - contestant_wins) lower = min(new_door_wins, contestant_wins) if lower {greater_than} 0: pctdiff = 'or {0:.1f}%'.format(100*diff/lower) else: pctdiff = '' if new_door_wins {greater_than} contestant_wins: output += 'New door better by '+str(diff)+' '+pctdiff elif new_door_wins {less_than} contestant_wins: output += 'Contestant\'s door better by '+str(diff)+' '+pctdiff print('Contestant\'s door better by', diff, pctdiff) else: output += 'It\'s a tie' output += '\r\n' if not xywrite(output.encode()): xywrite(b'[Fail]') outok(1)>JM 2.XPyL/X/DGQ2 {2} {{5zappy}} Zap End-of-File 1Ah|Ascii-26|Ctrl-Z|EOF from file (XPyL) [CLD rev.8/18/13] {2}<IF<VA|50>{less_than}1><IF<VA$WS>{greater_than}0 ><IF<VA$MO>{less_than }1><IF"["{238}<VA$FI>{less_than}0>;*; <SX50,<VA$FP>><IF<VA$WS>{greater_than}1&<VA$TX&g t;{greater_than}0><SX50,<VA $DR>><EI>;*; <LBa>JM 2.swapslashQ2 ;*; <SX50," # Rev.8/18/13: read entire file only if b'\x1a' EoF is present fn = '"+<IS50>+"' newEoF = None with open(fn, 'rb') as f: f.seek(-1, 2) fd = f.read() if fd == b'\x1a': newEoF = f.tell() - 1 f.seek(0) fd = f.read(newEoF) if newEoF: with open(fn, 'wb') as f: f.write(fd) ">JM 2.XPyL//XQ2 <PRDone - Do not SAve file again><EX><EI><PRSecondary copy or Untitled file - No operation><EX><EI><PRFile modified - No operation><EX><EI><PRNo file><EX><EI>BX exist <PV50>Q2 <IF@not(<ER>)><GLa><EI><PRNon-existent file @50>{2} Original: {5zappy} Zap End-of-File 1Ah|Ascii-26|Ctrl-Z|EOF from file (XPyL) [CLD rev.8/11/13] {2}<IF<VA|50>{less_than}1><IF<VA$WS>{greater_than}0 ><IF<VA$MO>{less_than }1><IF"["{238}<VA$FI>{less_than}0>;*; <SX50,<VA$FP>><IF<VA$WS>{greater_than}1&<VA$TX&g t;{greater_than}0><SX50,<VA $DR>><EI>;*; <LBa>JM 2.swapslashQ2 ;*; <SX50," fn = '"+<IS50>+"' with open(fn, 'rb') as f: fd = f.read() if fd[-1] == 26: with open(fn, 'wb') as f: f.write(fd[:-1]) ">JM 2.XPyL//XQ2 <PRDone - Do not SAve file again><EX><EI><PRSecondary copy or Untitled file - No operation><EX><EI><PRFile modified - No operation><EX><EI><PRNo file><EX><EI>BX exist <PV50>Q2 <IF@not(<ER>)><GLa><EI><PRNon-existent file @50>{2} {{5gsfpy*}} Get Short Filename (XPyL) [CLD rev.12/25/13] {2}BX es 1Q2 <IF<VA|50>{less_than}1>DZ <IF<VA$DE>{greater_than}0><SV50><EI><EI>&l t;IF<VA|50>{greater_than}0>;*; <SV01,><SX02,<VA$FR>><IF<IS02>{240}"/">< ;SV01,/><XS02,01,01,01,01><EI>;*; <SX50,"from xy import outok, OUTFN, xywrite from win32api import GetShortPathName outok() long_name = r'''"+<IS50>+"''' try: xywrite( GetShortPathName(long_name), OUTFN, 'wt' ) except Exception as e: xywrite( str(e).encode() ) outok(1)"> JM 2.XPyL/X/<IF<VA|01>{greater_than}0><PV01><GLa>&l t;EI>PR<LBa>Q2 <EX> <EI><PRGSFPY[/50|/CM|/ME|/PR|/W] [LongPathName]|[DeFined LongPathName]{less_than}Helpkey{greater_than}>{2} {{5testpy}} XPyL test frame (CLD rev.7/19/13) {2}<SV50,import xy xy.outok() with open(xy.OUTFN, 'wb') as f: f.write(xy.xywild('a', 'E', 'i', 'O', 'u')) f.write(b'\r\n') f.write(xy.xy3bchar('a', 'E', 'i', 'O', 'u')) f.write(b' {less_than}== 3-byters\r\n') f.write(xy.xyfunc('BC', 'GT', 'DO', 'FF', '{less_than}{less_than}')) f.write(b'\r\n') f.write(xy.xycm('SV50,arg')) f.write(b'\r\n') f.write(xy.xychar(256, 266, 499, 998, 1013)) f.write(b'\r\n') xy.outok(1) xy.os.system('cls')>JM 2.XPyL/x/wQ2 XP TF GH {2} {{5demo#}} Demos 1 and 2 from XYPY.TXT [CLD rev.10/13/13] {2}<SX01,<VA$FR>><SV50, from xy import OUTFN, outok, xywrite, xyfunc, xycm, fBX outok() for varname in 'BC', 'GT': exec(varname + ' = xyfunc(varname)') xywrite(fBX('es 1') + xycm(b'SX01,\xaeVA$NW\xaf') + fBX('d nw=3') + fBX('ne/100') + BC + b'This Untitled window will ABort in 5 seconds...' + GT + b'[Nothing here in the text window]' + xycm('PRWaiting...') + fBX('p 5', 'ab') + fBX(b'd nw=\xaePV01\xaf') + BC + GT + xycm('PRDone', 'EX')) outok(1) >JM 2.XPyL/X/<IF<IS01>{240}"1">W<GLa><EI>50<LBa&g t;WQ2 <IF<IS01>{240}"2"><PV50><PRDone!><EX><E I> XP <PRABort window after viewing>{2} {{5demo1a}} Demos 1a from XYPY.TXT [CLD rev.10/13/13] {2}<SV50,from xy import outok, xywrite outok() xywrite(b'\xff\x82\xabes 1\xff\x82\x7f\xaeSX01,\xaeVA$NW\xaf\xaf \xff\x82\xabd nw=3\xff\x82\x7f\xff\x82\xabne/100\xff\x82\x7f \xff\x81\x1fThis Untitled window will ABort in 5 seconds... \xff\x80}[Nothing here in the text window]\xaePRWaiting...\xaf \xff\x82\xabp 5\xff\x82\x7f\xff\x82\xabab\xff\x82\x7f \xff\x82\xabd nw=\xaePV01\xaf\xff\x82\x7f\xff\x81\x1f \xff\x80}\xaePRDone\xaf\xaeEX\xaf') outok(1)>JM 2.XPyL/X/WQ2 XP <PRABort window after viewing>{2} {{5XyPyREG}} Set RegVar Python_EXE in XYWWWEB.REG [CLD rev.5/27/14] {2}BX es 1Q2 DX <SX50,<VA$ED>>JM 2.GetPathQ2 ;*; ;*; Test for existence (not content) of RegVar Python_EXE: <SX01,"<VA="+<IS50>+"\XYWWWEB.REG,Python_EXE=>"><SX 01,<PV01>> <IF<VA|01>{less_than}1>;*; <SX01,"<VA="+<IS50>+"\XYWWWEB.REG,Python_EXE.1=>">< SX01,<PV01>><EI>;*; <IF<VA|01>{less_than}1><IF<VA$WA>{greater_than}0> ; <SX01,<IS50>+"\xytmp.py">;*; <SX02,<IS50>+"\xpyldata.out">BX ernv <PV02>Q2 BX waitQ2 ;*; <SX03,<IS02>><SV04,\><LBa><IF<IS03>{240 }"\"><SV05,><XS03,04,06,,05> <SX03,<IS06>+"/"+<IS05>><GLa><EI>;*; <SX04,"import sys with open('"+<IS03>+"', 'wt') as f: f.write(sys.executable) # end">BX sa %04,<PV01>Q2 BX waitQ2 ;*; BX do/nv/x/z python.exe <PV01>Q2 BX waitQ2 ;*; <IF<VA$RR>{less_than}1>BX exist <PV02>Q2 <IF@not(<ER>)>;*; BX exist <PV50>\XYWWWEB.REGQ2 <IF@not(<ER>)>BX gofile <PV50>\XYWWWEB.REGQ2 <IF@not(<ER>)>BX ab/nvQ2 <EI>;*; BX ca/100 <PV50>\XYWWWEB.REGQ2 ;*; BX se [wC]Python_EXE=[wO][wC]Python_EXE.1=Q2 ;*; <IF<ER>>BX se [RD]Q2 <IF<ER>>BF BX seb ;[wC];Q2 <EI>LB ;*; <SV01,[Python] Python_EXE= ; ><GT01>LU LU LE <EI>BX me <PV02>Q2 BX waitQ2 YD DF LE DF DN ;*; BX stQ2 BX waitQ2 <IF<VA$WS>==0>BX rsQ2 <EI><EX><EI><PRUnexpected: Nonexistent XYWWWEB.REG -- Abort><EX1><EI><EI><PRUnable to set RegVar Python_EXE. Set it manually><EX1><EI><PRWindow needed to configure XYWWWEB.REG><EX1><EI><LB RegVar Python_EXE already configured>{2} {{5updatexypy}} Create xy.py module in Python /Lib/site-packages/xypy directory [CLD LastRev.12/25/13] {2}JM 2.mexypyQ2 JM 2.makexypyQ2 JM 2.xypyver/nvQ2 <PRXyPy updated to v@50>{2} {{5mexypy}} MErge XYPY.FRM into U2 (replace existing frames) [CLD rev.12/25/13] {2}<IF<VA$WA>{greater_than}0>BX es 1Q2 <SV21,><SX22,<VA$U2>><SX50,<IS22>><SV23 ,>;*; <SV99,Edit_Copy_of_U2_File>JM 2.RegDataQ2 ;*; <IF<VA|99>{greater_than}0><SX23,<IS99>><SX50, <IS23>><EI>;*; <IF<VA|22>{greater_than}0&<VA@22>{less_than}{greater_than }"(none)">;*; JM 2.CallorGo/100Q2 <IF<PV51>==1><SV21,!><EI>;*; ;*; TF <SV24,/-- >BX se "<PV24>Start XyPy routines[wC]"Q2 <IF@not(<ER>)>LU LB YD DF ;*; BX se "<PV24>End XyPy routines[wC][wC]"Q2 ;*; <IF@not(<ER>)>DF DN <GLa><EI><EI>;*; YD TF <SV24,{>BX se [wC]{<PV24>Q2 ;*; <IF<ER>><PRLoad the XyWWWEB U2!><EX1><EI>LB ;*; ;*; <LBa><SX50,<VA$ED>>JM 2.GetPathQ2 ;*; BX exist <PV50>\XYPY.FRMQ2 <IF<ER>><PRUnZIP XYPY.ZIP into @50><EX1><EI>;*; BX me <PV50>\XYPY.FRMQ2 BX waitQ2 ;*; <SX24,";U2; {"+"{M*}"+"} "><SX25,<IS50>+"\NO.U2">BX sa %24,<PV25>Q2 <IF<ER>><LBb>BX ab/nvQ2 <SX21,<VA$ER>><SX21,"<VA\"+<IS21>+">">< SX21,<PV21>><PR@21><EX1><EI> BX waitQ2 ;*; BX load <PV25>Q2 <IF<ER>><GLb><EI>BX waitQ2 ;*; BX saQ2 <IF<ER>><GLb><EI>BX waitQ2 ;*; <IF<VA|23>{greater_than}0>BX sa/nv <PV22>Q2 <IF<ER>><GLb><EI> BX waitQ2 <EI>;*; BX ()BX load <PV22>Q2 <IF<VA$ER>{less_than}{greater_than}11><GLb><EI> BX waitQ2 ;*; GH BX ernv <PV25>Q2 <IF<VA|21>{greater_than}0>TF BX se 5xypyverQ2 LU LB <EI><IF<VA|21>{less_than}1>BX ab/nvQ2 <IF<VA$WS>{less_than}1> BX rsQ2 <EI><EI><EX><EI><EI><PRNo window><EX1> {{5makexypy}} Create xy.py module in Python /Lib/site-packages/xypy directory [CLD LastRev.12/15/13] {2}JM 2.XyPyREGQ2 <IF<VA$WA>{greater_than}0>BX es 1Q2 DX <PRWorking...>;*; <SV99,Python_EXE>JM 2.RegData/RQ2 <IF<VA|99>{greater_than}0><SX50,<IS99>>JM 2.GetPathQ2 <SX91,<IS50>+"\Lib">BX exist <PV91>\xy.pyQ2 <IF@not(<ER>)>BX ernv <PV91>\xy.pyQ2 BX waitQ2 <EI> <SX91,<IS91>+"\site-packages"><SX50,<VA$ED>>JM 2.GetPathQ2 <SX92,<IS50>>;*; <SX93,<VA$PA>><SX94,"BX "+<VA@93:1>+":Q2 BX cd "+<IS93>+"Q2 "> <SX93,<VA@92:1>>BX <PV93>:Q2 BX cd <PV92>Q2 ;*; BX exist <PV92>\XYPY.TPLQ2 <IF@not(<ER>)>JM 2.swapslashQ2 <SX93,<IS50>><LBa><SX50,<IS92>+"\XYPY.TPL"> ;JM 2.CallorGo/1Q2 <IF<PV51>==1>BX ab/nvQ2 <GLa><EI> BX sa/ne/nv <PV92>\xypy.tmpQ2 <IF@not(<ER>)>BX waitQ2 ;*; TF BX ch/1 "[wC]EDDIR = ''"[wC]EDDIR = '<PV93>'"Q2 ;*; <IF@not(<ER>)>BX saQ2 BX waitQ2 BX ab/nvQ2 <IF<VA$WS>{less_than}1>BX rsQ2 <EI>;*; <SX93,"@echo off if not exist "+<IS91>+"\xypy.pth echo .\xypy{greater_than} "+<IS91>+"\xypy.pth if not exist "+<IS91>+"\xypy\*.* mkdir "+<IS91>+"\xypy :: Next line creates xy.py, to avoid XCOPY Directory or File prompt echo.{greater_than}"+<IS91>+"\xypy\xy.py xcopy /q/y "+<IS92>+"\xypy.tmp "+<IS91>+"\xypy\xy.py{greater_than}nul xcopy /q/y "+<IS92>+"\xypy.tmp "+<IS92>+"\xy.py{greater_than}nul del "+<IS92>+"\xypy.tmp">BX sa %93,<PV92>\xypy.batQ2 <IF@not(<ER>)>BX waitQ2 ;*; BX dos/nv/x/z /c cmd.exe /c <PV92>\xypy.batQ2 ;*; <PV94><IF@not(<ER>)>BX waitQ2 <SX91,"Created "+<IS91>+"\xy.py"><LBb>DO F.2D <PR@91><IF"Created"{238}<IS91>==0><EX><EI> <EX1><EI><EI><SX91,"Error creating "+<IS92>+"\XYPY.BAT -- Abort"><GLb><EI><SX91,"Corrupted XYPY.TPL! Unzip it again><GLb><EI><SX91,<VA$ER>><SX92,"<VA \"+<IS91>+">"><SX92,<PV92>><SX91, "Could not create "xy.py! (Error #"+<IS91>+": "+<IS92>+")"><GLb><EI><SX91,"File "+<IS50>+" does not exist!"><GLb><EI> <SV91,Python not installed or RegVar Python_EXE not configured><GLb><EI> <SV91,No window [MAKEXYPY]><GLb>{2} {{5SV50}} SaVe file contents to S/G 50 (S/G 50 in & out: d:\path\filename in; file contents out) [CLD 1/18/09] {2}<IF<VA|50>{greater_than}0>BX exist <PV50>Q2 <IF@not(<ER>)><IF".DLL"{238}<VA$ED>{less_than}0> <SX49,<IS50>>JM 2.UsurpBQ2 <SX51,"<IF<PV54>{less_than}0><SV"+<IS50>+",>& lt;EI><SX52,<IS"+<IS50>+">>"> <PV51>BX ldpm <PV49>,<PV50>Q2 BX waitQ2 <SX51,"<SX49,<IS"+<IS50>+">+""""><IF<PV54> {less_than}0> BX remove "+<IS50>+"Q2 <EI> <SX"+<IS50>+",<IS52>>"><PV51><SX50,<IS4 9>><EX><EI> <SX50,<IS50>+",50">JM 2.ldnbQ2 <EX><EI><SV50,><EI>{2} {{5swapslash}} Swap "/" for "\" in in_string (S/G 50 in|out) [CLD] {2}<SV51,\><LBa><IF<IS50>{240}"\"><SV52,>& lt;XS50,51,53,,52> <SX50,<IS53>+"/"+<IS52>><GLa><EI>{2} /-- End XyPy routines [End file XYPYDOC.TXT]