| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- # $Id: 98_help.pm 15223 2017-10-10 10:14:24Z betateilchen $
- #
- package main;
- use strict;
- use warnings;
- use Data::Dumper;
- my $ret;
- sub CommandHelp;
- sub cref_internals;
- sub cref_search;
- sub cref_search_cmd;
- sub cref_fill_list;
- sub cref_findInfo;
- sub help_Initialize($$) {
- my %hash = ( Fn => "CommandHelp",
- Hlp => "[<moduleName>],get help (this screen or module dependent docu)",
- InternalCmds => cref_internals() );
- $cmds{help} = \%hash;
- cref_fill_list();
- }
- sub CommandHelp {
- my ($cl, $arg) = @_;
- my ($mod,$lang) = split(" ",$arg);
-
- $lang //= AttrVal('global','language','en');
- $lang = (lc($lang) eq 'de') ? '_DE' : '';
- if($mod) {
- $mod = "help" if($mod eq "?");
- $mod = $defs{$mod}->{TYPE} if( defined($defs{$mod}) && $defs{$mod}->{TYPE} );
- $mod = lc($mod);
- my $modPath = AttrVal('global','modpath','.');
- my $output = '';
-
- my $outputInfo = cref_findInfo($modPath,$mod);
- if($cmds{help}{InternalCmds} !~ m/$mod\,/) {
- my %mods;
- my @modDir = ("$modPath/FHEM");
- $mod = $cmds{$mod}{ModuleName} if defined($cmds{$mod}) && defined($cmds{$mod}{ModuleName});
- foreach my $modDir (@modDir) {
- eval { opendir(DH, $modDir); }; # || die "Cant open $modDir: $!\n";
- while(my $l = readdir DH) {
- next if($l !~ m/^\d\d_.*\.pm$/);
- my $of = $l;
- $l =~ s/.pm$//;
- $l =~ s/^[0-9][0-9]_//;
- $mods{lc($l)} = "$modDir/$of";
- }
- }
- return "Module $mod not found" unless defined($mods{$mod});
- # read commandref docu from file
- $output = cref_search($mods{$mod},$lang);
- unless($output) {
- $output = cref_search($mods{$mod},"");
- $output = "<br/><br/>Keine deutsche Hilfe gefunden!<br/>$output" if $output;
- }
-
- $output = "No help found for module: $mod" unless $output;
- $output = $outputInfo.$output;
- } else {
- $output = "<br/><b>Internal command:</b> $mod";
- my $i;
- my $f = "$modPath/docs/commandref_frame$lang.html";
- my $skip = 1;
- my ($err,@text) = FileRead({FileName => $f, ForceType => 'file'});
- return $err if $err;
- foreach my $l (@text) {
- if($l =~ m/^<a name=\"$mod\"/) {
- $skip = 0;
- } elsif($l =~ m/^<!-- $mod.end/) {
- $skip = 1;
- } elsif (!$skip) {
- $output .= $l;
- }
- }
- }
- if( $cl && $cl->{TYPE} eq 'telnet' ) { # telnet output
- $output =~ s/<br\s*\?>/\n/ig;
- $output =~ s/\s*<li>\s*/\n- /ig;
- $output =~ s/<\/?ul>/\n/ig;
- $output =~ s/<\/?[^>]+>//g;
- $output =~ s/</</g;
- $output =~ s/>/>/g;
- $output =~ tr/ / /s;
- $output =~ s/\n\n\ /\n/g;
- $output =~ s/ / /g;
- $output =~ s/ä/ä/g;
- $output =~ s/Ä/Ä/g;
- $output =~ s/ö/ö/g;
- $output =~ s/Ö/Ö/g;
- $output =~ s/ü/ü/g;
- $output =~ s/Ü/Ü/g;
- $output =~ s/ß/ß/g;
- $output =~ s/\n\s*\n\s*\n/\n\n\n/g;
- $output =~ s/^\s+//;
- $output =~ s/\s+$//;
-
- } else { # html output
- my $url_prefix;
- if(AttrVal('global','exclude_from_update','') =~ m/commandref/) {
- $url_prefix = "http://fhem.de/commandref$lang.html";
- } else {
- $url_prefix = "$FW_ME/docs/commandref$lang.html";
- }
- # replace <a href="#..."> tags with a
- # working real link to commandref
- $output =~ s,<a\s+href="#,<a target="_blank" href="$url_prefix#,g;
- $output = "<html>$output</html>";
- }
-
- return $output;
- } else { # mod
- # cref_search_cmd(undef);
- my $str = "Possible commands:\n\n" .
- "Command Parameter\n" .
- " Description\n" .
- "----------------------------------------------------------------------\n";
- for my $cmd (sort keys %cmds) {
- next if($cmd =~ m/header:command/);
- next if(!$cmds{$cmd}{Hlp});
- next if($cl && $cmds{$cmd}{ClientFilter} &&
- $cl->{TYPE} !~ m/$cmds{$cmd}{ClientFilter}/);
- my @a = split(",", $cmds{$cmd}{Hlp}, 2);
- # $a[0] =~ s/</</g;
- # $a[0] =~ s/>/>/g;
- $a[1] //= "";
- $a[1] = " $a[1]";
- # $a[1] =~ s/</</g;
- # $a[1] =~ s/>/>/g;
- $str .= sprintf("%-15s%-50s\n%s\n", $cmd, $a[0], $a[1]);
- }
- return $str;
- }
- }
- sub cref_internals {
- my $mod = "./docs/commandref_frame.html";
- my $output = "";
- my ($err,@text) = FileRead({FileName => $mod, ForceType => 'file'});
- return $err if $err;
- foreach my $l (@text) {
- if($l =~ m/(^<!-- )(.*)( end.*>)/) {
- $output .= "$2,";
- }
- }
- return $output;
- }
- sub cref_search {
- my ($mod,$lang) = @_;
- my $output = "";
- my $skip = 1;
- my ($err,@text) = FileRead({FileName => $mod, ForceType => 'file'});
- return $err if $err;
- foreach my $l (@text) {
- if($l =~ m/^=begin html$lang$/) {
- $skip = 0;
- } elsif($l =~ m/^=end html$lang$/) {
- $skip = 1;
- } elsif(!$skip) {
- $output .= "$l\n";
- if($l =~ m,INSERT_DOC_FROM: ([^ ]+)/([^ /]+) ,) {
- my ($dir, $re) = ($1, $2);
- if(opendir(DH, $dir)) {
- foreach my $file (grep { m/^$2$/ } readdir(DH)) {
- $output .= cref_search("$dir/$file", $lang);
- }
- closedir(DH);
- }
- }
- }
- }
- return $output;
- }
- sub cref_search_cmd {
- my $skip = 1;
- my $mod = "./docs/commandref_frame.html";
- my ($err,@text) = FileRead({FileName => $mod, ForceType => 'file'});
- return $err if $err;
- foreach my $l (@text) {
- if($l =~ m/<b>Fhem commands<\/b>/) {
- $skip = 0;
- } elsif($l =~ m/<\/ul>/) {
- $skip = 1;
- } elsif(!$skip && $l !~ m/<ul>/) {
- $l =~ s/\?\,help//;
- $l =~ s/<a.*">//;
- $l =~ s/<\/a>.*//;
- $l =~ s/ //g;
- unless (defined($cmds{$l}{Hlp}) && $cmds{$l}{Hlp}) {
- my %hash = ( Hlp => "use \"help $l\" for more help");
- $cmds{$l} = \%hash if $l;
- }
- }
- }
- foreach my $i (split(",",$cmds{help}{InternalCmds})) {
- my %hash = ( Hlp => "use \"help $i\" for more help");
- $cmds{$i} = \%hash if $i;
- }
- return;
- }
- sub cref_fill_list(){
- my %mods;
- my %modIdx;
- my @modDir = ("FHEM");
- foreach my $modDir (@modDir) {
- opendir(DH, $modDir) || die "Cant open $modDir: $!\n";
- while(my $l = readdir DH) {
- next if($l !~ m/^\d\d_.*\.pm$/);
- my $of = $l;
- $l =~ s/.pm$//;
- $l =~ s/^[0-9][0-9]_//;
- $mods{$l} = "$modDir/$of";
- $modIdx{$l} = "device";
- open(MOD, "$modDir/$of") || die("Cant open $modDir/$l");
- while(my $cl = <MOD>) {
- if($cl =~ m/^=item\s+(helper|command|device)/) {
- $modIdx{$l} = $1;
- last;
- }
- }
- close(MOD);
- }
- }
- foreach my $mod (sort keys %mods) {
- my %h = ( Fn => undef,
- Hlp => "Command $mod not loaded. Use \"help $mod\" for more help" );
- $cmds{$mod} = \%h if ( ($modIdx{$mod} eq "command") && !(defined($cmds{$mod})) );
- }
- }
- sub cref_findInfo {
- my ($modPath,$mod) = @_;
- my ($l,@line,$found,$text);
- my ($err,@text) = FileRead({FileName => "$modPath/MAINTAINER.txt", ForceType => 'file'});
- foreach $l (@text) {
- @line = split("[ \t][ \t]*", $l,3);
- $found = ($l =~ m/_$mod/i);
- last if ($found);
- }
- if($found) {
- $line[0]= (split("/",$line[0]))[1] if $line[0] =~ /\//;
- $line[2]= "no info" if ($line[2] =~ /http/ || !defined($line[2]));
- $text = "<br/><b>Module:</b> $line[0] ";
- $text .= "<b>Maintainer:</b> $line[1] ";
- $text .= "<b>Forum:</b> $line[2]\n";
- }
- $text //= '';
- return $text;
- }
- 1;
- =pod
- =item command
- =item summary show help for module or device
- =item summary_DE Hilfe für Module und Geräte
- =begin html
- <a name="help"></a>
- <h3>?, help</h3>
- <ul>
- <code>? [<moduleName|deviceName>] [<language>]</code><br/>
- <code>help [<moduleName|deviceName>] [<language>]</code><br/>
- <br/>
- <ul>
- <li>Returns a list of available commands, when called without a
- moduleName/deviceName.</li>
- <li>Returns a module dependent helptext, same as in commandref.</li>
- <li>language will be determined in following order:
- <ul>
- <li>valid parameter <language> given</li>
- <li>global attribute language</li>
- <li>nothing founde: return english</li>
- </ul>
- </li>
- </ul>
- </ul>
- =end html
- =begin html_DE
- <a name="help"></a>
- <h3>?, help</h3>
- <ul>
- <code>? [<moduleName|deviceName>] [<language>]</code><br/>
- <code>help [<moduleName|deviceName>] [<language>]</code><br/>
- <br>
- <ul>
- <li>Liefert eine Liste aller Befehle mit einer Kurzbeschreibung zurück.</li>
- <li>Falls moduleName oder deviceName spezifiziert ist, wird die modul-spezifische Hilfe
- aus commandref zurückgeliefert.</li>
- <li>Die anzuzeigende Sprache wird in folgender Reihenfolge bestimmt:
- <ul>
- <li>gültiger Parameter <language> beim Aufruf übergeben</li>
- <li>globales Attribut language</li>
- <li>falls alles fehlt: englisch</li>
- </ul>
- </li>
- </ul>
- </ul>
- =end html_DE
- =cut
|