I want to insert certain Unicode symbol at current cursor position when Control-L is pressed. How to achieve this in Geany? (symbol ロ for example)
Had a similar desire. Here is a solution that makes use of the GeanyPy plugin:
Install and enable GeanyPy plugin that allows you to write Python plugins for Geany (this is available as geany-plugin-py in Ubuntu 16.04).
Place the following in your plugin directory (for me this was ~/.config/geany/plugins/):
# -*- coding: utf-8 -*-
import gtk
import geany
class InsertSymbols(geany.Plugin):
__plugin_name__ = "InsertSymbols"
__plugin_version__ = "0.1"
__plugin_description__ = "Insert symbols e.g. unicode"
__plugin_author__ = "klimaat"
chars = ['°', '×', '²', '³', '±', 'µ', '·', 'ロ']
def __init__(self):
self.symbol_menuitem = gtk.MenuItem("Insert Symbol")
self.symbol_menuitem.show()
symbol_submenu = gtk.Menu()
self.symbol_menuitem.set_submenu(symbol_submenu)
for char in self.chars:
char_item = gtk.MenuItem(char)
char_item.show()
char_item.connect("activate", self.on_insert_symbol_clicked)
symbol_submenu.append(char_item)
geany.main_widgets.tools_menu.append(self.symbol_menuitem)
def cleanup(self):
self.symbol_menuitem.destroy()
def on_insert_symbol_clicked(self, data):
char = data.get_label()
doc = geany.document.get_current()
if doc:
pos = doc.editor.scintilla.get_current_position()
doc.editor.scintilla.insert_text(char)
doc.editor.scintilla.set_current_position(pos+2)
You should now have a "Insert Symbol" item under "Tools".
Probably much better ways to do it...
Macros Plugin helped. It allows to assign a Control-L key, and it has a command to insert any text at cursor. Took some time to figure, but not difficult.
Related
I am converting an org file to Markdown (specifically commonmark). I am adding a custom attribute to my code blocks, which the commonmark writer does not support, and strips them from the code block during conversion. I am trying to find a way to keep my custom attributes.
This is what I have:
#+begin_src python :hl_lines "2"
def some_function():
print("foo bar")
return
#+end_src
This is what I want in my .md file:
``` python hl_lines="2"
def some_function():
print("foo bar")
return
```
After doing some research, I think a filter can solve my issue: I am now playing with panflute, a python lib for writing pandoc filters.
I found some relevant questions, but they apply to other conversions (rST -> html, rst -> latex) and I don't know enough Lua to translate the code into Python and the org -> md conversion.
Thanks for any help.
I was able to write a script, posting it here for future Python-based questions about pandoc filters.
The filter below requires panflute, but there are other libs for pandoc filters in Python.
import panflute
def keep_attributes_markdown(elem, doc, format="commonmark"):
"""Keep custom attributes specified in code block headers when exporting to Markdown"""
if type(elem) == panflute.CodeBlock:
language = "." + elem.classes[0]
attributes = ""
attributes = " ".join(
[key + "=" + value for key, value in elem.attributes.items()]
)
header = "``` { " + " ".join([language, attributes]).strip() + " }"
panflute.debug(header)
code = elem.text.strip()
footer = "```"
content = [
panflute.RawBlock(header, format=format),
panflute.RawBlock(code, format=format),
panflute.RawBlock(footer, format=format),
]
return content
def main(doc=None):
return panflute.run_filter(keep_attributes_markdown, doc=doc)
if __name__ == "__main__":
main()
You can now run the following command:
pandoc --from=org --to=commonmark --filter=/full/path/to/keep_attributes_markdown.py --output=target_file.md your_file.org
Let's say I'm writing a custom editor for my RestructuredText/Sphinx stuff, with "live" html output preview. Output is built using Sphinx.
The source files are pure RestructuredText. No code there.
One desirable feature would be that right-clicking on some part of the preview opens the editor at the correct line of the source file.
To achieve that, one way would be to put that line number in every tag of the html file, for example using classes (e.g., class = "... lineno-124"). Or use html comments.
Note that I don't want to add more content to my source files, just that the line number be included everywhere in the output.
An approximate line number would be enough.
Someone knows how to do this in Sphinx, my way or another?
I decided to add <a> tags with a specific class "lineno lineno-nnn" where nnn is the line number in the RestructuredText source.
The directive .. linenocomment:: nnn is inserted before each new block of unindented text in the source, before the actual parsing (using a 'source-read' event hook).
linenocomment is a custom directive that pushes the <a> tag at build time.
Half a solution is still a solution...
import docutils.nodes as dn
from docutils.parsers.rst import Directive
class linenocomment(dn.General,dn.Element):
pass
def visit_linenocomment_html(self,node):
self.body.append(self.starttag(node,'a',CLASS="lineno lineno-{}".format(node['lineno'])))
def depart_linenocomment_html(self,node):
self.body.append('</a>')
class LineNoComment(Directive):
required_arguments = 1
optional_arguments = 0
has_content = False
add_index = False
def run(self):
node = linenocomment()
node['lineno'] = self.arguments[0]
return [node]
def insert_line_comments(app, docname, source):
print(source)
new_source = []
last_line_empty = True
lineno = 0
for line in source[0].split('\n'):
if line.strip() == '':
last_line_empty = True
new_source.append(line)
elif line[0].isspace():
new_source.append(line)
last_line_empty = False
elif not last_line_empty:
new_source.append(line)
else:
last_line_empty = False
new_source.append('.. linenocomment:: {}'.format(lineno))
new_source.append('')
new_source.append(line)
lineno += 1
source[0] = '\n'.join(new_source)
print(source)
def setup(app):
app.add_node(linenocomment,html=(visit_linenocomment_html,depart_linenocomment_html))
app.add_directive('linenocomment', LineNoComment)
app.connect('source-read',insert_line_comments)
return {
'version': 0.1
}
TL,DR: From a Sphinx extension, how do I tell sphinx-build to treat an additional file as a dependency? In my immediate use case, this is the extension's source code, but the question could equally apply to some auxiliary file used by the extension.
I'm generating documentation with Sphinx using a custom extension. I'm using sphinx-build to build the documentation. For example, I use this command to generate the HTML (this is the command in the makefile generated by sphinx-quickstart):
sphinx-build -b html -d _build/doctrees . _build/html
Since my custom extension is maintained together with the source of the documentation, I want sphinx-build to treat it as a dependency of the generated HTML (and LaTeX, etc.). So whenever I change my extension's source code, I want sphinx-build to regenerate the output.
How do I tell sphinx-build to treat an additional file as a dependency? That is not mentioned in the toctree, since it isn't part of the source. Logically, this should be something I do from my extension's setup function.
Sample extension (my_extension.py):
from docutils import nodes
from docutils.parsers.rst import Directive
class Foo(Directive):
def run(self):
node = nodes.paragraph(text='Hello world\n')
return [node]
def setup(app):
app.add_directive('foo', Foo)
Sample source (index.rst):
.. toctree::
:maxdepth: 2
.. foo::
Sample conf.py (basically the output of sphinx-quickstart plus my extension):
import sys
import os
sys.path.insert(0, os.path.abspath('.'))
extensions = ['my_extension']
templates_path = ['_templates']
source_suffix = '.rst'
master_doc = 'index'
project = 'Hello directive'
copyright = '2019, Gilles'
author = 'Gilles'
version = '1'
release = '1'
language = None
exclude_patterns = ['_build']
pygments_style = 'sphinx'
todo_include_todos = False
html_theme = 'alabaster'
html_static_path = ['_static']
htmlhelp_basename = 'Hellodirectivedoc'
latex_elements = {
}
latex_documents = [
(master_doc, 'Hellodirective.tex', 'Hello directive Documentation',
'Gilles', 'manual'),
]
man_pages = [
(master_doc, 'hellodirective', 'Hello directive Documentation',
[author], 1)
]
texinfo_documents = [
(master_doc, 'Hellodirective', 'Hello directive Documentation',
author, 'Hellodirective', 'One line description of project.',
'Miscellaneous'),
]
Validation of a solution:
Run make html (or sphinx-build as above).
Modify my_extension.py to replace Hello world by Hello again.
Run make html again.
The generated HTML (_build/html/index.html) must now contain Hello again instead of Hello world.
It looks like the note_dependency method in the build environment API should do what I want. But when should I call it? I tried various events but none seemed to hit the environment object in the right state. What did work was to call it from a directive.
import os
from docutils import nodes
from docutils.parsers.rst import Directive
import sphinx.application
class Foo(Directive):
def run(self):
self.state.document.settings.env.note_dependency(__file__)
node = nodes.paragraph(text='Hello done\n')
return [node]
def setup(app):
app.add_directive('foo', Foo)
If a document contains at least one foo directive, it'll get marked as stale when the extension that introduces this directive changes. This makes sense, although it could get tedious if an extension adds many directives or makes different changes. I don't know if there's a better way.
Inspired by Luc Van Oostenryck's autodoc-C.
As far as I know app.env.note_dependency can be called within the doctree-read to add any file as a dependency to the document currently being read.
So in your use case, I assume this would work:
from typing import Any, Dict
from sphinx.application import Sphinx
import docutils.nodes as nodes
def doctree-read(app: Sphinx, doctree: nodes.document):
app.env.note_dependency(file)
def setup(app: Sphinx):
app.connect("doctree-read", doctree-read)
Sphinx can define themes as well as a pygments style to use.
I couldn't however - find a good way for a Sphinx project to define a custom style (color scheme) for pygments to use.
From the docs:
To make the style usable for Pygments, you must
either register it as a plugin (see the plugin docs)
or drop it into the styles subpackage of your Pygments distribution one style class per style, where the file name is the style name and the class name is StylenameClass.
From what I can tell the first option is what I'm after since it should be possible to extend pygments dynamically. Although from checking the link I'm not sure how this would be done (no examples of how to use the plugin system).
The second example involves copying files into pygments which isn't practical especially since the path may not be writable by the user.
I did manage to hack in a style, although it's not a nice solution:
including for completeness
# Sphinx "conf.py"
# Master toctree document
master_doc = 'contents'
# BEGIN MONKEY-PATCH
from pygments.style import Style
from pygments.token import Text, Other, Comment, Whitespace
class MyFancyStyle(Style):
background_color = "#1e1e27"
default_style = ""
styles = {
Text: "#cfbfad",
Other: "#cfbfad",
Whitespace: "#434357",
Comment: "#cd8b00",
Comment.Preproc: "#409090",
Comment.PreprocFile: "bg:#404040 #ffcd8b",
Comment.Special: "#808bed",
# ... snip (just more colors, you get the idea) ...
}
def pygments_monkeypatch_style(mod_name, cls):
import sys
import pygments.styles
cls_name = cls.__name__
mod = type(__import__("os"))(mod_name)
setattr(mod, cls_name, cls)
setattr(pygments.styles, mod_name, mod)
sys.modules["pygments.styles." + mod_name] = mod
from pygments.styles import STYLE_MAP
STYLE_MAP[mod_name] = mod_name + "::" + cls_name
pygments_monkeypatch_style("my_fancy_style", MyFancyStyle)
pygments_style = "my_fancy_style"
# END MONKEY-PATCH
In your conf.py specify the Pygments style you want to use. From the Sphinx documentation:
pygments_style
The style name to use for Pygments highlighting of source code. If not set, either the theme’s default style or 'sphinx' is selected for HTML output.
Available names can be retrieved by:
>>> from pygments.styles import get_all_styles
>>> styles = list(get_all_styles())
An online preview of some Sphinx theme and Pygments style combinations is available.
If out-of-the-box Pygments styles are not to your liking, then you can create a custom Pygments style.
This is how I set it up:
Folder Structure:
docs
├── source
│ ├── conf.py <--
│ ├── _pygments
│ │ ├── style.py <--
│ ├── _static
│ ├── ...
conf.py
(at the very top)
import sys, os
sys.path.append(os.path.abspath("./_pygments"))
pygments_style = 'style.MonokaiStyle'
...
style.py
from pygments.style import Style
from pygments.token import Keyword, Name, Comment, String, Error, Text, \
Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
class MonokaiStyle(Style):
"""
This style mimics the Monokai color scheme.
"""
background_color = "#272822"
highlight_color = "#49483e"
styles = {
# No corresponding class for the following:
Text: "#f8f8f2", # class: ''
Whitespace: "", # class: 'w'
Error: "#960050 bg:#1e0010", # class: 'err'
Other: "", # class 'x'
...
}
You can choose a predefined style here (as I did) and put the corresponding *.py file from the official pygment repo into the _pygment folder. Or you can define your own style, renaming the class to your liking (don't forget to adapt the import clause in conf.py to the new names)
EDIT: This is an even better resource for style lookup.
I had a similar need, though what I really wanted was to slightly change an existing style (called the base style below). I was able to extent the code in the question for my needs. I post it here for anyone else coming across this problem.
# Sphinx "conf.py"
# Syntax highlighting of code blocks
import pygments.styles, pygments.token
def monkeypatch_pygments(name, base_name='default', attrs={}):
import importlib, sys
base_module = importlib.import_module('.'.join(['pygments', 'styles', base_name]))
def name_to_class_name(name):
return name.capitalize() + 'Style'
base_class = getattr(base_module, name_to_class_name(base_name))
styles = getattr(base_class, 'styles', {}).copy()
styles.update(attrs.pop('styles', {}))
attrs['styles'] = styles
class_name = name_to_class_name(name)
Style = type(class_name, (base_class,), attrs)
module = type(base_module)(name)
setattr(module, class_name, Style)
setattr(pygments.styles, name, module)
pygments.styles.STYLE_MAP[name] = f'{name}::{class_name}'
sys.modules['.'.join(['pygments', 'styles', name])] = module
pygments_style = 'custom' # Arbitrary name of new style
monkeypatch_pygments(
pygments_style,
'friendly', # Name of base style to use
{
# Changes to base style
'background_color': '#f6f6f6',
'styles': {
pygments.token.Comment: 'italic #688F98',
pygments.token.Name.Variable: '#d27a0a',
},
},
)
In the above example, the friendly style is used as the base style. Its 'background_color' and a few items within the 'styles' dictionary are redefined. Note that items not specified in 'styles' will be taken from the base style. The base style itself is not changed.
The "proper" way to include a pygments style as a plugin is to make a new package and install it via setuptools.
Use the usual process to create a setup.cfg (https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html)
Add the following section to it:
[options.entry_points]
pygments.styles =
my_fancy_style = mypackage.mystyle:MyFancyStyle
Create your style as class MyFancyStyle in mypackage/mystyle.py
Install the package: pip install -e .
Profit! You can now refer use "my_fancy_style" anywhere a Pygments style is expected. Phew.
I adopt the solution of Glades and it works well, except in the case that the style-python package is installed (style-1.1.0 in my case).
It lead to the ERROR (sorry for the part of french in the ouput) :
Une exception a été levée :
File "/home/bp/.local/lib/python3.8/site-packages/style/styled_string_builder.py", line 44, in __getattr__
raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
AttributeError: '_StyledStringBuilder' object has no attribute 'MonokaiStyle'
Only solution I find is just to uninstall this package named style :
$ pip uninstall style
First off, I am a complete beginner with Python and I'm working my way through Zed Shaw's latest edition of Learn Python 3 the Hard Way. Im stuck on ex 23 String, Bytes, and Character Encoding. I can't get the program to run at all in the OSX terminal. When I attempt run the program it just returns zero information.
Here is a link to the screenshot of my terminal after I attempt to run the program.( Apparently i'm too much of a noob to embed my image lol.)
OSX python3.6 ex23.py
import sys
script, input_encoding, error = sys.argv
def main(language_file, encoding, errors):
line = language_file.readline()
if line:
print_line(line, encoding, errors)
return main(language_file, encoding, errors)
def print_line(line, encoding, errors):
next_lang = line.strip()
raw_bytes = next_lang.encode(encoding, errors=errors)
cooked_string = raw_bytes.decode(encoding, error=errors)
print(raw_bytes, "<===>", cooked_string)
languages = open("languages.txt", encoding="utf-8")
main(languages, input_encoding, error)
Why is this not running? What's going on?
Are you sure it is not just incorrect indentation? Python uses indentation instead of braces to structure its programs. Looking at your code, it seems that you have extra indentations, try this:
import sys
script, input_encoding, error = sys.argv
def main(language_file, encoding, errors):
line = language_file.readline()
if line:
print_line(line, encoding, errors)
return main(language_file, encoding, errors)
def print_line(line, encoding, errors):
next_lang = line.strip()
raw_bytes = next_lang.encode(encoding, errors=errors)
cooked_string = raw_bytes.decode(encoding, errors=errors)
print(raw_bytes, "<===>", cooked_string)
languages = open("languages.txt", encoding="utf-8")
main(languages, input_encoding, error)