Skip to content

Instantly share code, notes, and snippets.

@rdipardo
Last active September 2, 2023 20:05
Show Gist options
  • Save rdipardo/0b78f62e1ce481ff0d8f8e80cc298ced to your computer and use it in GitHub Desktop.
Save rdipardo/0b78f62e1ce481ff0d8f8e80cc298ced to your computer and use it in GitHub Desktop.
Notepad++ UDL for Vim script
<?xml version="1.0" encoding="UTF-8"?>
<!--
Description: User Defined Language for Vim script
Author: Robert Di Pardo <https://github.com/rdipardo>
-->
<NotepadPlus>
<UserLang name="Vim script" ext="vim vimrc gvimrc exrc" udlVersion="2.1">
<Settings>
<Global caseIgnored="no" allowFoldOfComments="yes" foldCompact="no" forcePureLC="0" decimalSeparator="0"/>
<Prefix Keywords1="no" Keywords2="no" Keywords3="no" Keywords4="no" Keywords5="no" Keywords6="no" Keywords7="yes" Keywords8="yes"/>
</Settings>
<KeywordLists>
<Keywords name="Comment">1 2 0&quot;</Keywords>
<Keywords name="Delimiters">00&apos; 01 02((&apos; EOL))</Keywords>
<Keywords name="Numbers, prefix1"/>
<Keywords name="Numbers, prefix2">0b 0o 0x #</Keywords>
<Keywords name="Numbers, extras1">A B C D E F a b c d e f + -</Keywords>
<Keywords name="Numbers, extras2"/>
<Keywords name="Operators1">~ ` ! @ % ^ * | ? . , + : / \ ( ) [ ] { } &lt; &gt; = a: b: g: l: s: t: v: w:</Keywords>
<Keywords name="Operators2">&amp;&amp; # - _ is is#</Keywords>
<Keywords name="Folders in code2, open">augroup if for func function while</Keywords>
<Keywords name="Folders in code2, middle">else elseif</Keywords>
<Keywords name="Folders in code2, close">END endif endfor endfunc endfunction endwhile</Keywords>
<Keywords name="Keywords1">abort argv au autocmd augroup awa beval_bufnr beval_col beval_lnum beval_text beval_winid beval_winnr bNext bnext bprevious break breakadd breakdel bufdo bw bwipe bwipeout call catch cclose cd char charconvert_from charconvert_to checktime cm cmap cmapc cmapclear cmdarg cmdbang cnext cno cnor cnoremap collate colo colorscheme com command completed_item continue cope copen count1 cprevious ctype cu cun cunmap dd delm doautoall doautocmd dying Explore echo echoerr echohl echom echomsg echon echospace edit else elseif emenu END End end endif endfor endfunc endfunction endtry endwhile enew errmsg errors event exception exe exec execute exit exiting exusage false fcs_choice fcs_reason filetype finally finish fold foldc foldd foldclose folddashes folddo folddoc folddoclosed folddoopen foldend foldopen foldstart for fname_diff fname_in fname_new fname_out func function Hexplore hi highlight if iabbrev in im imap imapc imapclear ino inor inoremap iu iunmap key Lexplore lang lc_time lcd lch let lm lma lmap lmapc lmapclear ln lnoremap lnum ls lu lua luado luafile lunmap ma mapc mapclear mark marks mouse_col mouse_lnum mouse_win mouse_winid mz mzf mzfile mzscheme Nexplore new nm nmap nmapc nmapclear nn nnoremap noh nohlsearch none nor nore norem noremap norm normal null numbermax numbermin numbersize nun nunmap oldfiles om omap omapc omapclear only ono onoremap operator option_new option_old option_oldlocal option_oldglobal option_type option_command ou ounmap Pexplore perl perld perldo prevcount pr print prof profd profdel profile progname progpath put pwd py py3 pyx pydo py3do pyxdo py3file pyf pyfile python python3 pythonx pyxfile qa Rexplore redir redr redraw redraws redrawstatus redrawt redrawtabline reg register registers region return ruby rubyd rubydo rubyf rubyfile Sexplore sbNext sbnext sbprevious scrollstart searchforward servername set setf setl setlocal shell_error silent smap smapc smapclear snor snore snoremap so source statusmsg sunm sunmap swapchoice swapcommand swapname sy syn syntax syntime Texplore t_blob t_bool t_channel t_dict t_float t_func t_job t_list t_none t_number t_string tabclose tabmove tabnew tabNext tabnext tabonly tabprevious termresponse termblinkresp termstyleresp termrbgresp termrfgresp termu7resp testing this_session throw throwpoint tma tmap tmapc tmapclear tno tnoremap true try tunma tunmap unlet unm unmap Vexplore val verb verbose version versionlong vert vertical vim_did_enter viusage vmap vmapc vmapclear vn vnoremap vu vunmap vVy warningmsg while wincmd windo windowid wNext wnext wprevious xm xmap xmapc xmapclear xn xnoremap xu xunmap zi zj zk zN zn</Keywords>
<!-- keyboard codes -->
<Keywords name="Keywords2">BAR Bar bar BS CR Cr cr CTRL DEL Del del DOWN Down down ENTER Enter enter EOL Eol eol ESC Esc esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 HOME Home home INSERT Insert insert k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 LEFT Left left NL PageUp PageDown RETURN Return return RIGHT Right right SPACE Space space TAB Tab tab UP Up up</Keywords>
<!-- built-in functions -->
<Keywords name="Keywords3">abs add acos argc argidx arglistid and append appendbufline asin atan atan2 blob2list browse browsedir bufadd bufexists buflisted bufload bufloaded bufname bufnr bufwinid bufwinnr byte2line byteidx byteidxcomp ceil changenr char2nr charclass charcol charidx chdir cindent clearmatches col complete_add complete_check complete_info confirm copy cos cosh cscope_connection cursor debugbreak deepcopy delete deletebufline did_filetype diff_filler diff_hlID echoraw empty environ err_teapot escape eval eventhandler executable exepath exists exists_compiled exp expand expandcmd extend extendnew feedkeys filereadable filewritable filter finddir findfile flatten flattennew float2nr floor fmod fnameescape fnamemodify foldclosed foldclosedend foldtextresult foreground fullcommand funcref garbagecollect getbufinfo getbufline getbufvar getchar getcompletion getcwd getline getpos getreg glob glob2regpat globpath has has_key haslocaldir hasmapto histadd histdel histget histnr hlID hlexists hlget hlset hostname iconv index indexof input inputdialog inputlist inputrestore inputsave inputsecret instanceof interrupt invert isabsolutepath isdirectory isinf islocked isnan items join js_decode json_decode js_encode json_encode keys keytrans len libcall libcallnr line line2byte lispindent list2blob list2str listener_add listener_flush listener_remove localtime log log10 luaeval map maparg mapc mapcheck maplist mapnew mapset match matchadd matchaddpos matcharg matchdelete matchend matchfuzzy matchfuzzypos matchlist matchstr matchstrpos max menu_info min mkdir mode mzeval nextnonblank nr2char or pathshorten perleval pow prevnonblank printf pum_getpos pumvisible pyeval py3eval pyxeval rand range readblob readdir readdirex readfile reduce reg_executing reg_recording reltime reltimefloat reltimestr remove rename repeat resolve reverse round rubyeval screenattr screenchar screenchars screencol screenpos screenrow screenstring search searchcount searchdecl searchpair searchpairpos searchpos server2client serverlist setbufvar setbufline setcellwidths setcharpos setcharsearch setcmdline setcmdpos setcursorcharpos setenv setfperm setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar settagstack setwinvar sha256 shellescape simplify sin sinh slice sort sound_clear sound_playevent sound_playfile sound_stop soundfold spellbadword spellsuggest split sqrt srand state str2float str2list str2nr strcharlen strcharpart strchars strdisplaywidth strftime strgetchar stridx string strlen strpart strptime strridx strtrans strutf16len strwidth submatch substitute swapfilelist swapinfo synID synIDattr synIDtrans synconcealed synstack system systemlist tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname terminalprops tolower toupper tr trim trunc type typename undotree uniq utf16idx values virtcol virtcol2col visualmode wildmenumode winbufnr wincol windowsversion winheight winlayout winline winnr winrestcmd winrestview winsaveview winwidth wordcount writefile xor</Keywords>
<!-- pre-defined editor variables -->
<Keywords name="Keywords4">abuf afile ai amatch args autochdir autoindent autoread autowrite bang buffer Cmd cexpr cfile client count cscopeverbose csverb cursorbind cursorcolumn cursorline cWORD cword darkblue default delek desert dos elflord enable endofline eol evening expandtab expr f-args fen filler fixendofline fixeol foldenable fs fsync global hid hidden hlsearch ignorecase incsearch indent industry internal koehler latin1 lazyredraw lbr LEADER Leader leader linebreak localleader mac magic manual menu menuone modifiable mods more morning murphy newtab nobackup nobuflisted nocompatible nocscopeverbose nocsverb nocursorbind nocursorcolumn nocursorbind nocursorline noendofline noeol noerrorbells noexpandtab nofen nofile nofixendofline nofixeol nofoldenable nofs nofsync nohid nohidden noimd nolbr nolinebreak nolist nomodifiable nomore noshellslash noshelltemp noshowmatch novisualbell NONE None NOP Nop nop noshowmatch noshowmode nosb nosol nospell nosplit nosplitbelow nosplitright nospr nostartofline noswapfile nowait nowb nowrap number off on pablo peachpuff PLUG Plug plug PLUGIN Plugin plugin preview q-args q-mods range relativenumber ron ruler sb script sfile sflnum shellslash shelltemp shine showcmd showmatch si SID slate slnum smartcase smarttab sol special spell splitbelow splitright spr stack start startofline swapfile termguicolors torte ttyfast undofile unique unnamed unnamedplus unix useopen usetab utf8 utf-8 vglobal visualbell wildmenu wrap zellner</Keywords>
<!-- editor events and highlight groups -->
<Keywords name="Keywords5">BufAdd BufCreate BufDelete BufEnter BufFilePost BufFilePre BufHidden BufLeave BufNew BufNewFile BufRead BufReadCmd BufReadPost BufReadPre BufUnload BufWinEnter BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre CmdwinEnter CmdwinLeave ColorColumn ColorScheme CompleteDone Conceal Cursor CursorColumn CursorHold CursorHoldI CursorIM CursorLine CursorLineNr CursorMoved CursorMovedI DiffAdd DiffChange DiffDelete DiffText Directory EncodingChanged EndOfBuffer ErrorMsg FileAppendCmd FileAppendPost FileAppendPre FileChangedShell FileChangedShellPost FileChangedRO FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePre FileWritePost FilterReadPost FilterReadPre FilterWritePost FilterWritePre Folded FoldColumn FocusGained FocusLost FuncUndefined GUIEnter GUIFailed IncSearch InsertChange InsertCharPre InsertEnter InsertLeave LineNr LineNrAbove LineNrBelow lCursor MatchParen MenuPopup ModeMsg MoreMsg NonText Normal Pmenu PmenuSel PmenuSbar PmenuThumb Question QuickFixCmdPost QuickFixCmdPre QuickFixLine QuitPre RemoteReply Search SessionLoadPost ShellCmdPost ShellFilterPost SignColumn SourceCmd SourcePre SpecialKey SpellBad SpellCap SpellFileMissing SpellLocal SpellRare StatusLine StatusLineNC StatusLineTerm StatusLineTermNC StdinReadPost StdinReadPre SwapExists Syntax TabEnter TabLeave TabLine TabLineFill TabLineSel TermChanged Terminal TermResponse TextChanged TextChangedI Title User VertSplit VimEnter VimLeave VimLeavePre VimResized Visual VisualNOS WarningMsg WildMenu WinEnter WinLeave</Keywords>
<!-- configurable editor options -->
<Keywords name="Keywords6">background backspace clipboard cmdheight columns complete completeopt cpo cpoptions cscopeprg csprg cterm ctermbg ctermfg diffopt encoding equalprg errorformat fcl fdc fde fdi fdl fdls fdm fdn fdo fdt fex ffs fileformats fillchars flp fml fmr fo foldclose foldcolumn foldexpr foldignore foldlevel foldlevelstart foldmarker foldmethod foldminlines foldnestmax foldopen foldtext formatexpr formatlistpat formatoptions formatprg gfm gp grepformat grepprg gui guibg guifg guifont guioptions guitablabel history inccommand insertmode isfname iskeyword keywordprg langmap langmenu laststatus lines lmap makeprg pumheight rtp runtimepath shell shellcmdflag shellpipe shellquote shellredir shelltype shellxescape shellxquote shiftwidth softtabstop spelllang stal stl statusline switchbuf tabline tabstop timeoutlen tm ttimeoutlen ttm ttymouse ttyscroll tw undodir whichwrap wildignore wildmode verbosefile</Keywords>
<!-- prefixes of editor options, environment variables, and termcap settings -->
<Keywords name="Keywords7">&amp; $ t_</Keywords>
<!-- prefixes of built-in functions -->
<Keywords name="Keywords8">assert_ autocmd_ balloon_ ch_ digraph_ get job_ popup_ prompt_ prop_ remote_ sign_ term_ test_ timer_ win_</Keywords>
</KeywordLists>
<Styles>
<WordsStyle name="DEFAULT" fgColor="000000" bgColor="FFFFFF" colorStyle="0" fontName="" fontStyle="0"/>
<WordsStyle name="COMMENT" fgColor="008000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="2"/>
<WordsStyle name="COMMENT LINE" fgColor="008000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="2"/>
<WordsStyle name="FOLDEROPEN" fgColor="0000FF" bgColor="FFFFFF" colorStyle="0" fontName="" fontStyle="0"/>
<WordsStyle name="FOLDERCLOSE" fgColor="0000FF" bgColor="FFFFFF" colorStyle="0" fontName="" fontStyle="0"/>
<WordsStyle name="FOLDER IN COMMENT" fgColor="008000" bgColor="FFFFFF" colorStyle="0" fontName="" fontStyle="0"/>
<WordsStyle name="NUMBERS" fgColor="FF0000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="OPERATORS" fgColor="378BBA" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="1"/>
<WordsStyle name="KEYWORDS1" fgColor="0000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="KEYWORDS2" fgColor="8000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="KEYWORDS3" fgColor="8000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="1"/>
<WordsStyle name="KEYWORDS4" fgColor="8000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="KEYWORDS5" fgColor="5C2C26" bgColor="FEFDE0" colorStyle="1" fontName="" fontStyle="2"/>
<WordsStyle name="KEYWORDS6" fgColor="5C2C26" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="3"/>
<WordsStyle name="KEYWORDS7" fgColor="5C2C26" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="3"/>
<WordsStyle name="KEYWORDS8" fgColor="8000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="DELIMITERS1" fgColor="B72F14" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="DELIMITERS2" fgColor="5C2C26" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0"/>
<WordsStyle name="FOLDER IN CODE1" fgColor="378BBA" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0"/>
<WordsStyle name="FOLDER IN CODE2" fgColor="0000FF" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0"/>
</Styles>
</UserLang>
</NotepadPlus>
#
# Copyright (C) 2023 Robert Di Pardo
#
# Permission to use, copy, modify, and/or distribute this software for any purpose
# with or without fee is hereby granted.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
"""
Generate auto-completion definitions for the Vim script Notepad++ UDL.(*)
...
(*) <https://gist.github.com/rdipardo/0b78f62e1ce481ff0d8f8e80cc298ced>
<https://gist.github.com/rdipardo/b8d586e156f543afc84690ac9ddf8e91> (Obsidian theme)
"""
import re
import csv
import tempfile
import xml.etree.ElementTree as xml
from datetime import datetime
from http import client
from io import StringIO
from urllib import request, error as urllib_error
VIML_AC_FILE_INFO = f"""
Description: Keyword and function completions for Vim script
Version: {datetime.today().strftime('%Y-%m-%d')}
Author: Robert Di Pardo <https://github.com/rdipardo>
Credits: Function signatures drawn from <https://vimhelp.org/builtin.txt.html>, (c) Bram Moolenaar
Notes: To use with the default UDL, save this file as "Vim script.xml" (with a " ") in the
"autoCompletion" directory where Notepad++ is installed, e.g.,
"%ProgramFiles%\\Notepad++\\autoCompletion" (64-bit),
"%ProgramFiles(x86)%\\Notepad++\\autoCompletion" (32-bit),
or wherever a portable "notepad++.exe" has been installed.
To use with the Obsidian UDL, the exact file name is "Vim script (Obsidian).xml"
"""
VIML_AC_FUNC_DEFS = 'https://raw.githubusercontent.com/vim/vim/master/runtime/doc/builtin.txt'
VIML_AC_UDL_SOURCE = 'https://raw.githubusercontent.com/notepad-plus-plus/userDefinedLanguages/master/UDLs/Vimscript_by_rdipardo.xml'
VIML_AC_FILE_NAME = 'Vim script'
VIML_AC_FILE_NAME_DARK = 'Vim script (Obsidian)'
def generate(filename: str):
"""
Build the XML tree of a Notepad++ auto-completion definition and save it to `filename`.
"""
try:
func_defs = vim_funcs_to_csv()
if func_defs is None:
raise IOError(f"Error parsing {VIML_AC_FUNC_DEFS}")
funcs, udl_funcs, udl_func_prefixes, kwrds = [], *get_udl_keywords()
root = xml.Element('NotepadPlus')
autoc = xml.SubElement(root, 'AutoComplete', { 'language': 'Vim script' })
autoc.append(xml.Element('Environment', {
'ignoreCase': 'no', 'startFunc': '(', 'stopFunc': ')', 'paramSeparator': ','
}))
with open(func_defs, 'r', newline='', encoding='utf-8') as data:
for func in csv.DictReader(data, delimiter=',', fieldnames=['sig', 'retVal', 'descr']):
sig = re.sub(r'[{}]', '', get_or_default(func, 'sig').strip())
func['name'] = sig[:sig.index('(')] if re.match(r'(?i)^[a-z0-9_]+\(', sig) else sig
func['sig'] = sig
if func['name'].find('_') > -1:
for pre in udl_func_prefixes:
if func['name'].startswith(pre):
funcs.append(func)
elif func['name'] in udl_funcs:
funcs.append(func)
for k in kwrds:
if k not in [get_or_default(f, 'name') for f in funcs]:
funcs.append({'name': k})
for func in sorted(funcs, key=lambda f: get_or_default(f, 'name')):
kwrd = xml.SubElement(autoc, 'KeyWord', { 'name': func['name'] })
ret = get_or_default(func, 'retVal')
if bool(ret):
kwrd.attrib['func'] = 'yes'
sig = get_or_default(func, 'sig')
args = sig[(len(func['name']) + 1):-1] if bool(sig) else ''
overload = xml.SubElement(kwrd, 'Overload', {
'descr': get_or_default(func, 'descr'),
'retVal': f'var x: {ret} ='
})
overload.append(xml.Element('Param', { 'name': args }))
xml.indent(autoc, space='\t', level=2)
xml.indent(root, space='\t', level=0)
with open(filename, 'w', encoding='utf-8') as xml_file:
print('Generating', f'"{filename}"', '...', end=' ')
with StringIO() as out:
print("""<?xml version="1.0" encoding="UTF-8" ?>""", file=out)
print(to_xml(xml.Comment(VIML_AC_FILE_INFO)), file=out)
print(to_xml(root), file=out)
xml_file.write(out.getvalue())
print('done.')
except (xml.ParseError, IOError, TypeError) as err:
print(err)
def vim_funcs_to_csv():
"""
Parse Vim's docs for function signatures, save them in CSV format and return the file name.
"""
csv_file = None
try:
vim_doc = get_resource(VIML_AC_FUNC_DEFS)
if vim_doc is None:
raise RuntimeError(f"Error requesting {VIML_AC_FUNC_DEFS}")
func_defs = []
start = vim_doc.find('*builtin-function-list*')
end = vim_doc.find('*builtin-function-details*')
data = \
re.sub(r'\]\)\s+', '])\t',
re.sub(r'\}\)\s+', '})\t',
re.sub(r'(?<!~|\))\s{2,}', '\t',
re.sub(r'(?<!\))[\r\n]\t{2,}', ' ',
re.sub(r'\)[\r\n]\t{2,}', ')\t',
vim_doc[start:end]))))).replace('|', '')
for line in data.splitlines():
if line.find('(') < 0 > line.find(')'):
continue
cols = list(filter(bool, line.split('\t')))
if cols and len(cols) < 3:
if len(cols) > 1:
spliced = cols[1]
spliced = spliced.replace(' or ', '/')
idx = spliced.find(' ')
if idx > -1:
cols[1] = spliced[:idx].strip()
cols.append(spliced[idx:].strip())
func_defs.append(','.join(map(lambda f: f'"{f}"', cols[:3]))+'\n')
try:
_, csv_file = tempfile.mkstemp(prefix='vim-builtins-', suffix='.csv', text=True)
if csv_file:
with open(csv_file, 'w', encoding='utf-8') as tmp:
tmp.writelines(func_defs)
else:
raise RuntimeError(f"Error parsing {VIML_AC_FUNC_DEFS}")
except IOError as err:
print(err)
except (IndexError, RuntimeError, TypeError) as err:
print(err)
return csv_file
def get_udl_keywords():
"""
Parse the UDL source code for keywords and return them as lists.
"""
funcs, func_prefixes, kwrds = [], [], []
try:
udl_src = get_resource(VIML_AC_UDL_SOURCE)
if udl_src is None:
raise RuntimeError(f"Error requesting {VIML_AC_UDL_SOURCE}")
for kwlist in xml.fromstring(udl_src).findall('.//UserLang/KeywordLists/Keywords'):
n_list = get_or_default(kwlist.attrib, 'name')
index = n_list.replace('Keywords', '')
if index in [str(n) for n in range(1,7)]:
if index == '3':
funcs.extend(kwlist.text.split())
else:
kwrds.extend(kwlist.text.split())
elif index == '8':
func_prefixes.extend(kwlist.text.split())
except (xml.ParseError, RuntimeError, TypeError):
print(f"Error parsing {VIML_AC_UDL_SOURCE}")
return funcs, func_prefixes, kwrds
def get_resource(resource: str):
"""
Request `resource` and return its content.
"""
response_text = None
try:
with request.urlopen(request.Request(resource)) as response:
if response.status == 200:
try:
response_text = response.read().decode('utf8')
except (client.IncompleteRead, IndexError, TypeError):
print(f"Error parsing {resource}")
else:
print(f"Got response [{response.status_code}] requesting {resource}")
except (urllib_error.HTTPError, urllib_error.URLError) as err:
print(err)
return response_text
def to_xml(root: xml.Element):
"""
Return `root` as an XML string, lightly converted into a better format.
"""
out = xml.tostring(root, encoding='unicode').replace("'", "&apos;")
for mtch in re.finditer(r'(?P<ref>&#)(?P<val>\d+);', out):
grp = mtch.groupdict()
out = out.replace(''.join(grp.values()), f"{grp['ref']}x{int(grp['val']):02X}")
return out
def get_or_default(item: dict, key: str):
"""
Return the value at `item[key]` or an empty string.
"""
return item.get(key, '')
if __name__ == '__main__':
for name in [VIML_AC_FILE_NAME, VIML_AC_FILE_NAME_DARK]:
generate(f"{name}.xml")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment