<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/assets/rss.xsl" type="text/xsl"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
	<title>Sacha Chua - tag - syncthing</title>
	<atom:link href="https://sachachua.com/blog/tag/syncthing/feed/index.xml" rel="self" type="application/rss+xml" />
	<atom:link href="https://sachachua.com/blog/tag/syncthing" rel="alternate" type="text/html" />
	<link>https://sachachua.com/blog/tag/syncthing/feed/index.xml</link>
	<description>Emacs, sketches, and life</description>
	<lastBuildDate>Tue, 22 Oct 2024 12:03:51 GMT</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>daily</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>11ty</generator>
  <item>
		<title>Tweaking Emacs on Android via Termux: xclip, xdg-open, syncthing conflicts</title>
		<link>https://sachachua.com/blog/2019/07/tweaking-emacs-on-android-via-termux-xclip-xdg-open-syncthing-conflicts/</link>
		<dc:creator><![CDATA[Sacha Chua]]></dc:creator>
		<pubDate>Sat, 13 Jul 2019 20:39:00 GMT</pubDate>
    <category>android</category>
<category>emacs</category>
		<guid isPermaLink="false">https://sachachua.com/blog/?p=29449</guid>
		<description><![CDATA[<p>Update: Fixed reference to termux.properties</p>
<p>I&#8217;m planning to leave my laptop at home during our 3-week trip, so I&#8217;ve been shifting more things to my phone in preparation. Orgzly is handy for reviewing my agenda and adding items on the go, but nothing beats Emacs for full flexibility. Runnng Emacs via Termux works pretty well. I can resize by pinch-zooming, scroll by swiping, and even enter in more text by swiping right on the row of virtual keyboard buttons.</p>
<p>Here&#8217;s what I&#8217;ve configured in <code>~/.termux/termux.properties</code>:</p>
<pre class="example">extra-keys = [['ESC','/','-','HOME','UP','END','PGUP','F5'],['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN','F6']]</pre>
<p>and here&#8217;s what that looks like:</p>
<p><a href="https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux.jpg"><img loading="lazy" class="alignnone size-medium wp-image-29450" src="https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux-640x1316.jpg" alt="Screenshot of Emacs" width="640" height="1316" srcset="https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux-640x1316.jpg 640w, https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux-97x200.jpg 97w, https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux-768x1579.jpg 768w, https://sachachua.com/blog/wp-content/uploads/2019/07/Screenshot_20190713-163813_Termux.jpg 1080w" sizes="(max-width: 640px) 100vw, 640px"></a></p>
<p>I patched my Termux to <a href="https://github.com/termux/termux-app/pull/1161">allow the use of function keys in the extra keys shortcut bar</a>. It&#8217;s been merged upstream, but the new version hasn&#8217;t been released yet, so I&#8217;m still running the one I compiled from source. It would be nice to fix <a href="https://github.com/termux/termux-app/issues/905">accidental keypresses when swiping extra keys to get to the input field</a>, but that can wait a bit.</p>
<p>I set up Syncthing to synchronize files with my server and laptop, Termux:API to make storage accessible, and symlinks in my home directory to replicate the main parts of my setup. I set up Orgzly to auto-sync with a local repository (synchronized with my server and laptop via Syncthing) and the same Org files set up in my agenda in Emacs on Termux. That way, I can hop between Orgzly and Emacs as quickly as I want. Here are a few tweaks that made Emacs even better.</p>
<p>First, a little bit of code for phone-specific config, taking advantage of the weird automatic username I have there.</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">my/phone-p</span> ()
  (<span class="org-keyword">and</span> (equal (system-name) <span class="org-string">"localhost"</span>) 
       (not (equal user-login-name <span class="org-string">"sacha"</span>))))</pre>
</div>
<p>For Emacs News, I wanted to be able to easily open Org Mode links to webpages by tapping on them. This code makes that work (and in general, anything that involves opening webpages):</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">setq</span> browse-url-browser-function 'browse-url-xdg-open)</pre>
</div>
<p>This piece of code cleans up my Inbox.org file so that it&#8217;s easier to skim in Orgzly. It archives all the done tasks and sorts them.</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">     (<span class="org-keyword">defun</span> <span class="org-function-name">my/org-clean-up-inbox</span> ()
       <span class="org-doc">"Archive all DONE tasks and sort the remainder by TODO order."</span>
       (<span class="org-keyword">interactive</span>)
       (<span class="org-keyword">with-current-buffer</span> (find-file my/org-inbox-file)
         (my/org-archive-done-tasks 'file)
         (goto-char (point-min))
         (<span class="org-keyword">if</span> (org-at-heading-p) (<span class="org-keyword">save-excursion</span> (insert <span class="org-string">"\n"</span>)))
         (org-sort-entries nil ?p)
         (goto-char (point-min))
         (org-sort-entries nil ?o)
         (save-buffer)))

     (<span class="org-keyword">defun</span> <span class="org-function-name">my/org-archive-done-tasks</span> (<span class="org-type">&amp;optional</span> scope)
       <span class="org-doc">"Archive finished or cancelled tasks.</span>
<span class="org-doc">SCOPE can be 'file or 'tree."</span>
       (<span class="org-keyword">interactive</span>)
       (org-map-entries
        (<span class="org-keyword">lambda</span> ()
          (org-archive-subtree)
          (<span class="org-keyword">setq</span> org-map-continue-from (outline-previous-heading)))
        <span class="org-string">"TODO=\"DONE\"|TODO=\"CANCELLED\""</span> (<span class="org-keyword">or</span> scope (<span class="org-keyword">if</span> (org-before-first-heading-p) 'file 'tree))))</pre>
</div>
<p>I also sometimes wanted to copy and paste between Termux and Emacs by using the keyboard, so I submitted a patch for xclip.el so that it would detect and work with <code>termux-clipboard-get/set</code>. That code is now in xclip 1.9 in ELPA, so if you <code>M-x package-install</code> xclip, you should be able to turn on <code>xclip-mode</code> and have it copy and paste between applications. In my config, that looks like:</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">when</span> (my/phone-p)
  (<span class="org-keyword">use-package</span> <span class="org-constant">xclip</span> <span class="org-builtin">:config</span> (xclip-mode 1)))</pre>
