jarun / ddgr

:duck: DuckDuckGo from the terminal
GNU General Public License v3.0
2.92k stars 139 forks source link

Copy multiple urls #139

Closed kendfss closed 2 years ago

kendfss commented 2 years ago

Sometimes you want to copy more than one url at a time, particularly when looking for files and documents to download with tools like curl or wget. In order to implement this I've taken the following steps which, I hope, serve as a minimal change to the current program structure:

lots of lines here

class DdgCmd:

...

def cmdLoop(self):
    # ...
            elif re.match("c [\s\d]+", cmd):
                self.copy_urls(map(int, cmd[2:].split()))
- change the `copy_url` method of the `DdgCmd` class to `copy_urls`
```py
class DdgCmd:
    # ...
    def copy_urls(self, indices):
        self.clipboard.clear()

        for idx in indices:
            if 0 < idx <= min(self._opts.num, len(self._urltable)):
                self.clipboard.add_line(self._urltable[str(idx)])
            else:
                printerr("invalid index")

        self.clipboard.write()
class Clipboard:
    """
    Handler for copying events.

    Parameters
    ----------
    N/A

    Attributes
    ----------
    __lines : list[str]

    Class Variables
    ---------------
    N/A

    Methods
    -------
    add_line(str)
    clear()
    write()

    Properties
    -------
    lines : list[str]
    content : bytes

    """
    def __init__(self):
        self.clear()

    def add_line(self, string):
        self.__lines.append(string)

    def clear(self):
        self.__lines = []

    @property
    def content(self):
        return os.linesep.join(self.lines).encode('utf-8')

    @property
    def lines(self):
        return self.__lines

    def write(self):
        try:
            # try copying the url to clipboard using native utilities
            copier_params = []
            if sys.platform.startswith(('linux', 'freebsd', 'openbsd')):
                if shutil.which('xsel') is not None:
                    copier_params = ['xsel', '-b', '-i']
                elif shutil.which('xclip') is not None:
                    copier_params = ['xclip', '-selection', 'clipboard']
                elif shutil.which('wl-copy') is not None:
                    copier_params = ['wl-copy']
                # If we're using Termux (Android) use its 'termux-api'
                # add-on to set device clipboard.
                elif shutil.which('termux-clipboard-set') is not None:
                    copier_params = ['termux-clipboard-set']
            elif sys.platform == 'darwin':
                copier_params = ['pbcopy']
            elif sys.platform == 'win32':
                copier_params = ['clip']
            elif sys.platform.startswith('haiku'):
                copier_params = ['clipboard', '-i']

            if copier_params:
                Popen(copier_params, stdin=PIPE, stdout=DEVNULL, stderr=DEVNULL).communicate(self.content)
                return

            # If native clipboard utilities are absent, try to use terminal multiplexers
            # tmux
            if os.getenv('TMUX_PANE'):
                copier_params = ['tmux', 'set-buffer']
                Popen(copier_params + [self.content], stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL).communicate()
                print('URL copied to tmux buffer.')
                return

            # GNU Screen paste buffer
            if os.getenv('STY'):
                copier_params = ['screen', '-X', 'readbuf', '-e', 'utf8']
                tmpfd, tmppath = tempfile.mkstemp()
                try:
                    with os.fdopen(tmpfd, 'wb') as fp:
                        fp.write(self.content)
                    copier_params.append(tmppath)
                    Popen(copier_params, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL).communicate()
                finally:
                    os.unlink(tmppath)
                return

            printerr('failed to locate suitable clipboard utility')
        except Exception as e:
            raise NoKeywordsException from e
class DdgCmd:
    # ...
    def __init__(self, *args, **kwargs):
        # ...
        self.clipboard = Clipboard()
jarun commented 2 years ago

Thanks for sharing. No plans to incorporate. People who need it can pick it up from here.

kendfss commented 2 years ago

Fairs. Also, probably worth noting, the directory for installing man pages differs on osx and the following would account for that:

ifeq ($(shell uname),Linux)
    MANDIR ?= $(PREFIX)/man/man1
endif
ifeq ($(shell uname),Darwin)
    MANDIR ?= $(PREFIX)/share/man/man1
endif

Never could seem to snoop out a clear answer for windows, but if you're interested here's the formatting for powershell (not sure what converter would do the job atm): http://kevinpelgrims.com/blog/2010/05/10/add-help-to-your-own-powershell-scripts/