Pug: compilation of extended blocks in a condition - compilation
I recently moved from Jade to Pug and I encountered a problem compiling my code. The code of a block inserted in a condition is no longer called, only the alternate message ([content]) is returned :
// PatternLayouts.pug
block var
//- Default values
// [etc...]
- contentlarge = false
main(itemprop='mainContentOfPage')
if contentlarge
block content
// Default
p [Content]
else
.section
.wrap
h1(itemprop='headline name').emphasized= name
block content
// Default
p [Content]
If variable contentlarge = false then no interpretation problem, but if this is equal to true the code defined by the alternative condition (else) does not work ...
I finally found, it is actually a regression of functionality: Github, issue # 2367
Related
Missing space between define and initializer sphynx rtd_theme
I am using doxygen + breathe + Sphinx to document C source code. In my conf.py I have set: breathe_show_define_initializer = True and html_theme = 'sphinx_rtd_theme' In my C source code I have defines such as: #define FOO 12U //!< example #define In the xml generated from doxygen, I see: <name>FOO</name> <initializer>12U</initializer> <briefdescription> <para>example #define </para> </briefdescription> So far so good! The problem is the output from Sphinx is missing white space between the name and the initializer. i.e. as shown, no space between FOO and 12U: FOO12U example #define I tried using both: .. doxygendefine:: FOO and I tried the group which has a number of defines: .. doxygengroup:: MY_DEFINES_GROUP If I change html_theme = 'alabaster' Then there is a space between FOO and 12U Any thoughts - am I missing a configuration?
I found this question via Google since I ran into the same issue. I'm posting my solution here which I hacked up and it seems to work for my case in the hopes of saving someone else time. My solution was to insert a "no break space" after each name of the define (but before the value). Create a custom css: under _static/custom-signame.css (which is where I store my other custom css files) The contents of the file are: /* add a space to fix Breathe+Sphinx rtd_theme with breathe_show_define_initializer */ .sig-name::after { content: "\00a0"; } Make sure that conf.py is updated to include the new custom css created in step 2: html_static_path = ['_static'] html_css_files = [ 'custom-table.css', 'custom-signame.css', ]
How to include the source line number everywhere in html output in Sphinx?
Let's say I'm writing a custom editor for my RestructuredText/Sphinx stuff, with "live" html output preview. Output is built using Sphinx. The source files are pure RestructuredText. No code there. One desirable feature would be that right-clicking on some part of the preview opens the editor at the correct line of the source file. To achieve that, one way would be to put that line number in every tag of the html file, for example using classes (e.g., class = "... lineno-124"). Or use html comments. Note that I don't want to add more content to my source files, just that the line number be included everywhere in the output. An approximate line number would be enough. Someone knows how to do this in Sphinx, my way or another?
I decided to add <a> tags with a specific class "lineno lineno-nnn" where nnn is the line number in the RestructuredText source. The directive .. linenocomment:: nnn is inserted before each new block of unindented text in the source, before the actual parsing (using a 'source-read' event hook). linenocomment is a custom directive that pushes the <a> tag at build time. Half a solution is still a solution... import docutils.nodes as dn from docutils.parsers.rst import Directive class linenocomment(dn.General,dn.Element): pass def visit_linenocomment_html(self,node): self.body.append(self.starttag(node,'a',CLASS="lineno lineno-{}".format(node['lineno']))) def depart_linenocomment_html(self,node): self.body.append('</a>') class LineNoComment(Directive): required_arguments = 1 optional_arguments = 0 has_content = False add_index = False def run(self): node = linenocomment() node['lineno'] = self.arguments[0] return [node] def insert_line_comments(app, docname, source): print(source) new_source = [] last_line_empty = True lineno = 0 for line in source[0].split('\n'): if line.strip() == '': last_line_empty = True new_source.append(line) elif line[0].isspace(): new_source.append(line) last_line_empty = False elif not last_line_empty: new_source.append(line) else: last_line_empty = False new_source.append('.. linenocomment:: {}'.format(lineno)) new_source.append('') new_source.append(line) lineno += 1 source[0] = '\n'.join(new_source) print(source) def setup(app): app.add_node(linenocomment,html=(visit_linenocomment_html,depart_linenocomment_html)) app.add_directive('linenocomment', LineNoComment) app.connect('source-read',insert_line_comments) return { 'version': 0.1 }
AENUM creating class bodies dynamically causes pylint warning
I cannot explain why I get a pylint "<class 'AttributeError'>: 'For' object has no attribute 'targets'" warning when I create enum entries dynamically. I cannot see any reason for the the warning in my code. from aenum import IntEnum class Commands(IntEnum): _ignore_ = 'Commands index' _init_ = 'value string' BEL = 0x07, 'Bell' Commands = vars() for index in range(4): Commands[f'DC{index + 1}'] = 0x11 + index, f'Device Control {index + 1}' for command in Commands: print(f"0x{command.value:02X} is {command.string}") The code works fine but I do NOT expect a warning!
The code is OK the bug was within the toolchain: https://github.com/PyCQA/pylint/issues/2719
How to stop ImageMagick in Ruby (Rmagick) evaluating an # sign in text annotation
In an app I recently built for a client the following code resulted in the variable #nameText being evaluated, and then resulting in an error 'no text' (since the variable doesn't exist). To get around this I used gsub, as per the example below. Is there a way to tell Magick not to evaluate the string at all? require 'RMagick' #image = Magick::Image.read( '/path/to/image.jpg' ).first #nameText = '#SomeTwitterUser' #text = Magick::Draw.new #text.font_family = 'Futura' #text.pointsize = 22 #text.font_weight = Magick::BoldWeight # Causes error 'no text'... # #text.annotate( #image, 0,0,200,54, #nameText ) #text.annotate( #image, 0,0,200,54, #nameText.gsub('#', '\#') )
This is the C code from RMagick that is returning the error: // Translate & store in Draw structure draw->info->text = InterpretImageProperties(NULL, image, StringValuePtr(text)); if (!draw->info->text) { rb_raise(rb_eArgError, "no text"); } It is the call to InterpretImageProperties that is modifying the input text - but it is not Ruby, or a Ruby instance variable that it is trying to reference. The function is defined here in the Image Magick core library: http://www.imagemagick.org/api/MagickCore/property_8c_source.html#l02966 Look a bit further down, and you can see the code: /* handle a '#' replace string from file */ if (*p == '#') { p++; if (*p != '-' && (IsPathAccessible(p) == MagickFalse) ) { (void) ThrowMagickException(&image->exception,GetMagickModule(), OptionError,"UnableToAccessPath","%s",p); return((char *) NULL); } return(FileToString(p,~0,&image->exception)); } In summary, this is a core library feature which will attempt to load text from file (named SomeTwitterUser in your case, I have confirmed this -try it!), and your work-around is probably the best you can do. For efficiency, and minimal changes to input strings, you could rely on the selectivity of the library code and only modify the string if it starts with #: #text.annotate( #image, 0,0,200,54, #name_string.gsub( /^#/, '\#') )
Forcing a package's function to use user-provided function
I'm running into a problem with the MNP package which I've traced to an unfortunate call to deparse (whose maximum width is limited to 500 characters). Background (easily skippable if you're bored) Because mnp uses a somewhat idiosyncratic syntax to allow for varying choice sets (you include cbind(choiceA,choiceB,...) in the formula definition), the left hand side of my formula call is 1700 characters or so when model.matrix.default calls deparse on it. Since deparse supports a maximum width.cutoff of 500 characters, the sapply(attr(t, "variables"), deparse, width.cutoff = 500)[-1L] line in model.matrix.default has as its first element: [1] "cbind(plan1, plan2, plan3, plan4, plan5, plan6, plan7, plan8, plan9, plan10, plan11, plan12, plan13, plan14, plan15, plan16, plan17, plan18, plan19, plan20, plan21, plan22, plan23, plan24, plan25, plan26, plan27, plan28, plan29, plan30, plan31, plan32, plan33, plan34, plan35, plan36, plan37, plan38, plan39, plan40, plan41, plan42, plan43, plan44, plan45, plan46, plan47, plan48, plan49, plan50, plan51, plan52, plan53, plan54, plan55, plan56, plan57, plan58, plan59, plan60, plan61, plan62, plan63, " [2] " plan64, plan65, plan66, plan67, plan68, plan69, plan70, plan71, plan72, plan73, plan74, plan75, plan76, plan77, plan78, plan79, plan80, plan81, plan82, plan83, plan84, plan85, plan86, plan87, plan88, plan89, plan90, plan91, plan92, plan93, plan94, plan95, plan96, plan97, plan98, plan99, plan100, plan101, plan102, plan103, plan104, plan105, plan106, plan107, plan108, plan109, plan110, plan111, plan112, plan113, plan114, plan115, plan116, plan117, plan118, plan119, plan120, plan121, plan122, plan123, " [3] " plan124, plan125, plan126, plan127, plan128, plan129, plan130, plan131, plan132, plan133, plan134, plan135, plan136, plan137, plan138, plan139, plan140, plan141, plan142, plan143, plan144, plan145, plan146, plan147, plan148, plan149, plan150, plan151, plan152, plan153, plan154, plan155, plan156, plan157, plan158, plan159, plan160, plan161, plan162, plan163, plan164, plan165, plan166, plan167, plan168, plan169, plan170, plan171, plan172, plan173, plan174, plan175, plan176, plan177, plan178, plan179, " [4] " plan180, plan181, plan182, plan183, plan184, plan185, plan186, plan187, plan188, plan189, plan190, plan191, plan192, plan193, plan194, plan195, plan196, plan197, plan198, plan199, plan200, plan201, plan202, plan203, plan204, plan205, plan206, plan207, plan208, plan209, plan210, plan211, plan212, plan213, plan214, plan215, plan216, plan217, plan218, plan219, plan220, plan221, plan222, plan223, plan224, plan225, plan226, plan227, plan228, plan229, plan230, plan231, plan232, plan233, plan234, plan235, " [5] " plan236, plan237, plan238, plan239, plan240, plan241, plan242, plan243, plan244, plan245, plan246, plan247, plan248, plan249, plan250, plan251, plan252, plan253, plan254, plan255, plan256, plan257, plan258, plan259, plan260, plan261, plan262, plan263, plan264, plan265, plan266, plan267, plan268, plan269, plan270, plan271, plan272, plan273, plan274, plan275, plan276, plan277, plan278, plan279, plan280, plan281, plan282, plan283, plan284, plan285, plan286, plan287, plan288, plan289, plan290, plan291, " [6] " plan292, plan293, plan294, plan295, plan296, plan297, plan298, plan299, plan300, plan301, plan302, plan303, plan304, plan305, plan306, plan307, plan308, plan309, plan310, plan311, plan312, plan313)" When model.matrix.default tests this against the variables in the data.frame, it returns an error. The problem To get around this, I've written a new deparse function: deparse <- function (expr, width.cutoff = 60L, backtick = mode(expr) %in% c("call", "expression", "(", "function"), control = c("keepInteger", "showAttributes", "keepNA"), nlines = -1L) { ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) paste0(ret,collapse="") } However, when I run mnp again and step through, it returns the same error for the same reason (base::deparse is being run, not my deparse). This is somewhat surprising to me, as what I expect is more typified by this example, where the user-defined function temporarily over-writes the base function: > print <- function() { + cat("user-defined print ran\n") + } > print() user-defined print ran I realize the right way to solve this problem is to rewrite model.matrix.default, but as a tool for debugging I'm curious how to force it to use my deparse and why the anticipated (by me) behavior is not happening here.
The functions fixInNamespace and assignInNamespace are provided to allow editing of existing functions. You could try ... but I will not since mucking with deparse looks too dangerous: assignInNamespace("deparse", function (expr, width.cutoff = 60L, backtick = mode(expr) %in% c("call", "expression", "(", "function"), control = c("keepInteger", "showAttributes", "keepNA"), nlines = -1L) { ret <- .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), nlines)) paste0(ret,collapse="") } , "base") There is an indication on the help page that the use of such functions has restrictions and I would not be surprised that such core function might have additional layers of protection. Since it works via side-effect, you should not need to assign the result.
This is how packages with namespaces search for functions, as described in Section 1.6, Package Namespaces of Writing R Extensions Namespaces are sealed once they are loaded. Sealing means that imports and exports cannot be changed and that internal variable bindings cannot be changed. Sealing allows a simpler implementation strategy for the namespace mechanism. Sealing also allows code analysis and compilation tools to accurately identify the definition corresponding to a global variable reference in a function body. The namespace controls the search strategy for variables used by functions in the package. If not found locally, R searches the package namespace first, then the imports, then the base namespace and then the normal search path.