commit 9dcd4757168e7121500d31fcd554ce0c25a44af2 Author: Rudis Muiznieks Date: Sat Sep 4 17:25:04 2021 -0500 initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a6274f5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.{lua,pl}] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..9bd275e --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# telescope-dict.nvim + +A [Telescope](https://github.com/nvim-telescope/telescope.nvim) extension that loads a list of synonyms for the word under the cusor in the current buffer, and shows their definition in the preview window. Selecting one of the synonyms replaces the word in the buffer. + +## Requirements + +These should be available through your package manager (or likely already installed, in the case of `perl`): + +- `perl` +- `dictd`: dictionary server + - `dict-wn`: WordNet dictionary for `dictd` + - `dict-moby-thesaurus`: Moby Thesaurus dictionary for `dictd` + +## Usage + +Install with packer (or similar equivalent package manager): + +```lua +use 'rudism/telescope-dict.nvim' +``` + +Bind this to a key and execute it to open the synonym list for the word currently under the cursor: + +```lua +require('telescope').extensions.dict.synonyms() +``` diff --git a/lua/telescope/_extensions/cmd.pl b/lua/telescope/_extensions/cmd.pl new file mode 100644 index 0000000..6171e96 --- /dev/null +++ b/lua/telescope/_extensions/cmd.pl @@ -0,0 +1,90 @@ +#!/usr/bin/env perl + +# script that parses the following dictd output: +# arg1=synonyms: moby-thesaurus +# - one word per line +# arg1=definitions: wn +# - one definition per line separated by blank lines + +use warnings; +use strict; +use Data::Dumper qw(Dumper); + +my ($cmd, $word) = (shift, shift); +my $qword = quotemeta($word); + +if ($cmd eq 'synonyms') { + open(my $fh, '-|', "dict -d moby-thesaurus $qword 2>/dev/null"); + my $first = 1; + while (my $line = <$fh>) { + chomp($line); + if ($line =~ /^ /) { + $line =~ s/^\s+//; + $line =~ s/[\s,]*$//; + my @words = split(/\s*,\s*/, $line); + foreach my $word (@words) { + if ($first) { + $first = 0; + } else { + print "\n"; + } + print $word; + } + } + } + close($fh); +} + +elsif ($cmd eq 'definitions') { + open(my $fh, '-|', "dict -d wn $qword 2>/dev/null"); + my $defsraw = ''; + while (my $line = <$fh>) { + if ($line =~ /^ {6}/) { + $defsraw .= $line; + } + } + close($fh); + my @defs = split(/\n (?=[a-z]* ?\d+: )/, $defsraw); + my $curtype; + my $defmap = {}; + my ($biggest, $count) = (0, 0); + my @deftypes = (); + foreach my $def (@defs) { + my $line = $def; + if ($line) { + $line =~ s/(^\s+|\s+$)//g; + $line =~ s/\s*\n\s*/ /g; + if ($line =~ /^(([^0-9]+) )?(\d+): (.*?)( \[.*)?$/) { + my ($type, $num, $desc, $meta) = ($2, $3, $4, $5); + if ($type) { + $curtype = $type; + $defmap->{$curtype} = []; + push @deftypes, $type; + $count = 0; + } + next if !$curtype; + push @{$defmap->{$curtype}}, { + desc => $desc, + meta => $meta}; + $count++; + if ($count > $biggest) { + $biggest = $count; + } + } + } + } + my $first = 1; + for (my $i = 0; $i < $biggest; $i++) { + foreach my $key (@deftypes) { + if($defmap->{$key}->[$i]) { + my $desc = $defmap->{$key}->[$i]->{desc}; + if ($first) { + $first = 0; + } else { + print "\n\n"; + } + print "$key: $desc"; + } + } + } +} diff --git a/lua/telescope/_extensions/dict.lua b/lua/telescope/_extensions/dict.lua new file mode 100644 index 0000000..b0e3903 --- /dev/null +++ b/lua/telescope/_extensions/dict.lua @@ -0,0 +1,64 @@ +local telescope = require('telescope') +local pickers = require('telescope.pickers') +local finders = require('telescope.finders') +local sorters = require('telescope.sorters') +local previewers = require('telescope.previewers') +local previewer_utils = require('telescope.previewers.utils') +local actions = require('telescope.actions') +local action_state = require('telescope.actions.state') + +function script_path() + local str = debug.getinfo(2, "S").source:sub(2) + return str:match("(.*/)") +end + +function upper_first(word) + return word:gsub("(%a)([%w_']*)", function(first, rest) return first:upper()..rest:lower() end) +end + +return telescope.register_extension { + exports = { + synonyms = function(opts) + opts = opts or {} + local cursor_word = vim.fn.expand("") + local command = table.concat({ + "perl ", + script_path().."/cmd.pl ", + "synonyms ", + vim.fn.shellescape(cursor_word) + }) + local synonyms = vim.fn.systemlist(command) or {} + table.insert(synonyms, cursor_word:lower()) + pickers.new(opts, { + prompt_title = upper_first(cursor_word).." Synonyms", + finder = finders.new_table { + results = synonyms, + }, + sorter = sorters.get_substr_matcher(), + previewer = previewers.new_buffer_previewer({ + define_preview = function(self, entry, status) + vim.api.nvim_win_set_option(self.state.winid, 'wrap', true) + vim.api.nvim_win_set_option(self.state.winid, 'lbr', true) + local cmd = { "perl", script_path().."/cmd.pl", "definitions", entry.value } + return previewer_utils.job_maker(cmd, self.state.bufnr, { + callback = function(bufnr, content) + previewer_utils.highlighter(bufnr, 'yaml') + end + }) + end, + title = "Definition" + }), + dynamic_preview_title = true, + attach_mappings = function(prompt_bufnr) + actions.select_default:replace(function() + local selection = action_state.get_selected_entry() + actions.close(prompt_bufnr) + vim.cmd("normal! ciw" .. selection[1]) + vim.cmd "stopinsert" + end) + return true + end, + }):find() + end + } +}