98_help.pm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. # $Id: 98_help.pm 11992 2016-08-19 18:18:00Z betateilchen $
  2. #
  3. package main;
  4. use strict;
  5. use warnings;
  6. use Data::Dumper;
  7. my $ret;
  8. sub CommandHelp;
  9. sub cref_search;
  10. sub cref_search_cmd;
  11. sub help_Initialize($$) {
  12. my %hash = ( Fn => "CommandHelp",
  13. Hlp => "[<moduleName>],get help (this screen or module dependent docu)",
  14. InternalCmds => "attributes,command,commands,devspec,global,perl" );
  15. $cmds{help} = \%hash;
  16. }
  17. sub CommandHelp {
  18. my ($cl, $arg) = @_;
  19. my ($mod,$lang) = split(" ",$arg);
  20. $lang //= AttrVal('global','language','en');
  21. $lang = (lc($lang) eq 'de') ? '_DE' : '';
  22. if($mod) {
  23. $mod = "help" if($mod eq "?");
  24. $mod = $defs{$mod}->{TYPE} if( defined($defs{$mod}) && $defs{$mod}->{TYPE} );
  25. my $internals = "attributes,command,commands,devspec,global,perl";
  26. $mod = lc($mod);
  27. my $modPath = AttrVal('global','modpath','.');
  28. my $output = '';
  29. if($cmds{help}{InternalCmds} !~ m/$mod\,/) {
  30. my %mods;
  31. my @modDir = ("$modPath/FHEM");
  32. $mod = $cmds{$mod}{ModuleName} if defined($cmds{$mod}{ModuleName});
  33. foreach my $modDir (@modDir) {
  34. eval { opendir(DH, $modDir); }; # || die "Cant open $modDir: $!\n";
  35. while(my $l = readdir DH) {
  36. next if($l !~ m/^\d\d_.*\.pm$/);
  37. my $of = $l;
  38. $l =~ s/.pm$//;
  39. $l =~ s/^[0-9][0-9]_//;
  40. $mods{lc($l)} = "$modDir/$of";
  41. }
  42. }
  43. return "Module $mod not found" unless defined($mods{$mod});
  44. # read commandref docu from file
  45. $output = cref_search($mods{$mod},$lang);
  46. unless($output) {
  47. $output = cref_search($mods{$mod},"");
  48. $output = "Keine deutsche Hilfe gefunden!<br/>$output" if $output;
  49. }
  50. $output = "No help found for module: $mod" unless $output;
  51. } else {
  52. $output = '';
  53. my $i;
  54. my $f = "$modPath/docs/commandref_frame$lang.html";
  55. my $skip = 1;
  56. my ($err,@text) = FileRead({FileName => $f, ForceType => 'file'});
  57. return $err if $err;
  58. foreach my $l (@text) {
  59. if($l =~ m/^<a name=\"$mod\"/) {
  60. $skip = 0;
  61. } elsif($l =~ m/^<!-- $mod.end/) {
  62. $skip = 1;
  63. } elsif (!$skip) {
  64. $output .= $l;
  65. }
  66. }
  67. }
  68. if( $cl && $cl->{TYPE} eq 'telnet' ) { # telnet output
  69. $output =~ s/<br\s*\?>/\n/ig;
  70. $output =~ s/\s*<li>\s*/\n- /ig;
  71. $output =~ s/<\/?ul>/\n/ig;
  72. $output =~ s/<\/?[^>]+>//g;
  73. $output =~ s/&lt;/</g;
  74. $output =~ s/&gt;/>/g;
  75. $output =~ tr/ / /s;
  76. $output =~ s/\n\n\ /\n/g;
  77. $output =~ s/&nbsp;/ /g;
  78. $output =~ s/&auml;/ä/g;
  79. $output =~ s/&Auml;/Ä/g;
  80. $output =~ s/&ouml;/ö/g;
  81. $output =~ s/&Ouml;/Ö/g;
  82. $output =~ s/&uuml;/ü/g;
  83. $output =~ s/&Uuml;/Ü/g;
  84. $output =~ s/&szlig;/ß/g;
  85. $output =~ s/\n\s*\n\s*\n/\n\n\n/g;
  86. $output =~ s/^\s+//;
  87. $output =~ s/\s+$//;
  88. } else { # html output
  89. my $url_prefix;
  90. if(AttrVal('global','exclude_from_update','') =~ m/commandref/) {
  91. $url_prefix = "http://fhem.de/commandref$lang.html";
  92. } else {
  93. $url_prefix = "$FW_ME/docs/commandref$lang.html";
  94. }
  95. # replace <a href="#..."> tags with a
  96. # working real link to commandref
  97. $output =~ s,<a\s+href="#,<a target="_blank" href="$url_prefix#,g;
  98. $output = "<html>$output</html>";
  99. }
  100. return $output;
  101. } else { # mod
  102. cref_search_cmd(undef);
  103. my $str = "Possible commands:\n\n" .
  104. "Command Parameter\n" .
  105. " Description\n" .
  106. "----------------------------------------------------------------------\n";
  107. for my $cmd (sort keys %cmds) {
  108. next if($cmd =~ m/header:command/);
  109. next if(!$cmds{$cmd}{Hlp});
  110. next if($cl && $cmds{$cmd}{ClientFilter} &&
  111. $cl->{TYPE} !~ m/$cmds{$cmd}{ClientFilter}/);
  112. my @a = split(",", $cmds{$cmd}{Hlp}, 2);
  113. # $a[0] =~ s/</&lt;/g;
  114. # $a[0] =~ s/>/&gt;/g;
  115. $a[1] //= "";
  116. $a[1] = " $a[1]";
  117. # $a[1] =~ s/</&lt;/g;
  118. # $a[1] =~ s/>/&gt;/g;
  119. $str .= sprintf("%-15s%-50s\n%s\n", $cmd, $a[0], $a[1]);
  120. }
  121. return $str;
  122. }
  123. }
  124. sub cref_search {
  125. my ($mod,$lang) = @_;
  126. my $output = "";
  127. my $skip = 1;
  128. my ($err,@text) = FileRead({FileName => $mod, ForceType => 'file'});
  129. return $err if $err;
  130. foreach my $l (@text) {
  131. if($l =~ m/^=begin html$lang$/) {
  132. $skip = 0;
  133. } elsif($l =~ m/^=end html$lang$/) {
  134. $skip = 1;
  135. } elsif(!$skip) {
  136. $output .= "$l\n";
  137. }
  138. }
  139. return $output;
  140. }
  141. sub cref_search_cmd {
  142. my $skip = 1;
  143. my $mod = "./docs/commandref_frame.html";
  144. my ($err,@text) = FileRead({FileName => $mod, ForceType => 'file'});
  145. return $err if $err;
  146. foreach my $l (@text) {
  147. if($l =~ m/<b>Fhem commands<\/b>/) {
  148. $skip = 0;
  149. } elsif($l =~ m/<\/ul>/) {
  150. $skip = 1;
  151. } elsif(!$skip && $l !~ m/<ul>/) {
  152. $l =~ s/\?\,help//;
  153. $l =~ s/<a.*">//;
  154. $l =~ s/<\/a>.*//;
  155. $l =~ s/ //g;
  156. unless (defined($cmds{$l}{Hlp}) && $cmds{$l}{Hlp}) {
  157. my %hash = ( Hlp => "use \"help $l\" for more help");
  158. $cmds{$l} = \%hash if $l;
  159. }
  160. }
  161. }
  162. foreach my $i (split(",",$cmds{help}{InternalCmds})) {
  163. my %hash = ( Hlp => "use \"help $i\" for more help");
  164. $cmds{$i} = \%hash if $i;
  165. }
  166. return;
  167. }
  168. 1;
  169. =pod
  170. =item command
  171. =item summary show help for module or device
  172. =item summary_DE Hilfe f&uuml;r Module und Ger&auml;te
  173. =begin html
  174. <a name="help"></a>
  175. <h3>?, help</h3>
  176. <ul>
  177. <code>? [&lt;moduleName|deviceName&gt;] [<language>]</code><br/>
  178. <code>help [&lt;moduleName|deviceName&gt;] [<language>]</code><br/>
  179. <br/>
  180. <ul>
  181. <li>Returns a list of available commands, when called without a
  182. moduleName/deviceName.</li>
  183. <li>Returns a module dependent helptext, same as in commandref.</li>
  184. <li>language will be determined in following order:
  185. <ul>
  186. <li>valid parameter &lt;language&gt; given</li>
  187. <li>global attribute language</li>
  188. <li>nothing founde: return english</li>
  189. </ul>
  190. </li>
  191. </ul>
  192. </ul>
  193. =end html
  194. =begin html_DE
  195. <a name="help"></a>
  196. <h3>?, help</h3>
  197. <ul>
  198. <code>? [&lt;moduleName|deviceName&gt;] [<language>]</code><br/>
  199. <code>help [&lt;moduleName|deviceName&gt;] [<language>]</code><br/>
  200. <br>
  201. <ul>
  202. <li>Liefert eine Liste aller Befehle mit einer Kurzbeschreibung zur&uuml;ck.</li>
  203. <li>Falls moduleName oder deviceName spezifiziert ist, wird die modul-spezifische Hilfe
  204. aus commandref zur&uuml;ckgeliefert.</li>
  205. <li>Die anzuzeigende Sprache wird in folgender Reihenfolge bestimmt:
  206. <ul>
  207. <li>g&uuml;ltiger Parameter &lt;language&gt; beim Aufruf &uuml;bergeben</li>
  208. <li>globales Attribut language</li>
  209. <li>falls alles fehlt: englisch</li>
  210. </ul>
  211. </li>
  212. </ul>
  213. </ul>
  214. =end html_DE
  215. =cut