From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Ricardo Wurmus Newsgroups: gmane.emacs.devel Subject: interactive closure =?utf-8?Q?=E2=80=94?= variables not bound Date: Wed, 28 Sep 2016 08:21:10 +0200 Message-ID: <87y42ch7e1.fsf@elephly.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1475043754 11626 195.159.176.226 (28 Sep 2016 06:22:34 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 28 Sep 2016 06:22:34 +0000 (UTC) User-Agent: mu4e 0.9.16; emacs 25.1.1 To: Emacs developers Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Sep 28 08:22:31 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bp8Fw-0000Qo-NI for ged-emacs-devel@m.gmane.org; Wed, 28 Sep 2016 08:22:12 +0200 Original-Received: from localhost ([::1]:56340 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bp8Fv-00075t-1z for ged-emacs-devel@m.gmane.org; Wed, 28 Sep 2016 02:22:11 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60334) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bp8F7-00071a-DW for emacs-devel@gnu.org; Wed, 28 Sep 2016 02:21:22 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bp8F4-00065P-4L for emacs-devel@gnu.org; Wed, 28 Sep 2016 02:21:21 -0400 Original-Received: from sender163-mail.zoho.com ([74.201.84.163]:21329) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bp8F3-00064V-Rz for emacs-devel@gnu.org; Wed, 28 Sep 2016 02:21:18 -0400 Original-Received: from localhost (xd933ffaa.dyn.telefonica.de [217.51.255.170]) by mx.zohomail.com with SMTPS id 1475043676008288.1515556297685; Tue, 27 Sep 2016 23:21:16 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 74.201.84.163 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:207850 Archived-At: Hi emacs-devel, I’m currently attempting to rewrite some of the procedures and commands in xwidget.el to do without the “title hack”. Currently, the return value of any JavaScript snippet that is run in WebKit is stored in the title and then read out by running JavaScript to retrieve the title. With the WebKit2 API all JavaScript is run asynchronously. I’ve changed “xwidget-webkit-execute-script” such that it takes an optional third argument holding a Lisp callback, which is invoked with the return value from JavaScript using “call1”. This works fine for the most part, although using callbacks is a little less convenient than doing things synchronously (which is not supported by WebKit2). Now there is at least one instance where things aren’t as smooth. Take “xwidget-webkit-insert-string” for example. It is a command using either “read-string” or “read-passwd” dependent on the input field type. The input field type is retrieved using JavaScript. Using the title hack this can be implemented in a faux synchronous fashion: (defun xwidget-webkit-insert-string (xw str) … (interactive (let* ((xww …) (field-value …) (field-type (xwidget-webkit-execute-script-rv xww "findactiveelement(document).type;"))) (list xww (cond ((equal "text" field-type) (read-string "Text: " field-value)) ((equal "password" field-type) (read-passwd "Password: " nil field-value)) ((equal "textarea" field-type) …))))) … ; do things with “xw” and “str” ) Using callbacks instead we have a problem, because the return value of the JavaScript is only available in the callback procedure, not in the “interactive” form. To go around this problem I’m now trying to split up “xwidget-webkit-insert-string” in two parts: * “xwidget-webkit-insert-string”, which remains the interactive command exposed to the user. It runs the JavaScript expression and in the callback passes the return value to … * … a second interactive command, which takes care of prompting the user for a string to input. This looks something like this: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (defun xwidget-webkit-insert-string () (interactive) (let ((xww (xwidget-webkit-current-session))) (xwidget-webkit-execute-script xww (concat xwidget-webkit-activeelement-js "var res = findactiveelement(document); [res.value, res.type];") ;; This is called with “call1” from within “xwidget.c” when the ;; JavaScript return value is available (lambda (field) (let* ((field-value (car field)) (field-type (cadr field))) (call-interactively (lambda (str) (interactive (list (cond ((equal "text" field-type) (read-string "Text: " field-value)) ((equal "password" field-type) (read-passwd "Password: " nil field-value)) ((equal "textarea" field-type) (xwidget-webkit-begin-edit-textarea xww field-value))))) (xwidget-webkit-execute-script xww (format "findactiveelement(document).value='%s'" str))))))))) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The problem with this definition is that it doesn’t work (the other problem is that I’m replacing one ugly hack with another). At runtime Emacs says that “field-type” is undefined. At compile time Emacs says that in the callback “xww”, “field-value”, and “field-type” are references to free variables. But why? Isn’t this a closure? “field-value” and “field-type” are let-bound inside of the callback, so they should be available in the scope of the interactive lambda’s “cond”. I’ve also tried to do without “interactive” and just use “read-string” directly, but while this gives me a prompt at runtime it also freezes Emacs and eats up all my memory (which might be normal when using “read-string” in a lambda that’s called from C with “call1”, dunno). ~~ Ricardo PS: I’ve sent an email to assign@gnu.org a week ago with a completed request form template, but haven’t received any response yet.