How to get readable Data::Printer output inside neovim? - ansi-escape

I'm not sure what I need to tweak here. When I exec my Perl file from within neovim I get unreadable output. I'm using Data::Printer 1.000004
nvim --version
NVIM v0.7.0-dev+1135-gfdea15723
cat ~/.dataprinter
array_max = 5000
end_separator = 1
filters = DB, DateTime, JSON, URI
hash_separator = ' => '
index = 1
scalar_quotes = '
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw( state );
use List::SomeUtils qw( part );
my $i = 0;
my #part = part { $i++ % 2 } 1 .. 8;
use DDP;
p #part;
~
~
~
~
~
~
~
~
~
~
~
~
~
~
:call ExecFile()
:!"/Users/olafalders/Documents/perl/part.pl"
^[[0;38;2;102;217;239m[^[[0m
^[[0;38;2;161;187;197m[0] ^[[0m^[[0;38;2;102;217;239m[^[[0m
^[[0;38;2;161;187;197m[0] ^[[0m^[[0;38;2;247;140;106m1^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[1] ^[[0m^[[0;38;2;247;140;106m3^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[2] ^[[0m^[[0;38;2;247;140;106m5^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[3] ^[[0m^[[0;38;2;247;140;106m7^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;102;217;239m]^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[1] ^[[0m^[[0;38;2;102;217;239m[^[[0m
^[[0;38;2;161;187;197m[0] ^[[0m^[[0;38;2;247;140;106m2^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[1] ^[[0m^[[0;38;2;247;140;106m4^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[2] ^[[0m^[[0;38;2;247;140;106m6^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;161;187;197m[3] ^[[0m^[[0;38;2;247;140;106m8^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;102;217;239m]^[[0m^[[0;38;2;102;217;239m,^[[0m
^[[0;38;2;102;217;239m]^[[0m
The actual output should look like:
[
[0] [
[0] 1,
[1] 3,
[2] 5,
[3] 7,
],
[1] [
[0] 2,
[1] 4,
[2] 6,
[3] 8,
],
]

Data::Printer describes itself as:
colored & full-featured pretty print of Perl data structures and objects
The garbage you see is the escape sequences used by the package to colorise the output, which is not understood by the shell in which the script is executed.
To solve your problem at the script/environment level, I'd suggest reading the documentation of the package, which mentions a colored property and a ANSI_COLORS_DISABLED environment variable. It should have been your first move.
To solve it at the editor level, I'd suggest using the built-in :help :terminal, which supports ANSI colours, instead of :!, which doesn't.
And, by the way, the quickfix window is not involved, here.

Related

How to dynamically build a Cheetah3 placeholder variable name?

The bash shell lets you do this with ${!variablename}. This will retrieve the bash variable whose name is contained within the variable named 'variablename'. I'm looking for a way to do that same thing with Cheetah3 (not with necessarily the same syntax, of course - but I am looking for some way to achieve that capability within Cheetah3 itself.)
Here's an example using bash to show what I mean:
% ONE="1"
% TWO="2"
% CHOICE="ONE"
% echo ${!CHOICE}
1
% CHOICE="TWO"
% echo ${!CHOICE}
2
I'm not sure it's possible. My advice is to use a dictionary:
$variables = {
"ONE": "1",
"TWO": "2",
}
$CHOICE = "ONE"
echo $variables[$CHOICE] # -> 1
$CHOICE = "TWO"
echo $variables[$CHOICE] # -> 2

Spirit Qi conditional parsing

I am writing a pdf parsing library.
Once upon a time, I had an input to parse like this one:
1 0 obj
(anything)
endobj
I've created parsing rule for the outer container and then separate rule for the inner object:
CONTAINER_PARSER %=
number >> number >> "obj" >> OBJECT_PARSER >> "endobj";
OBJECT_PARSER %= number | value | ...
This worked without any problems. But, for various reasons a I had to redesign the rules, so that both container values belongs to the object itself.
The container itself is only optional. Meaning, the previous code and the following denotes the same object, without the additional container info:
(anything)
I had 2 ideas, how to solve this problem, but it seems to me, that both are incompatible with Qi approach.
Alternative parser
I wanted to tell the parser, to parse either value contained inside obj - endobj, or to parse only the value.
start %=
(
object_number
>> generation_number
>> qi::lit("obj")
>> object
> qi::lit("endobj")
) | object;
// I intentionally missed some semantic actions assigning the values to the object,
because it is out of the scope of my problem
I didn't manage to make this work, because both parts of the alternation has the same exposed attribute, and the compiler was confused.
Optional approach
I've tried to tell the parser, that the former container is only optional to the parsed value.
start %=
-(
object_number
>> generation_number
>> qi::lit("obj")
)
>> object
> -qi::lit("endobj");
Problem with this approach is, that the last part "endobj" has to be present, if the first part is present as well.
The solution might be trivial, but I was really not able to figure it out from either code, documentation and stackoverflow answers.
UPDATE After the comment:
start =
(
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
) >> "obj" >> object > "endobj"
| qi::attr(1) >> qi::attr(0) >> object
)
;
Assuming you're not interested in the (optional) numbers:
start =
-qi::omit [ object_number >> generation_number ]
>> "obj" >> object > "endobj"
;
If you are interested and have suitable defaults:
start =
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
)
>> "obj" >> object > "endobj"
;
Of course, you could
alter the recipient type to expect optional<int> for the object_numbers so you could simply -object_number >> -generation_number; This would be kinda sloppy since it also allows "1 obj (anything) endobj"
alter the recipient type to be a variant:
boost::variant<simple_object, object_contaier>
in this case your AST matches the "alternative" approach (first one) from your question

Simplest way to sort html table content

Given content from http://packdeps.haskellers.com/reverse what is the easiest way to represent content of this table sorted by second column? What tools are best for this kind of job?
Since content looked simple, I tried to hack with tr, sed and awk (mainly to learn the tools) but it turned out to be too complex to get all rows right. Format could look like this:
47 strict
54 Win32
55 transformers-base
57 enumerator
68 system-filepath
69 xml
or any other format as long it is not making for further processing too complex.
I like perl, and just for learning I did the job using the Web::Scraper module. It uses CSS selectors to extract both columns of the table and sorts them by the second one, which indicates the number of dependencias for each package:
The script.pl file:
#!/usr/bin/env perl
use strict;
use warnings;
use Web::Scraper;
use URI;
die qq|Usage: perl $0 <url>\n| unless #ARGV == 1;
my $packages_deps = scraper {
process 'tr', 'package_deps[]' => scraper {
process 'td:first-child > a', 'package_name' => 'TEXT';
process 'td:nth-child(2)', 'tot_deps' => 'TEXT';
};
result 'package_deps';
};
my $response = $packages_deps->scrape( URI->new( shift ) );
for ( sort { $a->{tot_deps} <=> $b->{tot_deps} } #$response[1..$#$response] ) {
printf qq|%d %s\n|, $_->{tot_deps}, $_->{package_name};
}
Run it providing the url:
perl script.pl "http://packdeps.haskellers.com/reverse"
And it yields (only show the beginning and end part of the list):
1 abstract-par-accelerate
1 accelerate-fft
1 acme-year
1 action-permutations
1 active
1 activehs-base
...
766 text
794 filepath
796 transformers
915 directory
1467 mtl
1741 bytestring
1857 containers
5287 base
Javascript includes a native sorting function, so Javascript is a natural choice.
There is a simple script here which you can either use or examine and learn from:
http://www.allmyscripts.com/Table_Sort/

How can I access ink levels of printers programmatically?

Okay, this is a Windows specific question.
I need to be able to access the ink levels of a printer connected to a computer. Possibly direct connection, or a network connection.
I recognize that it will likely be different for each printer (or printer company at least) but where can I find the information of how they reveal ink levels to a PC. Also, what is the best language to read this information in?
Okay, this is a OS agnostic answer... :-)
If the printer isn't a very cheapo model, it will have built-in support for SNMP (Simple Network Management Protocol). SNMP queries can return current values from the network devices stored in their MIBs (Management Information Bases).
For printers there's a standard defined called Printer MIB. The Printer MIB defines standard names and tree locations (OIDs == Object Identifiers in ASN.1 notation) for prtMarkerSuppliesLevel which in the case of ink marking printers map to ink levels.
Be aware that SNMP also allows private extensions to the standard MIBs. Most printer vendors do hide many additional pieces of information in their "private MIBs", though the standard info should always be available through the queries of the Printer MIB OIDs.
Practically every programming language has standard libraries which can help you to make specific SNMP queries from your own application.
One such implementation is Open Source, called Net-SNMP, which also comes with a few powerfull commandline tools to run SNMP queries.
I think the OID to query all levels for all inks is .1.3.6.1.2.1.43.11.1.1.9 (this webpage confirms my believe) but I cannot verify that right now, because I don't have a printer around in my LAN at the moment. So Net-SNMP's snmpget command to query ink levels should be something like:
snmpget \
-c public \
192.168.222.111 \
".1.3.6.1.2.1.43.11.1.1.9"
where public is the standard community string and 192.168.222.111 your printer's IP address.
I have an SNMP-capable HP 8600 pro N911a around to do some digging, so the following commands may help you a bit. Beware that this particular model has some firmware problems, you can't query "magenta" with snmpget, but you see a value with snmpwalk (which does some kind of recursive drill-down).
OLD: You can query the names and sequence of values, but I couldn't find the "max value" to calculate a clean percentage so far ;(. I'm guessing so far the values are relative to 255, so dividing by 2.55 yields a percentage.
Update: Marcelo's hint was great! From Registers .8.* you can read the max level per cartridge, and I was totally wrong assuming the max value can only be an 8-bit value. I have updated the sample script to read the max values and calculate c
There is also some discussion over there at Cacti forums.
One answer confirms that the ink levels are measured as percent (value 15 is "percent" in an enumeration):
# snmpwalk -v1 -c public 192.168.100.173 1.3.6.1.2.1.43.11.1.1.7
SNMPv2-SMI::mib-2.43.11.1.1.7.0.1 = INTEGER: 15
SNMPv2-SMI::mib-2.43.11.1.1.7.0.2 = INTEGER: 15
SNMPv2-SMI::mib-2.43.11.1.1.7.0.3 = INTEGER: 15
SNMPv2-SMI::mib-2.43.11.1.1.7.0.4 = INTEGER: 15
You need to install the net-snmp package. If you're not on Linux you might need some digging for SNMP command line tools for your preferred OS.
# snmpwalk -v1 -c public 192.168.100.173 1.3.6.1.2.1.43.11.1.1.6.0
SNMPv2-SMI::mib-2.43.11.1.1.6.0.1 = STRING: "black ink"
SNMPv2-SMI::mib-2.43.11.1.1.6.0.2 = STRING: "yellow ink"
SNMPv2-SMI::mib-2.43.11.1.1.6.0.3 = STRING: "cyan ink"
SNMPv2-SMI::mib-2.43.11.1.1.6.0.4 = STRING: "magenta ink"
# snmpwalk -v1 -c public 192.168.100.173 1.3.6.1.2.1.43.11.1.1.9.0
SNMPv2-SMI::mib-2.43.11.1.1.9.0.1 = INTEGER: 231
SNMPv2-SMI::mib-2.43.11.1.1.9.0.2 = INTEGER: 94
SNMPv2-SMI::mib-2.43.11.1.1.9.0.3 = INTEGER: 210
SNMPv2-SMI::mib-2.43.11.1.1.9.0.4 = INTEGER: 174
# snmpwalk -v1 -c praxis 192.168.100.173 1.3.6.1.2.1.43.11.1.1.8.0
SNMPv2-SMI::mib-2.43.11.1.1.8.0.1 = INTEGER: 674
SNMPv2-SMI::mib-2.43.11.1.1.8.0.2 = INTEGER: 240
SNMPv2-SMI::mib-2.43.11.1.1.8.0.3 = INTEGER: 226
SNMPv2-SMI::mib-2.43.11.1.1.8.0.4 = INTEGER: 241
On my Linux box I use the following script to do some pretty-printing:
#!/bin/sh
PATH=/opt/bin${PATH:+:$PATH}
# get current ink levels
eval $(snmpwalk -v1 -c praxis 192.168.100.173 1.3.6.1.2.1.43.11.1.1.6.0 |
perl -ne 'print "c[$1]=$2\n" if(m!SNMPv2-SMI::mib-2.43.11.1.1.6.0.(\d) = STRING:\s+"(\w+) ink"!i);')
# get max ink level per cartridge
eval $(snmpwalk -v1 -c praxis 192.168.100.173 1.3.6.1.2.1.43.11.1.1.8.0 |
perl -ne 'print "max[$1]=$2\n" if(m!SNMPv2-SMI::mib-2.43.11.1.1.8.0.(\d) = INTEGER:\s+(\d+)!i);')
snmpwalk -v1 -c praxis 192.168.100.173 1.3.6.1.2.1.43.11.1.1.9.0 |
perl -ne '
my #c=("","'${c[1]}'","'${c[2]}'","'${c[3]}'","'${c[4]}'");
my #max=("","'${max[1]}'","'${max[2]}'","'${max[3]}'","'${max[4]}'");
printf"# $c[$1]=$2 (%.0f)\n",$2/$max[$1]*100
if(m!SNMPv2-SMI::mib-2.43.11.1.1.9.0.(\d) = INTEGER:\s+(\d+)!i);'
An alternative approach could be using ipp. While most of the printers I tried support both, I found one which only worked with ipp and one that only worked for me with snmp.
Simple approach with ipptool:
Create file colors.ipp:
{
VERSION 2.0
OPERATION Get-Printer-Attributes
GROUP operation-attributes-tag
ATTR charset "attributes-charset" "utf-8"
ATTR naturalLanguage "attributes-natural-language" "en"
ATTR uri "printer-uri" $uri
ATTR name "requesting-user-name" "John Doe"
ATTR keyword "requested-attributes" "marker-colors","marker-high-levels","marker-levels","marker-low-levels","marker-names","marker-types"
}
Run:
ipptool -v -t ipp://192.168.2.126/ipp/print colors.ipp
The response:
"colors.ipp":
Get-Printer-Attributes:
attributes-charset (charset) = utf-8
attributes-natural-language (naturalLanguage) = en
printer-uri (uri) = ipp://192.168.2.126/ipp/print
requesting-user-name (nameWithoutLanguage) = John Doe
requested-attributes (1setOf keyword) = marker-colors,marker-high-levels,marker-levels,marker-low-levels,marker-names,marker-types
colors [PASS]
RECEIVED: 507 bytes in response
status-code = successful-ok (successful-ok)
attributes-charset (charset) = utf-8
attributes-natural-language (naturalLanguage) = en-us
marker-colors (1setOf nameWithoutLanguage) = #00FFFF,#FF00FF,#FFFF00,#000000,none
marker-high-levels (1setOf integer) = 100,100,100,100,100
marker-levels (1setOf integer) = 6,6,6,6,100
marker-low-levels (1setOf integer) = 5,5,5,5,5
marker-names (1setOf nameWithoutLanguage) = Cyan Toner,Magenta Toner,Yellow Toner,Black Toner,Waste Toner Box
marker-types (1setOf keyword) = toner,toner,toner,toner,waste-toner
marker-levels has current toner/ink levels, marker-high-levels are maximus (so far I've only seen 100s here), marker-names describe meaning of each field (tip: for colors you may want to strip everything after first space, many printers include cartridge types in this field).
Note: the above is with cups 2.3.1. With 2.2.1 I had to specify the keywords as one string instead ("marker-colors,marker-h....). Or it can be left altogether, then all keywords are returned.
More on available attributes (may differ between printers): https://www.cups.org/doc/spec-ipp.html
More on executing ipp calls (including python examples): https://www.pwg.org/ipp/ippguide.html
I really liked tseeling's approach!
Complementarily, I found out that the max value for the OID ... .9 is not 255 as guessed by him, but it actually varies per individual cartridge. The values can be obtained from OID .1.3.6.1.2.1.43.11.1.1.8 (the results obtained by dividing by these values match the ones obtained by running hp-inklevels command from hplip.
I wrote my own script that output CSVs like below (suppose printer IP addr is 192.168.1.20):
# ./hpink 192.168.1.20
black,73,366,19.9454
yellow,107,115,93.0435
cyan,100,108,92.5926
magenta,106,114,92.9825
values are in this order: <color_name>,<level>,<maxlevel>,<percentage>
The script source (one will notice I usually prefer awk over perl when the puzzle is simple enough):
#!/bin/sh
snmpwalk -v1 -c public $1 1.3.6.1.2.1.43.11.1.1 | awk '
/.*\.6\.0\./ {
sub(/.*\./,"");
split($0,TT,/[ "]*/);
color[TT[1]]=TT[4];
}
/.*\.8\.0\./ {
sub(/.*\./,"");
split($0,TT,/[ "]*/);
maxlevel[TT[1]]=TT[4];
}
/.*\.9\.0\./ {
sub(/.*\./,"");
split($0,TT,/[ "]*/);
print color[TT[1]] "," TT[4] "," maxlevel[TT[1]] "," TT[4] / maxlevel[TT[1]] * 100;
}'

How do I get a random number in template toolkit?

I want to get a random number using template toolkit. It doesn't have to be particularly random. How do I do it?
Hmm, you might have issues if you don't have (or cannot import) Slash::Test.
From a "vanilla" installation of TT, you can simply use the Math plugin:
USE Math;
GET Math.rand; # outputs a random number from 0 to 1
See this link in the template toolkit manual for more information on the Math plugin and the various methods.
Update: Math.rand requires a parameter. Therefore to get a random number from 0 to 1, use:
GET Math.rand(1);
From this post at Slashcode:
[slash#yaz slash]$ perl -MSlash::Test -leDisplay
[%
digits = [ 0 .. 9 ];
anumber = digits.rand _ digits.rand _ digits.rand;
anumber;
%]
^D
769

Resources