diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 70415f69fbe..96d2615c1f7 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -78,6 +78,7 @@ (declare-function treesit-node-child-by-field-name "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-prev-sibling "treesit.c") +(declare-function treesit-node-first-child-for-pos "treesit.c") ;;; Custom variables @@ -108,7 +109,8 @@ just toggles it when zero or left out." (defun c-ts-mode-set-modeline () (setq mode-name - (concat (if (eq major-mode 'c-ts-mode) "C" "C++") comment-start)) + (concat (if (eq major-mode 'c-ts-mode) "C" "C++") + (string-trim-right comment-start))) (force-mode-line-update)) (defun c-ts-mode--indent-style-setter (sym val) @@ -280,12 +282,19 @@ PARENT and BOL are like other anchor functions." (or (treesit-node-prev-sibling node t) (treesit-node-prev-sibling (treesit-node-first-child-for-pos parent bol) t) - (treesit-node-child parent -1 t)))) - (while (and prev-sibling - (equal "labeled_statement" - (treesit-node-type prev-sibling))) - ;; The 0th child is the label, the 1th the colon. - (setq prev-sibling (treesit-node-child prev-sibling 2))) + (treesit-node-child parent -1 t))) + (continue t)) + (while (and prev-sibling continue) + (pcase (treesit-node-type prev-sibling) + ;; Get the statement in the label. + ("labeled_statement" + (setq prev-sibling (treesit-node-child prev-sibling 2))) + ;; Get the last statement in the preproc. Tested by + ;; "Prev-Sibling When Prev-Sibling is Preproc" test. + ((or "preproc_if" "preproc_ifdef" "preproc_elif" "preproc_else") + (setq prev-sibling (treesit-node-child prev-sibling -2))) + ;; Don't do anything special. + (_ (setq continue nil)))) ;; This could be nil if a) there is no prev-sibling or b) ;; prev-sibling doesn't have a child. (treesit-node-start prev-sibling))) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index cd7b6a10868..e6f38792645 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1206,7 +1206,7 @@ Each function is passed the server as an argument") ;; ;; Not only does this seem like there should be a better way, ;; but it almost certainly doesn’t work on non-unix systems. - (list "sh" "-c" + (list shell-file-name "-c" (string-join (cons "stty raw > /dev/null;" (mapcar #'shell-quote-argument contact)) " ")) diff --git a/lisp/url/url-auth.el b/lisp/url/url-auth.el index e9ee72029f3..6848c0c73a7 100644 --- a/lisp/url/url-auth.el +++ b/lisp/url/url-auth.el @@ -100,7 +100,10 @@ instead of the filename inheritance method." (setq retval (base64-encode-string (format "%s:%s" user - (encode-coding-string pass 'utf-8)) + (if pass + (encode-coding-string pass + 'utf-8) + "")) t)))) (symbol-value url-basic-auth-storage)))) (byserv diff --git a/lisp/xwidget.el b/lisp/xwidget.el index abbda29081e..7daca81f9f7 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -925,7 +925,8 @@ Return the buffer." "Display the current xwidget webkit URL and place it on the `kill-ring'." (interactive nil xwidget-webkit-mode) (let ((url (xwidget-webkit-uri (xwidget-webkit-current-session)))) - (message "URL: %s" (kill-new (or url ""))))) + (when url (kill-new url)) + (message "URL: %s" url))) (defun xwidget-webkit-browse-history () "Display a buffer containing the history of page loads." diff --git a/src/nsxwidget.h b/src/nsxwidget.h index 8d55fac5326..2b5596f905e 100644 --- a/src/nsxwidget.h +++ b/src/nsxwidget.h @@ -36,6 +36,8 @@ Lisp_Object nsxwidget_webkit_uri (struct xwidget *xw); Lisp_Object nsxwidget_webkit_title (struct xwidget *xw); void nsxwidget_webkit_goto_uri (struct xwidget *xw, const char *uri); void nsxwidget_webkit_goto_history (struct xwidget *xw, int rel_pos); +double nsxwidget_webkit_estimated_load_progress(struct xwidget *xw); +void nsxwidget_webkit_stop_loading (struct xwidget *xw); void nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change); void nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script, Lisp_Object fun); diff --git a/src/nsxwidget.m b/src/nsxwidget.m index e1fbd749b62..0e00589bb7f 100644 --- a/src/nsxwidget.m +++ b/src/nsxwidget.m @@ -57,12 +57,13 @@ @interface XwWebView : WKWebView @end @implementation XwWebView : WKWebView -- (id)initWithFrame:(CGRect)frame +- (id) initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration xwidget:(struct xwidget *)xw { /* Script controller to add script message handler and user script. */ - WKUserContentController *scriptor = [[WKUserContentController alloc] init]; + WKUserContentController *scriptor = [[[WKUserContentController alloc] init] + autorelease]; configuration.userContentController = scriptor; /* Enable inspect element context menu item for debugging. */ @@ -81,7 +82,8 @@ - (id)initWithFrame:(CGRect)frame if (self) { self.xw = xw; - self.urlScriptBlocked = [[NSMutableDictionary alloc] init]; + self.urlScriptBlocked = [[[NSMutableDictionary alloc] init] + autorelease]; self.navigationDelegate = self; self.UIDelegate = self; self.customUserAgent = @@ -89,23 +91,48 @@ - (id)initWithFrame:(CGRect)frame @" AppleWebKit/603.3.8 (KHTML, like Gecko)" @" Version/11.0.1 Safari/603.3.8"; [scriptor addScriptMessageHandler:self name:@"keyDown"]; - [scriptor addUserScript:[[WKUserScript alloc] - initWithSource:xwScript - injectionTime: - WKUserScriptInjectionTimeAtDocumentStart - forMainFrameOnly:NO]]; + WKUserScript *userScript = [[[WKUserScript alloc] + initWithSource:xwScript + injectionTime: + WKUserScriptInjectionTimeAtDocumentStart + forMainFrameOnly:NO] autorelease]; + [scriptor addUserScript:userScript]; } return self; } -- (void)webView:(WKWebView *)webView +/* These 4 functions emulate the behavior of webkit_view_load_changed_cb + in the GTK implementation*/ +- (void) webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { if (EQ (Fbuffer_live_p (self.xw->buffer), Qt)) - store_xwidget_event_string (self.xw, "load-changed", ""); + store_xwidget_event_string (self.xw, "load-changed", "load-finished"); } -- (void)webView:(WKWebView *)webView +- (void) webView:(WKWebView *)webView +didStartProvisionalNavigation:(WKNavigation *)navigation +{ + if (EQ (Fbuffer_live_p (self.xw->buffer), Qt)) + store_xwidget_event_string (self.xw, "load-changed", "load-started"); +} + +- (void) webView:(WKWebView *)webView +didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation +{ + if (EQ (Fbuffer_live_p (self.xw->buffer), Qt)) + store_xwidget_event_string (self.xw, "load-changed", "load-redirected"); +} + +/* Start loading WKWebView */ +- (void) webView:(WKWebView *)webView +didCommitNavigation:(WKNavigation *)navigation +{ + if (EQ (Fbuffer_live_p (self.xw->buffer), Qt)) + store_xwidget_event_string (self.xw, "load-changed", "load-committed"); +} + +- (void) webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { @@ -114,13 +141,13 @@ - (void)webView:(WKWebView *)webView decisionHandler (WKNavigationActionPolicyAllow); break; default: - // decisionHandler (WKNavigationActionPolicyCancel); + /* decisionHandler (WKNavigationActionPolicyCancel); */ decisionHandler (WKNavigationActionPolicyAllow); break; } } -- (void)webView:(WKWebView *)webView +- (void) webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { @@ -166,7 +193,7 @@ - (void)webView:(WKWebView *)webView /* No additional new webview or emacs window will be created for . */ -- (WKWebView *)webView:(WKWebView *)webView +- (WKWebView *) webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures @@ -177,7 +204,7 @@ - (WKWebView *)webView:(WKWebView *)webView } /* Open panel for file upload. */ -- (void)webView:(WKWebView *)webView +- (void) webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray *URLs))completionHandler @@ -197,13 +224,13 @@ - (void)webView:(WKWebView *)webView - Correct mouse hand/arrow/I-beam is displayed (TODO: not perfect yet). */ -- (void)mouseDown:(NSEvent *)event +- (void) mouseDown:(NSEvent *)event { [self.xw->xv->emacswindow mouseDown:event]; [super mouseDown:event]; } -- (void)mouseUp:(NSEvent *)event +- (void) mouseUp:(NSEvent *)event { [self.xw->xv->emacswindow mouseUp:event]; [super mouseUp:event]; @@ -214,7 +241,7 @@ - (void)mouseUp:(NSEvent *)event emacs as first responder to avoid focus held in an input element with matching text. */ -- (void)keyDown:(NSEvent *)event +- (void) keyDown:(NSEvent *)event { Lisp_Object var = Fintern (build_string ("isearch-mode"), Qnil); Lisp_Object val = buffer_local_value (var, Fcurrent_buffer ()); @@ -250,7 +277,7 @@ - (void)keyDown:(NSEvent *)event }]; } -- (void)interpretKeyEvents:(NSArray *)eventArray +- (void) interpretKeyEvents:(NSArray *)eventArray { /* We should do nothing and do not forward (default implementation if we not override here) to let emacs collect key events and ask @@ -258,7 +285,7 @@ - (void)interpretKeyEvents:(NSArray *)eventArray } static NSString *xwScript; -+ (void)initialize ++ (void) initialize { /* Find out if an input element has focus. Message to script message handler when 'C-g' key down. */ @@ -284,7 +311,7 @@ + (void)initialize /* Confirming to WKScriptMessageHandler, listens concerning keyDown in webkit. Currently 'C-g'. */ -- (void)userContentController:(WKUserContentController *)userContentController +- (void) userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.body isEqualToString:@"C-g"]) @@ -343,6 +370,20 @@ - (void)userContentController:(WKUserContentController *)userContentController } } +double +nsxwidget_webkit_estimated_load_progress (struct xwidget *xw) +{ + XwWebView *xwWebView = (XwWebView *) xw->xwWidget; + return xwWebView.estimatedProgress; +} + +void +nsxwidget_webkit_stop_loading (struct xwidget *xw) +{ + XwWebView *xwWebView = (XwWebView *) xw->xwWidget; + [xwWebView stopLoading]; +} + void nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change) { @@ -430,7 +471,7 @@ - (void)userContentController:(WKUserContentController *)userContentController } else if (result && FUNCTIONP (fun)) { - // NSLog (@"result=%@, type=%@", result, [result class]); + /* NSLog (@"result=%@, type=%@", result, [result class]); */ Lisp_Object lisp_value = js_to_lisp (result); store_xwidget_js_callback_event (xw, fun, lisp_value); } @@ -440,19 +481,20 @@ - (void)userContentController:(WKUserContentController *)userContentController /* Window containing an xwidget. */ @implementation XwWindow -- (BOOL)isFlipped { return YES; } +- (BOOL) isFlipped { return YES; } @end /* Xwidget model, macOS Cocoa part. */ void -nsxwidget_init(struct xwidget *xw) +nsxwidget_init (struct xwidget *xw) { block_input (); NSRect rect = NSMakeRect (0, 0, xw->width, xw->height); xw->xwWidget = [[XwWebView alloc] initWithFrame:rect - configuration:[[WKWebViewConfiguration alloc] init] + configuration:[[[WKWebViewConfiguration alloc] init] + autorelease] xwidget:xw]; xw->xwWindow = [[XwWindow alloc] initWithFrame:rect]; @@ -470,16 +512,18 @@ - (BOOL)isFlipped { return YES; } ((XwWebView *) xw->xwWidget).configuration.userContentController; [scriptor removeAllUserScripts]; [scriptor removeScriptMessageHandlerForName:@"keyDown"]; - [scriptor release]; + if (xw->xv) xw->xv->model = Qnil; /* Make sure related view stale. */ /* This stops playing audio when a xwidget-webkit buffer is - killed. I could not find other solution. */ + killed. I could not find other solution. + TODO: improve this */ nsxwidget_webkit_goto_uri (xw, "about:blank"); [((XwWebView *) xw->xwWidget).urlScriptBlocked release]; [xw->xwWidget removeFromSuperviewWithoutNeedingDisplay]; + [xw->xwWidget release]; [xw->xwWindow removeFromSuperviewWithoutNeedingDisplay]; [xw->xwWindow release]; @@ -507,7 +551,7 @@ - (BOOL)isFlipped { return YES; } /* Xwidget view, macOS Cocoa part. */ @implementation XvWindow : NSView -- (BOOL)isFlipped { return YES; } +- (BOOL) isFlipped { return YES; } @end void diff --git a/src/xwidget.c b/src/xwidget.c index efe27055629..7f30e48c954 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -3063,6 +3063,36 @@ DEFUN ("xwidget-webkit-title", #endif } +DEFUN ("xwidget-webkit-estimated-load-progress", + Fxwidget_webkit_estimated_load_progress, Sxwidget_webkit_estimated_load_progress, + 1, 1, 0, doc: /* Get the estimated load progress of XWIDGET, a WebKit widget. +Return a value ranging from 0.0 to 1.0, based on how close XWIDGET +is to completely loading its page. */) + (Lisp_Object xwidget) +{ + struct xwidget *xw; +#ifdef USE_GTK + WebKitWebView *webview; +#endif + double value; + + CHECK_LIVE_XWIDGET (xwidget); + xw = XXWIDGET (xwidget); + CHECK_WEBKIT_WIDGET (xw); + + block_input (); +#ifdef USE_GTK + webview = WEBKIT_WEB_VIEW (xw->widget_osr); + value = webkit_web_view_get_estimated_load_progress (webview); +#elif defined NS_IMPL_COCOA + value = nsxwidget_webkit_estimated_load_progress (xw); +#endif + + unblock_input (); + + return make_float (value); +} + DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, 2, 2, 0, @@ -3810,28 +3840,6 @@ LIMIT is not specified or nil, it is treated as `50'. */) return list3 (back, here, forward); } -DEFUN ("xwidget-webkit-estimated-load-progress", - Fxwidget_webkit_estimated_load_progress, Sxwidget_webkit_estimated_load_progress, - 1, 1, 0, doc: /* Get the estimated load progress of XWIDGET, a WebKit widget. -Return a value ranging from 0.0 to 1.0, based on how close XWIDGET -is to completely loading its page. */) - (Lisp_Object xwidget) -{ - struct xwidget *xw; - WebKitWebView *webview; - double value; - - CHECK_LIVE_XWIDGET (xwidget); - xw = XXWIDGET (xwidget); - CHECK_WEBKIT_WIDGET (xw); - - block_input (); - webview = WEBKIT_WEB_VIEW (xw->widget_osr); - value = webkit_web_view_get_estimated_load_progress (webview); - unblock_input (); - - return make_float (value); -} #endif DEFUN ("xwidget-webkit-set-cookie-storage-file", @@ -3874,19 +3882,23 @@ This will stop any data transfer that may still be in progress inside XWIDGET as part of loading a page. */) (Lisp_Object xwidget) { -#ifdef USE_GTK struct xwidget *xw; +#ifdef USE_GTK WebKitWebView *webview; +#endif CHECK_LIVE_XWIDGET (xwidget); xw = XXWIDGET (xwidget); CHECK_WEBKIT_WIDGET (xw); block_input (); +#ifdef USE_GTK webview = WEBKIT_WEB_VIEW (xw->widget_osr); webkit_web_view_stop_loading (webview); - unblock_input (); +#elif defined NS_IMPL_COCOA + nsxwidget_webkit_stop_loading (xw); #endif + unblock_input (); return Qnil; } @@ -3936,8 +3948,9 @@ syms_of_xwidget (void) #ifdef USE_GTK defsubr (&Sxwidget_webkit_load_html); defsubr (&Sxwidget_webkit_back_forward_list); - defsubr (&Sxwidget_webkit_estimated_load_progress); #endif + + defsubr (&Sxwidget_webkit_estimated_load_progress); defsubr (&Skill_xwidget); DEFSYM (QCxwidget, ":xwidget"); diff --git a/test/lisp/wdired-tests.el b/test/lisp/wdired-tests.el index 897c6cd69a8..20caaff17c7 100644 --- a/test/lisp/wdired-tests.el +++ b/test/lisp/wdired-tests.el @@ -31,6 +31,10 @@ "Test using non-nil wdired-use-interactive-rename. Partially modifying a file name should succeed." (ert-with-temp-directory test-dir + ;; The call to file-truename is for MS-Windows, where numeric + ;; tails or some other feature (like SUBST) could cause file names + ;; to fail to compare 'equal'. + (setq test-dir (file-truename test-dir)) (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c")) (replace "bar") (new-file (string-replace "foo" replace test-file)) @@ -56,6 +60,7 @@ Partially modifying a file name should succeed." "Test using non-nil wdired-use-interactive-rename. Aborting an edit should leaving original file name unchanged." (ert-with-temp-directory test-dir + (setq test-dir (file-truename test-dir)) (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c")) (wdired-use-interactive-rename t)) (write-region "" nil test-file nil 'silent) @@ -106,6 +111,7 @@ only the name before the link arrow." Finding the new name should be possible while still in wdired-mode." (ert-with-temp-directory test-dir + (setq test-dir (file-truename test-dir)) (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c")) (replace "bar") (new-file (string-replace "foo" replace test-file))) @@ -143,7 +149,11 @@ wdired-get-filename before and after editing." (with-current-buffer buf (dired-create-empty-file "foo") (set-file-modes "foo" (file-modes-symbolic-to-number "+x")) - (make-symbolic-link "foo" "bar") + (skip-unless + ;; This check is for wdired, not symbolic links, so skip + ;; it when make-symbolic-link fails for any reason (like + ;; insufficient privileges). + (ignore-errors (make-symbolic-link "foo" "bar") t)) (make-directory "foodir") (dired-smart-shell-command "mkfifo foopipe") (when (featurep 'make-network-process '(:family local)) @@ -176,6 +186,7 @@ wdired-get-filename before and after editing." (ert-deftest wdired-test-bug39280 () "Test for https://debbugs.gnu.org/39280." (ert-with-temp-directory test-dir + (setq test-dir (file-truename test-dir)) (let* ((fname "foo") (full-fname (expand-file-name fname test-dir))) (make-empty-file full-fname) @@ -202,7 +213,11 @@ should be invisible again." (dired-hide-details-hide-symlink-targets t)) (unwind-protect (with-current-buffer buf - (make-symbolic-link "bar" "foo") + (skip-unless + ;; This check is for wdired, not symbolic links, so skip + ;; it when make-symbolic-link fails for any reason (like + ;; insufficient privileges). + (ignore-errors (make-symbolic-link "bar" "foo") t)) (dired-hide-details-mode) (should (memq 'dired-hide-details-link buffer-invisibility-spec)) (dired-toggle-read-only)