1

I know that this works to view the contents of a function:

cat function:\mkdir

That's fine, so I thought I'd use the bat to syntax highlight that output

PS C:\> bat function:\mkdir
function:\mkdir: No such file or directory

I thought this might work:

PS C:\> bat $(function:\mkdir)
function:\mkdir : The term 'function:\mkdir' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:7
+ bat $(function:\mkdir)
+        ~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (function:\mkdir:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

This also fails:

cat function:\mkdir | bat

What am I doing wrong; how can I output the function contents with a parser of my choice?

For some context, this is for my function that tells me as much information as possible about any cmdlet, function, alias, module, external script, application, or variable, just point what at any object and it will tell you about that object (e.g. what mkdir or what what etc). If bat is on the path, it will use that and colourise the output as PowerShell, and if not, it will use Get-Content. https://gist.github.com/roysubs/20c1bc888383d56df67008f4ba4179cb

YorSubs
  • 3,194
  • 7
  • 37
  • 60
  • 6
    Out of curiosity - what is `bat`? – JosefZ Nov 11 '22 at 16:41
  • you mean [this bat](https://github.com/sharkdp/bat)? It's a native application and not a powershell cmdlet so obviously it can't receive a powershell object – phuclv Nov 11 '22 at 16:44
  • 1
    yes, that's the tool. It's a very useful (for me) `cat` replacement that syntax highlights all code files. I put it somewhere on my path and then do `function ca { bat $args -p }` (the -p makes it act like a normal parser, like normal `cat` output, and I use `ca` instead of `cat` to not interfere with `cat` default), and then I can view files on the console in Technicolour ©™® instead of drab black and white. – YorSubs Nov 11 '22 at 16:45
  • Ok, it can't receive the object. How can I then turn that object into text? I tried using `out-string` also and that didn't help. i.e. how can I allow `bat` to manipulate the output of `function:\mkdir` – YorSubs Nov 11 '22 at 16:46
  • 1
    the function: provider outputs a scriptblock object. Maybe you can do something like `bat ((cat Function:\mkdir).toString())`, but you might have to trim line endings or something. Or you can copy the whole thing with `cat function:\mkdir | Set-Clipboard` and paste it into something with highlighting – Cpt.Whale Nov 11 '22 at 16:55
  • It's not *irrelevant*, but maybe more of a superuser questions. Ok, I'll close it, just was confused by this. Thanks CptWhale, that's perfect, works great.. – YorSubs Nov 11 '22 at 17:03
  • 1
    The main problem here is that you're trying to use a `cat`-replacement in place of something that _isn't_ cat - `cat` in PowerShell is an alias for `Get-Content`, and as @Cpt.Whale explains it works natively with _all_ of PowerShell's content providers, not just the file system. – Mathias R. Jessen Nov 11 '22 at 17:10

1 Answers1

2

Use namespace variable notation:

# As argument.
bat $function:mkdir

# Via the pipeline
$function:mkdir | bat

Note:

  • If the function name contains special characters, such as -, enclose the entire identifier in {...}, such as ${function:Get-Foo}.

  • As an aside:

    • As noted, in PowerShell on Windows, cat is a built-in alias for Get-Content. By contrast, in PowerShell on Unix-like platforms, cat refers to the standard Unix utility (/bin/cat).

In short:

  • $function:mkdir is the equivalent of Get-Content function:mkdir

  • The result is a [scriptblock] instance, which is implicitly stringified when you pass it to an external program, such as bat in your case.

    • A script block conveniently stringifies to its verbatim content, i.e. to its source code. (In the case of a script-block literal - { ... } - the { and } are not included).
  • Namespace variable notation only works with literal function names; use the Get-Content equivalent if the function must be supplied via a variable or expression:

    $cmd = 'mkdir'
    
    # As argument.
    bat (Get-Content function:$cmd)
    
    # Via the pipeline
    (Get-Content function:$cmd) | bat
    
mklement0
  • 382,024
  • 64
  • 607
  • 775