From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14462 invoked by alias); 3 Sep 2018 00:40:56 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: List-Unsubscribe: X-Seq: 23601 Received: (qmail 5389 invoked by uid 1010); 3 Sep 2018 00:40:56 -0000 X-Qmail-Scanner-Diagnostics: from mail-pl1-f195.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(209.85.214.195):SA:0(1.6/5.0):. Processed in 2.956679 secs); 03 Sep 2018 00:40:56 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: * X-Spam-Status: No, score=1.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM, FSL_HELO_FAKE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_PASS, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.1 X-Envelope-From: joeypabalinas@gmail.com X-Qmail-Scanner-Mime-Attachments: |signature.asc| X-Qmail-Scanner-Zip-Files: | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Kt+1NzlDSx9wu29U9wXsGRsWBOXItHgs4AYXnsLmHUs=; b=U1xWoKxwz59YK3pww9o71TcoDsB4zZ7o8Nw4qqHdIFnUuOBkkBgRkj0ffYkXFw3tC/ Pbpxn6ULGzUn73Z9FQ8DATdYW2NJe5zq8/8HH6RYvOZkHgEflZnosXsG3NRFFKVpZc8W NfC3GxDAZEKNMwLipxrocSAUhKqpRqW0VaKucqnDipq/RrSaxBT52X8IQ1pC2dUAAQQ1 VGOLRE0NFbejkAipObwcY6ho7dnB7byLHCND5Skk2TfgpViNcVhdlp1vqtqNpM1O7d4+ uLOpO7Mn4hLtkGqjS/0ZY6QSp75gt0SgskE4noZ2rbCwU6r62+AOKHAqIpuexS8/wSwn WCgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=Kt+1NzlDSx9wu29U9wXsGRsWBOXItHgs4AYXnsLmHUs=; b=jiw5mI1+JyRmHh2aopuW/l+oDK4rAIot9i/DAdqSojlEuWOlyRitGFxzGacQ7b8Ve5 a4F2x2vDtQhfiENTBB6neyY1tGCmtpAzxgUjstVnRK/cj6Ix7g4+WWl/5WEN3xpyF1i7 6UL1UPEivVHkTzvxhfqBqH4r0PkwOT4oAEilohynNbGmbl7irwgzv9VcMf/UkxXAq7J/ o7HF1l+5ETV5TIU/w7OVRg/oALI/h65ecGbct8LTQsZQNXeK9ZX/Rus26PcZbW/nxnO3 ZVDWyQEnOFTV3pFrqq5uHUqJ86PQWtgRZGre5qPb8Goad+alteaY+TWnBlV9JuGRe9TD xT2g== X-Gm-Message-State: APzg51D0XbkGSiSn7bMm3cBDUxsmQs2sIVpSTmohy8Ex9D9TjS7tbJhG S1hxhiUzBdGU2RbRyRxnL5TNxPp7 X-Google-Smtp-Source: ANB0Vda7ApFKp2c8kfQzXfbK/HNmHVehzuXNdayRu5tW3PBEe8zQWuGBrfF+m6u9qKLYAAooz7EWWg== X-Received: by 2002:a17:902:163:: with SMTP id 90-v6mr25661830plb.322.1535935250677; Sun, 02 Sep 2018 17:40:50 -0700 (PDT) Date: Sun, 2 Sep 2018 14:40:47 -1000 From: Joey Pabalinas To: Ben Klein Cc: zsh-users@zsh.org, Joey Pabalinas Subject: Re: Capturing STDOUT without subshells or file I/O Message-ID: <20180903004047.ew2kvmzhnecqgki2@gmail.com> References: <04a12c6a-c926-b088-f386-8a2bdb81dad2@gmail.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="sddeeyo3tg5gtxnm" Content-Disposition: inline In-Reply-To: <04a12c6a-c926-b088-f386-8a2bdb81dad2@gmail.com> User-Agent: NeoMutt/20180716 --sddeeyo3tg5gtxnm Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Sep 02, 2018 at 04:57:49PM -0400, Ben Klein wrote: > Currently, I have this: >=20 > =C2=A0 p10k_render_prompt_from_spec p10k_left p10k_opts > $tmpd/prompt > =C2=A0 read -d $'\0' _P10K_RENDERED_OUTPUT_PROMPT < $tmpd/prompt > =C2=A0 p10k_render_prompt_from_spec p10k_right p10k_opts right > $tmpd/pr= ompt > =C2=A0 read -d $'\0' _P10K_RENDERED_OUTPUT_RPROMPT < $tmpd/prompt >=20 > And that involves creating a temporary file (/tmp) which might be > mounted on a spinning drive, so performance might take a hit. >=20 > The other route using a pipe: >=20 > p10k_render_prompt_from_spec p10k_left p10k_opts | read -d $'\0' > _P10K_RENDERED_OUTPUT_PROMPT >=20 > Causes environment variables and changes made during the `render_prompt` > call to be ignored. (Ends up in a subshell...?) >=20 > Is there some way I can use a virtual FD, or perhaps Zsh provides some > kind of buffer I could use instead? >=20 > In the end, I'm looking for a way to connect STDOUT to STDIN between ZSH > functions/builtins without any subshells or file I/O. (It's fine if it > gets buffered until close-of-stream.) You can sort of use the fact that if you delete the filesystem name of a temporary file (which would make the hard link count 0), as long as there still exists open file descriptors referring to it, you are still able to read/write to it. Let's make an example function that changes $FOO from 0 to 42, then prints some output, sort of like your function: > % FOO=3D0 > % fun() { FOO=3D42; print -r - "output of $funcstack[1]()"; } > % print -r - "FOO=3D$FOO" > FOO=3D0 Now we will use mktemp(1) to create a file in a tmpfs (usually /tmp) directory, which a swap-backed ramdisk, then redirects an arbitrary read/write fd to it and deletes the file: > % tmp=3D$(mktemp) > % exec {FD}<>$tmp > % rm -fv -- $tmp > removed '/tmp/tmp.sS1G9F6OjR' The redirected file descriptor is still open however (if you have colors in your ls you will see it in red because the file no longer exists), and you can write to it by redirecting stdout: > % ls -li /proc/$$/fd > 29987340 lrwx------ 1 jp jp 64 Sep 2 14:36 0 -> /dev/pts/2 > 29986634 lrwx------ 1 jp jp 64 Sep 2 14:36 1 -> /dev/pts/2 > 29986638 lrwx------ 1 jp jp 64 Sep 2 14:36 12 -> /tmp/tmp.dneCPiOqS5 > 29986635 lrwx------ 1 jp jp 64 Sep 2 14:36 2 -> /dev/pts/2 > % fun >&$FD Reading back your output, however, is a little weirder. The r/w file descriptor file position is set past your output; reading =66rom it normally would give us back our output. You also can't reopen it (file is gone), nor is there a mechanism in zsh to call something like lseek(2) to rewind file descriptors. However, what we *can* do it (ab)use the fact that subshells will rewind the file descriptors since they are duplicated during fork(). So we can make a subshell, redirect our fd to stdin and read back what we have written! Like so: > hobbes% output=3D$(( hobbes% print -lr - "FOO=3D$FOO" "output=3D\"$output\"" > FOO=3D42 > output=3D"output of fun()" And of course, it's always good practice to close your file descriptors in the main shell instance (subshell file descriptors are implicitly closed when the subshell exits) when you are finished with them: > hobbes% exec {FD}>&- Of course, realize this is kind of a hacky solution, and the better way is to just have your function either not play with the current environment (does something like a prompt generation script really need to change the environment?) or have it set `PROMPT` and `RPROMPT` itself and avoid worrying stdout at all. But hey, we all need to have a little fun sometimes :) --=20 Cheers, Joey Pabalinas --sddeeyo3tg5gtxnm Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEKlZXrihdNOcUPZTNruvLfWhyVBkFAluMgw4ACgkQruvLfWhy VBmzWw//aCXW9+PJ8QHPbSmqKKmwj0egUVGfEjbbxjgcD29SBFXU6mg4t9TMauGN hJiYxwl3G5E5ioS+SBf8TN1fMY0hM5CM24yFofXAnMV6u5UPsqJW5z/Uc+36/RqT TFBHpI7CqzxSzCIFKV22d0yXO+PqfZT1ktnCFeDcrwdBSp9JaI/ycOhdoV9dNIrg ncrwnxtrv+eLnMZ1sjZy2jF/EfNPi7WCQOvgdG9mNktygNocwQejHIMdXp+isPg6 A4d+DVBpKaMjO0a8QIygSjqMeNlvDVfqFUdp/TZW3a/vz55BBsJVvCTZRdQ1dajx pMPHo0fMK9//aQRAyW5tlBVBI92Nk0qkjCHMBhUySe4WMuKRwrh5N+FbEKxWQJpO VeE415lw69VCdXg/ITEVYcXqnbz65gOWQIcjsGRwqNT7BHu0lfyP3GgEE0OiTk0i TTGRHLgHb9SgqncQ3LFj0daZChB4Vxa8iONuqqRavViH1w0IHRvQT8xQ7/Yc3FxI J3K4zMTJBIwWE/MBkW9wHyfg0yq3luRtdzybThZJwpz419ppxRPRNUSH/Nd1iBYZ pxTihMXNK6Y9auNAXrGCaZLfkZeTeWnKGLlGYLVaVEWOWA00BHbU7lodGXEkBTbw Dz/ohduPDM9V0RUO9waOOD7MngD3JAC+vqcjPe+Jl2oJeU4aZek= =PVyJ -----END PGP SIGNATURE----- --sddeeyo3tg5gtxnm--