</div>
<p>Because I use Orgzly and Termux to edit my Org files <i>and</i> I also edit the files on my laptop, I occasionally get synchronization errors. I came across this handy bit of code to <a href="https://www.reddit.com/r/emacs/comments/bqqqra/quickly_find_syncthing_conflicts_and_resolve_them/">find Syncthing conflicts and resolve them</a>. I just had to change some of the code (in bold below) in order to make it work, and I needed to <code>pkg install diffutils</code> to solve the diff errors. Here&#8217;s the fixed code below, along with a convenience function that checks my Orgzly directory:</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">my/resolve-orgzly-syncthing</span> ()
  (<span class="org-keyword">interactive</span>)
  (ibizaman/syncthing-resolve-conflicts <span class="org-string">"~/cloud/orgzly"</span>))

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing-resolve-conflicts</span> (directory)
  <span class="org-doc">"Resolve all conflicts under given DIRECTORY."</span>
  (<span class="org-keyword">interactive</span> <span class="org-string">"D"</span>)
  (<span class="org-keyword">let<strong>*</strong></span> ((all (ibizaman/syncthing&#45;&#45;get-sync-conflicts directory))
        (chosen (ibizaman/syncthing&#45;&#45;pick-a-conflict all)))
    (ibizaman/syncthing-resolve-conflict chosen)))

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing-show-conflicts-dired</span> (directory)
  <span class="org-doc">"Open dired buffer at DIRECTORY showing all syncthing conflicts."</span>
  (<span class="org-keyword">interactive</span> <span class="org-string">"D"</span>)
  (find-name-dired directory <span class="org-string">"*.sync-conflict-*"</span>))

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing-resolve-conflict-dired</span> (<span class="org-type">&amp;optional</span> arg)
  <span class="org-doc">"Resolve conflict of first marked file in dired or close to point with ARG."</span>
  (<span class="org-keyword">interactive</span> <span class="org-string">"P"</span>)
  (<span class="org-keyword">let</span> ((chosen (car (dired-get-marked-files nil arg))))
    (ibizaman/syncthing-resolve-conflict chosen)))

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing-resolve-conflict</span> (conflict)
  <span class="org-doc">"Resolve CONFLICT file using ediff."</span>
  (<span class="org-keyword">let*</span> ((normal (ibizaman/syncthing&#45;&#45;get-normal-filename conflict)))
    (ibizaman/ediff-files
     (list conflict normal)
     `(<span class="org-keyword">lambda</span> ()
       (<span class="org-keyword">when</span> (y-or-n-p <span class="org-string">"Delete conflict file? "</span>)
         (kill-buffer (get-file-buffer ,conflict))
         (delete-file ,conflict))))))

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing&#45;&#45;get-sync-conflicts</span> (directory)
  <span class="org-doc">"Return a list of all sync conflict files in a DIRECTORY."</span>
  (directory-files-recursively directory <span class="org-string">"\\.sync-conflict-"</span>))

(<span class="org-keyword">defvar</span> <span class="org-variable-name">ibizaman/syncthing&#45;&#45;conflict-history <strong>nil </strong></span>
  <span class="org-string">"Completion conflict history"</span>)

(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing&#45;&#45;pick-a-conflict</span> (conflicts)
  <span class="org-doc">"Let user choose the next conflict from CONFLICTS to investigate."</span>
  (completing-read <span class="org-string">"Choose the conflict to investigate: "</span> conflicts
                   nil t nil ibizaman/syncthing&#45;&#45;conflict-history))


(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/syncthing&#45;&#45;get-normal-filename</span> (conflict)
  <span class="org-doc">"Get non-conflict filename matching the given CONFLICT."</span>
  (replace-regexp-in-string <span class="org-string">"\\.sync-conflict-.*</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">(</span></span><span class="org-string">\\..*</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">)</span></span><span class="org-string">$"</span> <span class="org-string">"\\1"</span> conflict))


(<span class="org-keyword">defun</span> <span class="org-function-name">ibizaman/ediff-files</span> (<span class="org-type">&amp;optional</span> files quit-hook)
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">lexical-let</span> ((files (<span class="org-keyword">or</span> files (dired-get-marked-files)))
                (quit-hook quit-hook)
                (wnd (current-window-configuration)))
    (<span class="org-keyword">if</span> (&lt;= (length files) 2)
        (<span class="org-keyword">let</span> ((file1 (car files))
              (file2 (<span class="org-keyword">if</span> (cdr files)
                         (cadr files)
                       (read-file-name
                        <span class="org-string">"file: "</span>
                        (dired-dwim-target-directory)))))
          (<span class="org-keyword">if</span> (file-newer-than-file-p file1 file2)
              (ediff-files file2 file1)
            (ediff-files file1 file2))
          (add-hook 'ediff-after-quit-hook-internal
                    (<span class="org-keyword">lambda</span> ()
                      (<span class="org-keyword">setq</span> ediff-after-quit-hook-internal nil)
                      (<span class="org-keyword">when</span> quit-hook (funcall quit-hook))
                      (set-window-configuration wnd))))
      (<span class="org-warning">error</span> <span class="org-string">"no more than 2 files should be marked"</span>))))</pre>
</div>
<p>If you use Emacs on Android via Termux, I hope some of these tweaks help you too!</p>
]]></description>
		</item>
	</channel>
</rss>